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 :: init_parallelization => multisystem_init_parallelization
81 procedure :: next_time_on_largest_dt => multisystem_next_time_on_largest_dt
82 procedure :: reset_iteration_counters => multisystem_reset_iteration_counters
83 procedure :: new_algorithm => multisystem_new_algorithm
84 procedure :: algorithm_finished => multisystem_algorithm_finished
85 procedure :: init_iteration_counters => multisystem_init_iteration_counters
86 procedure :: add_partners_to_list => multisystem_add_partners_to_list
87 procedure :: create_interactions => multisystem_create_interactions
88 procedure :: algorithm_start => multisystem_algorithm_start
89 procedure :: algorithm_finish => multisystem_algorithm_finish
90 procedure :: init_interaction => multisystem_init_interaction
91 procedure :: write_interaction_graph => multisystem_write_interaction_graph
92 procedure :: initialize => multisystem_initialize
93 procedure :: do_algorithmic_operation => multisystem_do_algorithmic_operation
94 procedure :: is_tolerance_reached => multisystem_is_tolerance_reached
95 procedure :: update_quantity => multisystem_update_quantity
96 procedure :: init_interaction_as_partner => multisystem_init_interaction_as_partner
97 procedure :: copy_quantities_to_interaction => multisystem_copy_quantities_to_interaction
98 procedure :: process_is_slave => multisystem_process_is_slave
99 procedure :: start_barrier => multisystem_start_barrier
100 procedure :: end_barrier => multisystem_end_barrier
101 procedure :: arrived_at_barrier => multisystem_arrived_at_barrier
102 procedure :: restart_write => multisystem_restart_write
103 procedure :: restart_read => multisystem_restart_read
104 procedure :: restart_write_data => multisystem_restart_write_data
105 procedure :: restart_read_data => multisystem_restart_read_data
106 procedure :: update_kinetic_energy => multisystem_update_kinetic_energy
107 procedure :: update_potential_energy => multisystem_update_potential_energy
108 procedure :: update_internal_energy => multisystem_update_internal_energy
109 procedure :: get_flat_list => multisystem_get_flat_list
110 end type multisystem_t
111
112contains
113
114 ! ---------------------------------------------------------------------------------------
117 recursive subroutine multisystem_init_parallelization(this, grp)
118 class(multisystem_t), intent(inout) :: this
119 type(mpi_grp_t), intent(in) :: grp
120
121 type(system_iterator_t) :: iter
122 class(system_t), pointer :: sys
123 type(mpi_grp_t) :: sys_grp
124
126
127 call system_init_parallelization(this, grp)
128
129 ! Now parallelize over systems in this multisystem
130 call iter%start(this%list)
131 do while (iter%has_next())
132 sys => iter%get_next()
133 ! for now, duplicate communicator - more complicated parallelization schemes can be implemented here
134 call mpi_grp_duplicate(sys_grp, grp)
135 call sys%init_parallelization(sys_grp)
136 end do
140
141 ! ---------------------------------------------------------------------------------------
142 recursive function multisystem_next_time_on_largest_dt(this) result(next_time_on_largest_dt)
143 class(multisystem_t), intent(inout) :: this
144 real(real64) :: next_time_on_largest_dt
145
146 type(system_iterator_t) :: iter
147 class(system_t), pointer :: system
148 type(iteration_counter_t) :: iteration
149
151
152 next_time_on_largest_dt = m_zero
153 call iter%start(this%list)
154 do while (iter%has_next())
155 system => iter%get_next()
156 select type (system)
157 class is (multisystem_t)
158 next_time_on_largest_dt = max(next_time_on_largest_dt, system%next_time_on_largest_dt())
159 class default
160 iteration = system%iteration + 1
161 next_time_on_largest_dt = max(next_time_on_largest_dt, iteration%value())
162 end select
163 end do
164
167
168 ! ---------------------------------------------------------------------------------------
169 recursive subroutine multisystem_execute_algorithm(this)
170 class(multisystem_t), intent(inout) :: this
171
172 type(system_iterator_t) :: iter
173 class(system_t), pointer :: system
175 type(event_handle_t) :: debug_handle
179 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_dt_operation"), &
180 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
182 ! Multisystem
185 ! Subsystems
186 call iter%start(this%list)
187 do while (iter%has_next())
188 system => iter%get_next()
189 call system%execute_algorithm()
190 end do
192 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
197 ! ---------------------------------------------------------------------------------------
198 recursive subroutine multisystem_reset_iteration_counters(this, accumulated_iterations)
199 class(multisystem_t), intent(inout) :: this
200 integer, intent(in) :: accumulated_iterations
202 type(system_iterator_t) :: iter
203 class(system_t), pointer :: system
204
206
207 ! Multisystem iteration counters
208 call system_reset_iteration_counters(this, accumulated_iterations)
209
210 ! Subsystems iteration counters
211 call iter%start(this%list)
212 do while (iter%has_next())
213 system => iter%get_next()
214 call system%reset_iteration_counters(accumulated_iterations)
215 end do
216
219
220 ! ---------------------------------------------------------------------------------------
221 recursive subroutine multisystem_new_algorithm(this, factory)
222 class(multisystem_t), intent(inout) :: this
223 class(algorithm_factory_t), intent(in) :: factory
224
225 type(system_iterator_t) :: iter
226 class(system_t), pointer :: system
227
229
230 ! Now initialized the algorithms of the subsystems
231 call iter%start(this%list)
232 do while (iter%has_next())
233 system => iter%get_next()
234 call system%new_algorithm(factory)
235 end do
236
237 ! Initialize the algorithm of the multisystem. By default the
238 ! multisystem itself and its own quantities are kept unchanged
239 ! by using the static propagator. However, the subsystems are allowed to have
240 ! their own propagators and those do not have to be static.
241 ! Needs to be done after initializing the subsystems propagators,
242 ! as we use the largest dt of the subsystems.
243 this%algo => factory%create_static(this)
244 call this%algo%rewind()
245
247
249 end subroutine multisystem_new_algorithm
250
251 ! ---------------------------------------------------------------------------------------
252 recursive function multisystem_algorithm_finished(this) result(finished)
253 class(multisystem_t), intent(in) :: this
254 logical :: finished
255
256 type(system_iterator_t) :: iter
257 class(system_t), pointer :: system
258
259 ! Check if multisystem itself is finished
260 finished = this%algo%finished()
261
262 ! Check subsystems
263 call iter%start(this%list)
264 do while (iter%has_next())
265 system => iter%get_next()
266 finished = finished .and. system%algorithm_finished()
267 end do
268
270
271 ! ---------------------------------------------------------------------------------------
274 recursive subroutine multisystem_init_iteration_counters(this)
275 class(multisystem_t), intent(inout) :: this
276
277 type(system_iterator_t) :: iter
278 class(system_t), pointer :: system
279
281
282 ! initialize multisystem iteration counters
284
285 ! initialize iteration counters of subsystems
286 call iter%start(this%list)
287 do while (iter%has_next())
288 system => iter%get_next()
289 call system%init_iteration_counters()
290 end do
294
295 ! ---------------------------------------------------------------------------------------
298 recursive subroutine multisystem_algorithm_start(this)
299 class(multisystem_t), intent(inout) :: this
300
301 type(system_iterator_t) :: iter
302 class(system_t), pointer :: system
303
304 type(event_handle_t) :: debug_handle
305
307
308 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_algorithm_start"), &
309 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
310
311 ! Now start the execution of the subsystems
312 call iter%start(this%list)
313 do while (iter%has_next())
314 system => iter%get_next()
315 call system%algorithm_start()
316 end do
317
318 ! Once the subsystems are initialized start the propagation of the multisystem
319 call system_algorithm_start(this)
320
321 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
322
324 end subroutine multisystem_algorithm_start
325
326 ! ---------------------------------------------------------------------------------------
329 recursive subroutine multisystem_algorithm_finish(this)
330 class(multisystem_t), intent(inout) :: this
331
332 type(system_iterator_t) :: iter
333 class(system_t), pointer :: system
334
335 type(event_handle_t) :: debug_handle
336
338
339 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_algorithm_finish"), &
340 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
341
342 ! Finish the execution of the multisystem
343 call system_algorithm_finish(this)
344
345 ! Now finish the execution of the subsystems
346 call iter%start(this%list)
347 do while (iter%has_next())
348 system => iter%get_next()
349 call system%algorithm_finish()
350 end do
351
352 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
353
355 end subroutine multisystem_algorithm_finish
356
357 ! ---------------------------------------------------------
365 recursive subroutine multisystem_add_partners_to_list(this, list, interaction_type)
366 class(multisystem_t), intent(in) :: this
367 class(partner_list_t), intent(inout) :: list
368 integer, optional, intent(in) :: interaction_type
369
370 type(system_iterator_t) :: iter
371 class(system_t), pointer :: system
372
373 if (present(interaction_type)) then
374 if (any(this%supported_interactions_as_partner == interaction_type)) then
375 call list%add(this)
376 end if
377 else
378 call list%add(this)
379 end if
380
381 call iter%start(this%list)
382 do while (iter%has_next())
383 system => iter%get_next()
384 call system%add_partners_to_list(list, interaction_type)
385 end do
386
388
389 ! ---------------------------------------------------------
397
398 recursive subroutine multisystem_create_interactions(this, interaction_factory, available_partners)
399 class(multisystem_t), intent(inout) :: this
400 class(interactions_factory_abst_t), intent(in) :: interaction_factory
401 class(partner_list_t), target, intent(in) :: available_partners
402
403 type(system_iterator_t) :: iter
404 class(system_t), pointer :: subsystem
405
406 ! Create the multisystem interactions
407 call system_create_interactions(this, interaction_factory, available_partners)
408
409 ! Create the subsystems interactions
410 call iter%start(this%list)
411 do while (iter%has_next())
412 subsystem => iter%get_next()
413 call subsystem%create_interactions(interaction_factory, available_partners)
414 end do
415
417
418 ! ---------------------------------------------------------
424
425 subroutine multisystem_init_interaction(this, interaction)
426 class(multisystem_t), target, intent(inout) :: this
427 class(interaction_t), intent(inout) :: interaction
428
430
431 ! The multisystem class should never know about any specific interaction.
432 ! Only classes that extend it can know about specific interactions.
433 ! Such classes should override this method to add new supported interactions.
434 message(1) = "Trying to initialize an interaction in the multi-system container class"
435 call messages_fatal(1, namespace=this%namespace)
436
438 end subroutine multisystem_init_interaction
439
440 ! ---------------------------------------------------------------------------------------
443 recursive subroutine multisystem_write_interaction_graph(this, iunit, include_ghosts)
444 class(multisystem_t), intent(in) :: this
445 integer, intent(in) :: iunit
446 logical, intent(in) :: include_ghosts
447
448 class(system_t), pointer :: system
449 class(interaction_t), pointer :: interaction
450 type(system_iterator_t) :: sys_iter
451 type(interaction_iterator_t) :: inter_iter
452
454
455 ! Loop over all the subsystems
456 call sys_iter%start(this%list)
457 do while (sys_iter%has_next())
458 system => sys_iter%get_next()
459
460 ! Loop over the interactions that this subsystem has
461 call inter_iter%start(system%interactions)
462 do while (inter_iter%has_next())
463 interaction => inter_iter%get_next()
464
465 ! Write interaction to DOT graph if this interaction has a partner
466 select type (interaction)
467 type is (ghost_interaction_t)
468 if (include_ghosts) then
469 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
470 '" [label="'+ interaction%label + '"];'
471 end if
472 ! Do not include systems connected by ghost interactions
473 class default
474 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
475 '" [label="'+ interaction%label + '"];'
476 end select
477 end do
478
479 ! If this subsystem is also a multisystem, then we also need to traverse it
480 select type (system)
481 class is (multisystem_t)
482 call system%write_interaction_graph(iunit, include_ghosts)
483 end select
484 end do
485
488
489 ! ---------------------------------------------------------
490 recursive subroutine multisystem_initialize(this)
491 class(multisystem_t), intent(inout) :: this
492
493 type(system_iterator_t) :: iter
494 class(system_t), pointer :: system
495
496 push_sub(multisystem_initialize)
497
498 call iter%start(this%list)
499 do while (iter%has_next())
500 system => iter%get_next()
501 call system%initialize()
502 end do
503
505 end subroutine multisystem_initialize
506
507 ! ---------------------------------------------------------
508 logical function multisystem_do_algorithmic_operation(this, operation, updated_quantities) result(done)
509 class(multisystem_t), intent(inout) :: this
510 class(algorithmic_operation_t), intent(in) :: operation
511 character(len=:), allocatable, intent(out) :: updated_quantities(:)
512
514
515 ! Currently there are no multisystem specific algorithmic operations
516 done = .false.
517
520
521 ! ---------------------------------------------------------
522 recursive logical function multisystem_is_tolerance_reached(this, tol) result(converged)
523 class(multisystem_t), intent(in) :: this
524 real(real64), intent(in) :: tol
525
526 type(system_iterator_t) :: iter
527 class(system_t), pointer :: system
528
530
531 converged = .true.
532 call iter%start(this%list)
533 do while (iter%has_next())
534 system => iter%get_next()
535 if (.not. system%is_tolerance_reached(tol)) converged = .false.
536 end do
537
540
541 ! ---------------------------------------------------------
542 subroutine multisystem_update_quantity(this, label)
543 class(multisystem_t), intent(inout) :: this
544 character(len=*), intent(in) :: label
545
547
548 ! The multisystem class should never know about any specific quantities.
549 ! Only classes that extend it can know about specific quantities.
550 ! Such classes should override this method to add new supported quantities.
551 message(1) = "Trying to update a quantity in the multi-system container class"
552 call messages_fatal(1, namespace=this%namespace)
553
555 end subroutine multisystem_update_quantity
556
557 ! ---------------------------------------------------------
558 subroutine multisystem_init_interaction_as_partner(partner, interaction)
559 class(multisystem_t), intent(in) :: partner
560 class(interaction_surrogate_t), intent(inout) :: interaction
561
563
564 ! The multisystem class should never know about any specific interaction.
565 ! Only classes that extend it can know about specific interactions.
566 ! Such classes should override this method to add new supported interactions.
567 message(1) = "Trying to initialize an interaction as partner in the multi-system container class"
568 call messages_fatal(1, namespace=partner%namespace)
569
572
573 ! ---------------------------------------------------------
574 subroutine multisystem_copy_quantities_to_interaction(partner, interaction)
575 class(multisystem_t), intent(inout) :: partner
576 class(interaction_surrogate_t), intent(inout) :: interaction
577
579
580 ! The multisystem class should never know about any specific quantities.
581 ! Only classes that extend it can know about specific quantities.
582 ! Such classes should override this method to add new supported quantities.
583 message(1) = "Trying to copy quantities to interaction in the multi-system container class"
584 call messages_fatal(1, namespace=partner%namespace)
585
588
589 ! ---------------------------------------------------------
590 recursive logical function multisystem_process_is_slave(this) result(is_slave)
591 class(multisystem_t), intent(in) :: this
592
593 type(system_iterator_t) :: iter
594 class(system_t), pointer :: system
595
597
598 is_slave = .false.
599 call iter%start(this%list)
600 do while (iter%has_next())
601 system => iter%get_next()
602 if (system%process_is_slave()) is_slave = .true.
603 end do
604
607
608 !--------------------------------------------------------------------
612 recursive subroutine multisystem_update_kinetic_energy(this)
613 class(multisystem_t), intent(inout) :: this
614
616
617 ! We currently do not have the center of mass coordinates implemented for multisystems,
618 ! hence we set the kinetic energy to zero.
619 ! The kinetic energies of the constituents are contributing to the internal energy.
620
621 this%kinetic_energy = m_zero
622
625
626 !---------------------------------------------------------
627 recursive subroutine multisystem_update_internal_energy(this)
628 class(multisystem_t), intent(inout) :: this
629
630 class(system_t), pointer :: system
631 class(system_t), pointer :: system_2
632 type(system_iterator_t) :: system_iter
633 type(system_iterator_t) :: system_iter_2
634
636
637 ! The internal energy of the multisystem contains the kinetic and internal energies of the consistuents
638 !TODO: the kinetic energy wrt the center of mass motion should be subtracted.
639
640 this%internal_energy = m_zero
641
642 call system_iter%start(this%list)
643 do while (system_iter%has_next())
644
645 system => system_iter%get_next()
646
647 ! First add the kinetic energies of the subsystems
648 call system%update_kinetic_energy()
649 this%internal_energy = this%internal_energy + system%kinetic_energy
650
651 ! First add the internal energies of the subsystems
652 call system%update_internal_energy()
653 this%internal_energy = this%internal_energy + system%internal_energy
654
655 ! Now add the (inter-) interactions between the systems in the container.
656 call system_iter_2%start(this%list)
657 do while(system_iter_2%has_next())
658
659 system_2 => system_iter_2%get_next()
660
661 ! exclude self-interactions (intra-interactions) as they are included in the internal energy
662 ! of the subsystem, which was already added above.
663 if(.not. associated(system, system_2)) then
664 this%internal_energy = this%internal_energy + multisystem_pair_energy(system, system_2)
665 end if
666 end do ! system_iter_2
668 end do ! system_iter
669
672
673 ! ---------------------------------------------------------
687 class(multisystem_t), intent(inout) :: this
688
689 type(system_iterator_t) :: system_iter
690 class(system_t), pointer :: system
691 type(interaction_iterator_t) :: interaction_iter
692 class(interaction_t), pointer :: interaction
693 type(system_list_t) :: flat_list
694
696
697 this%potential_energy = m_zero
698
699 ! We need to handle interactions of the container itself:
701
702 ! generate a list of all systems inside the container and its subcontainers:
703 call this%get_flat_list(flat_list)
704
705 ! loop over all systems inside the container
706 call system_iter%start(flat_list)
707 do while (system_iter%has_next())
708
709 system => system_iter%get_next()
710
711 ! Even though we are not using the potential energy of the subsystems here, we need to trigger their calculation
712 call system%update_potential_energy()
713
714 ! loop over all interactions and discard those with partners inside the container
715 call interaction_iter%start(system%interactions)
716 do while (interaction_iter%has_next())
717 interaction => interaction_iter%get_next()
718 if(.not. flat_list%contains(interaction%partner) .and. .not. interaction%intra_interaction) then
719 call interaction%calculate_energy()
720 this%potential_energy = this%potential_energy + interaction%energy
721 end if
722 end do
723
724 end do
725
728
729 ! ---------------------------------------------------------
736 recursive real(real64) function multisystem_pair_energy(partner_A, partner_B) result(pair_energy)
737 class(interaction_partner_t), intent(in) :: partner_a
738 class(interaction_partner_t), intent(in) :: partner_b
739
740 class(system_t), pointer :: system_a
741 class(system_t), pointer :: system_b
742 type(system_iterator_t) :: system_iterator_a
743 type(system_iterator_t) :: system_iterator_b
744
746
747 pair_energy = m_zero
748
749 select type(partner_a)
750 class is (multisystem_t) ! partner_A is container
751
752 call system_iterator_a%start(partner_a%list)
753 do while( system_iterator_a%has_next() )
754
755 system_a => system_iterator_a%get_next()
756
757 select type(partner_b)
758 class is (multisystem_t)
759
760 call system_iterator_b%start(partner_b%list)
761 do while( system_iterator_b%has_next() )
762 system_b => system_iterator_b%get_next()
763 pair_energy = pair_energy + multisystem_pair_energy(system_a, system_b)
764 end do
765
766 class is (system_t)
767 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
768 class default
769 assert(.false.) ! partner_A must be a system_t
770 end select
771 end do
772
773 class is (system_t) ! partner_A is non-container system
774
775 select type(partner_b)
776 class is (multisystem_t) ! partner_B is container
777
778 call system_iterator_b%start(partner_b%list)
779 do while( system_iterator_b%has_next() )
780 system_b => system_iterator_b%get_next()
781 pair_energy = pair_energy + multisystem_pair_energy(partner_a, system_b)
782 end do
783
784 class default ! both partner_A and partner_B are explicit: we need to calculate
785 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
786 end select
787
788 class default
789 assert(.false.)
790 end select
791
793
794 contains
795
796 real(real64) function interaction_energy(system, partner) result (energy)
797 class(system_t), target, intent(in) :: system
798 class(interaction_partner_t), target, intent(in) :: partner
799
800 type(interaction_iterator_t) :: interaction_iterator
801 class(interaction_t), pointer :: interaction
802
803 energy = m_zero
804
805 call interaction_iterator%start(system%interactions)
806 do while(interaction_iterator%has_next())
807 interaction => interaction_iterator%get_next()
808 if( associated(interaction%partner, partner)) then
809 call interaction%calculate_energy()
810 energy = energy + interaction%energy
811 end if
812 end do
813 end function interaction_energy
814
815 end function multisystem_pair_energy
816
817
818 ! ---------------------------------------------------------
821 recursive subroutine multisystem_get_flat_list(this, flat_list)
822 class(multisystem_t), intent(in) :: this
823 type(system_list_t), intent(out) :: flat_list
824
825 class(interaction_partner_t), pointer :: partner
826 type(partner_iterator_t) :: iterator
827
830 call iterator%start(this%list)
831 do while (iterator%has_next())
832 partner => iterator%get_next()
833
834 call flat_list%add(partner)
835
836 select type (partner)
837 class is (multisystem_t)
838 ! Also include the subsystems of a multisystem
839 call partner%get_flat_list(flat_list)
840 end select
841
842 end do
843
845
846 end subroutine multisystem_get_flat_list
847
848 ! ---------------------------------------------------------
849 recursive subroutine multisystem_end(this)
850 class(multisystem_t), intent(inout) :: this
851
852 type(system_iterator_t) :: iter
853 class(system_t), pointer :: system
854
855 push_sub(multisystem_end)
856
857 call iter%start(this%list)
858 do while (iter%has_next())
859 system => iter%get_next()
860 if (associated(system)) then
861 deallocate(system)
862 end if
863 end do
864
865 call system_end(this)
866
867 pop_sub(multisystem_end)
868 end subroutine multisystem_end
869
870 ! ---------------------------------------------------------
871 recursive subroutine multisystem_start_barrier(this, target_time, barrier_index)
872 class(multisystem_t), intent(inout) :: this
873 real(real64), intent(in) :: target_time
874 integer, intent(in) :: barrier_index
875
876 type(system_iterator_t) :: iter
877 class(system_t), pointer :: system
878
880
881 call iter%start(this%list)
882 do while (iter%has_next())
883 system => iter%get_next()
884 call system%start_barrier(target_time, barrier_index)
885 end do
886
888 end subroutine multisystem_start_barrier
890 ! ---------------------------------------------------------
891 recursive subroutine multisystem_end_barrier(this, barrier_index)
892 class(multisystem_t), intent(inout) :: this
893 integer, intent(in) :: barrier_index
894
895 type(system_iterator_t) :: iter
896 class(system_t), pointer :: system
897
899
900 call iter%start(this%list)
901 do while (iter%has_next())
902 system => iter%get_next()
903 call system%end_barrier(barrier_index)
904 end do
905
907 end subroutine multisystem_end_barrier
908
909 ! ---------------------------------------------------------
910 recursive logical function multisystem_arrived_at_barrier(this, barrier_index)
911 class(multisystem_t), intent(inout) :: this
912 integer, intent(in) :: barrier_index
913
914 type(system_iterator_t) :: iter
915 class(system_t), pointer :: system
916
918
920 call iter%start(this%list)
921 do while (iter%has_next())
922 system => iter%get_next()
924 system%arrived_at_barrier(barrier_index)
925 end do
926
929
930 ! ---------------------------------------------------------
931 recursive subroutine multisystem_restart_write(this)
932 class(multisystem_t), intent(inout) :: this
933
934 type(system_iterator_t) :: iter
935 class(system_t), pointer :: system
936
938
939 ! do generic restart steps
940 call system_restart_write(this)
941
942 ! loop over all subsystems
943 call iter%start(this%list)
944 do while (iter%has_next())
945 system => iter%get_next()
946 call system%restart_write()
947 end do
948 message(1) = "Wrote restart data for multisystem "//trim(this%namespace%get())
949 call messages_info(1, namespace=this%namespace)
950
952 end subroutine multisystem_restart_write
953
954 ! ---------------------------------------------------------
955 recursive logical function multisystem_restart_read(this)
956 class(multisystem_t), intent(inout) :: this
957
958 type(system_iterator_t) :: iter
959 class(system_t), pointer :: system
960
962
963 ! read generic restart data
964 multisystem_restart_read = system_restart_read(this)
965 call iter%start(this%list)
966 do while (iter%has_next())
967 system => iter%get_next()
968 ! TODO: adapt logics here for consistent restarting
970 system%restart_read()
971 end do
972
974 message(1) = "Successfully read restart data for multisystem "//trim(this%namespace%get())
975 call messages_info(1, namespace=this%namespace)
976 end if
977
979 end function multisystem_restart_read
980
981 ! ---------------------------------------------------------
982 subroutine multisystem_restart_write_data(this)
983 class(multisystem_t), intent(inout) :: this
986
987 ! do not write restart data for multisystem_t
988
990 end subroutine multisystem_restart_write_data
991
992 ! ---------------------------------------------------------
993 ! this function returns true if restart data could be read
994 logical function multisystem_restart_read_data(this)
995 class(multisystem_t), intent(inout) :: this
996
998
1000
1004end 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:141
real(real64), parameter, public m_zero
Definition: global.F90:188
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.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
subroutine mpi_grp_duplicate(mpi_grp_out, mpi_grp_in)
Definition: mpi.F90:413
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_init_parallelization(this, grp)
brief initialize the parallelization of the multisystem
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:138
This module implements the abstract system type.
Definition: system.F90:118
subroutine, public system_algorithm_start(this)
Definition: system.F90:1018
subroutine, public system_init_iteration_counters(this)
Initialize the iteration counters of the system and its interactions, algorithms and quantities.
Definition: system.F90:981
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:1320
subroutine, public system_init_parallelization(this, grp)
Basic functionality: copy the MPI group. This function needs to be implemented by extended types that...
Definition: system.F90:1236
subroutine, public system_algorithm_finish(this)
Definition: system.F90:1070
recursive subroutine, public system_create_interactions(this, interaction_factory, available_partners)
create the interactions of the system
Definition: system.F90:515
subroutine, public system_execute_algorithm(this)
perform one or more algorithmic operations
Definition: system.F90:335
subroutine, public system_reset_iteration_counters(this, accumulated_iterations)
Definition: system.F90:461
Abstract class for the algorithm factories.
Descriptor of one algorithmic operation.
Definition: algorithm.F90:163
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:306
Abstract class for systems.
Definition: system.F90:172
int true(void)