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
61 use system_oct_m
62 implicit none
63
64 private
65 public :: &
68
75 type, extends(system_t), abstract :: multisystem_t
76 type(system_list_t) :: list
77 contains
78 procedure :: execute_algorithm => multisystem_execute_algorithm
79 procedure :: init_parallelization => multisystem_init_parallelization
80 procedure :: next_time_on_largest_dt => multisystem_next_time_on_largest_dt
81 procedure :: reset_iteration_counters => multisystem_reset_iteration_counters
82 procedure :: init_algorithm => multisystem_init_algorithm
83 procedure :: algorithm_finished => multisystem_algorithm_finished
84 procedure :: init_iteration_counters => multisystem_init_iteration_counters
85 procedure :: propagation_start => multisystem_propagation_start
86 procedure :: propagation_finish => multisystem_propagation_finish
87 procedure :: add_partners_to_list => multisystem_add_partners_to_list
88 procedure :: create_interactions => multisystem_create_interactions
89 procedure :: init_interaction => multisystem_init_interaction
90 procedure :: write_interaction_graph => multisystem_write_interaction_graph
91 procedure :: initial_conditions => multisystem_initial_conditions
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 ! ---------------------------------------------------------------------------------------
116 recursive subroutine multisystem_init_parallelization(this, grp)
117 class(multisystem_t), intent(inout) :: this
118 type(mpi_grp_t), intent(in) :: grp
119
120 type(system_iterator_t) :: iter
121 class(system_t), pointer :: sys
122 type(mpi_grp_t) :: sys_grp
123
125
126 call system_init_parallelization(this, grp)
127
128 ! Now parallelize over systems in this multisystem
129 call iter%start(this%list)
130 do while (iter%has_next())
131 sys => iter%get_next()
132 ! for now, duplicate communicator - more complicated parallelization schemes can be implemented here
133 call mpi_grp_duplicate(sys_grp, grp)
134 call sys%init_parallelization(sys_grp)
135 end do
136
139
140 ! ---------------------------------------------------------------------------------------
141 recursive function multisystem_next_time_on_largest_dt(this) result(next_time_on_largest_dt)
142 class(multisystem_t), intent(inout) :: this
143 real(real64) :: next_time_on_largest_dt
144
145 type(system_iterator_t) :: iter
146 class(system_t), pointer :: system
147 type(iteration_counter_t) :: iteration
148
150
151 next_time_on_largest_dt = m_zero
152 call iter%start(this%list)
153 do while (iter%has_next())
154 system => iter%get_next()
155 select type (system)
156 class is (multisystem_t)
157 next_time_on_largest_dt = max(next_time_on_largest_dt, system%next_time_on_largest_dt())
158 class default
159 iteration = system%iteration + 1
160 next_time_on_largest_dt = max(next_time_on_largest_dt, iteration%value())
161 end select
162 end do
163
166
167 ! ---------------------------------------------------------------------------------------
168 recursive subroutine multisystem_execute_algorithm(this)
169 class(multisystem_t), intent(inout) :: this
170
171 type(system_iterator_t) :: iter
172 class(system_t), pointer :: system
174 type(event_handle_t) :: debug_handle
178 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_dt_operation"), &
179 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
181 ! Multisystem
184 ! Subsystems
185 call iter%start(this%list)
186 do while (iter%has_next())
187 system => iter%get_next()
188 call system%execute_algorithm()
189 end do
191 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
196 ! ---------------------------------------------------------------------------------------
197 recursive subroutine multisystem_reset_iteration_counters(this, accumulated_iterations)
198 class(multisystem_t), intent(inout) :: this
199 integer, intent(in) :: accumulated_iterations
201 type(system_iterator_t) :: iter
202 class(system_t), pointer :: system
203
205
206 ! Multisystem iteration counters
207 call system_reset_iteration_counters(this, accumulated_iterations)
208
209 ! Subsystems iteration counters
210 call iter%start(this%list)
211 do while (iter%has_next())
212 system => iter%get_next()
213 call system%reset_iteration_counters(accumulated_iterations)
214 end do
215
218
219 ! ---------------------------------------------------------------------------------------
220 recursive subroutine multisystem_init_algorithm(this, factory)
221 class(multisystem_t), intent(inout) :: this
222 class(algorithm_factory_t), intent(in) :: factory
223
224 type(system_iterator_t) :: iter
225 class(system_t), pointer :: system
226
228
229 ! Now initialized the propagators of the subsystems
230 call iter%start(this%list)
231 do while (iter%has_next())
232 system => iter%get_next()
233 call system%init_algorithm(factory)
234 end do
235
236 ! Initialize the propagator of the multisystem. By default the
237 ! multisystem itself and its own quantities are kept unchanged
238 ! by using the static propagator. However, the subsystems are allowed to have
239 ! their own propagators and those do not have to be static.
240 ! Needs to be done after initializing the subsystems propagators,
241 ! as we use the largest dt of the subsystems.
242 this%algo => factory%create_static(this)
243 call this%algo%rewind()
244
246
248 end subroutine multisystem_init_algorithm
249
250 ! ---------------------------------------------------------------------------------------
251 recursive function multisystem_algorithm_finished(this) result(finished)
252 class(multisystem_t), intent(in) :: this
253 logical :: finished
254
255 type(system_iterator_t) :: iter
256 class(system_t), pointer :: system
257
258 ! Check if multisystem itself is finished
259 finished = this%algo%finished()
260
261 ! Check subsystems
262 call iter%start(this%list)
263 do while (iter%has_next())
264 system => iter%get_next()
265 finished = finished .and. system%algorithm_finished()
266 end do
267
269
270 ! ---------------------------------------------------------------------------------------
273 recursive subroutine multisystem_init_iteration_counters(this)
274 class(multisystem_t), intent(inout) :: this
275
276 type(system_iterator_t) :: iter
277 class(system_t), pointer :: system
278
280
281 ! initialize multisystem iteration counters
283
284 ! initialize iteration counters of subsystems
285 call iter%start(this%list)
286 do while (iter%has_next())
287 system => iter%get_next()
288 call system%init_iteration_counters()
289 end do
293
294 ! ---------------------------------------------------------------------------------------
297 recursive subroutine multisystem_propagation_start(this)
298 class(multisystem_t), intent(inout) :: this
299
300 type(system_iterator_t) :: iter
301 class(system_t), pointer :: system
302
303 type(event_handle_t) :: debug_handle
304
306
307 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_propagation_start"), &
308 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
309
310 ! First start the propagation of the subsystems
311 call iter%start(this%list)
312 do while (iter%has_next())
313 system => iter%get_next()
314 call system%propagation_start()
315 end do
316
317 ! Once the subsystems are initialized start the propagation of the multisystem
318 call system_propagation_start(this)
319
320 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
321
323 end subroutine multisystem_propagation_start
324
325 ! ---------------------------------------------------------------------------------------
328 recursive subroutine multisystem_propagation_finish(this)
329 class(multisystem_t), intent(inout) :: this
330
331 type(system_iterator_t) :: iter
332 class(system_t), pointer :: system
333
334 type(event_handle_t) :: debug_handle
335
337
338 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_propagation_finish"), &
339 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
340
341 ! Finish the propagation of the multisystem
343
344 ! Now finish the propagation of the subsystems
345 call iter%start(this%list)
346 do while (iter%has_next())
347 system => iter%get_next()
348 call system%propagation_finish()
349 end do
350
351 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
352
354 end subroutine multisystem_propagation_finish
355
356 ! ---------------------------------------------------------
364 recursive subroutine multisystem_add_partners_to_list(this, list, interaction_type)
365 class(multisystem_t), intent(in) :: this
366 class(partner_list_t), intent(inout) :: list
367 integer, optional, intent(in) :: interaction_type
368
369 type(system_iterator_t) :: iter
370 class(system_t), pointer :: system
371
372 if (present(interaction_type)) then
373 if (any(this%supported_interactions_as_partner == interaction_type)) then
374 call list%add(this)
375 end if
376 else
377 call list%add(this)
378 end if
379
380 call iter%start(this%list)
381 do while (iter%has_next())
382 system => iter%get_next()
383 call system%add_partners_to_list(list, interaction_type)
384 end do
385
387
388 ! ---------------------------------------------------------
396
397 recursive subroutine multisystem_create_interactions(this, interaction_factory, available_partners)
398 class(multisystem_t), intent(inout) :: this
399 class(interactions_factory_abst_t), intent(in) :: interaction_factory
400 class(partner_list_t), target, intent(in) :: available_partners
401
402 type(system_iterator_t) :: iter
403 class(system_t), pointer :: subsystem
404
405 ! Create the multisystem interactions
406 call system_create_interactions(this, interaction_factory, available_partners)
407
408 ! Create the subsystems interactions
409 call iter%start(this%list)
410 do while (iter%has_next())
411 subsystem => iter%get_next()
412 call subsystem%create_interactions(interaction_factory, available_partners)
413 end do
414
416
417 ! ---------------------------------------------------------
423
424 subroutine multisystem_init_interaction(this, interaction)
425 class(multisystem_t), target, intent(inout) :: this
426 class(interaction_t), intent(inout) :: interaction
427
429
430 ! The multisystem class should never know about any specific interaction.
431 ! Only classes that extend it can know about specific interactions.
432 ! Such classes should override this method to add new supported interactions.
433 message(1) = "Trying to initialize an interaction in the multi-system container class"
434 call messages_fatal(1, namespace=this%namespace)
435
437 end subroutine multisystem_init_interaction
438
439 ! ---------------------------------------------------------------------------------------
442 recursive subroutine multisystem_write_interaction_graph(this, iunit, include_ghosts)
443 class(multisystem_t), intent(in) :: this
444 integer, intent(in) :: iunit
445 logical, intent(in) :: include_ghosts
446
447 class(system_t), pointer :: system
448 class(interaction_t), pointer :: interaction
449 type(system_iterator_t) :: sys_iter
450 type(interaction_iterator_t) :: inter_iter
451
453
454 ! Loop over all the subsystems
455 call sys_iter%start(this%list)
456 do while (sys_iter%has_next())
457 system => sys_iter%get_next()
458
459 ! Loop over the interactions that this subsystem has
460 call inter_iter%start(system%interactions)
461 do while (inter_iter%has_next())
462 interaction => inter_iter%get_next()
463
464 ! Write interaction to DOT graph if this interaction has a partner
465 select type (interaction)
466 type is (ghost_interaction_t)
467 if (include_ghosts) then
468 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
469 '" [label="'+ interaction%label + '"];'
470 end if
471 ! Do not include systems connected by ghost interactions
472 class default
473 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
474 '" [label="'+ interaction%label + '"];'
475 end select
476 end do
477
478 ! If this subsystem is also a multisystem, then we also need to traverse it
479 select type (system)
480 class is (multisystem_t)
481 call system%write_interaction_graph(iunit, include_ghosts)
482 end select
483 end do
484
487
488 ! ---------------------------------------------------------
489 recursive subroutine multisystem_initial_conditions(this)
490 class(multisystem_t), intent(inout) :: this
491
492 type(system_iterator_t) :: iter
493 class(system_t), pointer :: system
494
496
497 call iter%start(this%list)
498 do while (iter%has_next())
499 system => iter%get_next()
500 call system%initial_conditions()
501 end do
502
504 end subroutine multisystem_initial_conditions
505
506 ! ---------------------------------------------------------
507 logical function multisystem_do_algorithmic_operation(this, operation, updated_quantities) result(done)
508 class(multisystem_t), intent(inout) :: this
509 class(algorithmic_operation_t), intent(in) :: operation
510 integer, allocatable, intent(out) :: updated_quantities(:)
511
513
514 ! Currently there are no multisystem specific algorithmic operations
515 done = .false.
516
519
520 ! ---------------------------------------------------------
521 recursive logical function multisystem_is_tolerance_reached(this, tol) result(converged)
522 class(multisystem_t), intent(in) :: this
523 real(real64), intent(in) :: tol
524
525 type(system_iterator_t) :: iter
526 class(system_t), pointer :: system
527
529
530 converged = .true.
531 call iter%start(this%list)
532 do while (iter%has_next())
533 system => iter%get_next()
534 if (.not. system%is_tolerance_reached(tol)) converged = .false.
535 end do
536
539
540 ! ---------------------------------------------------------
541 subroutine multisystem_update_quantity(this, iq)
542 class(multisystem_t), intent(inout) :: this
543 integer, intent(in) :: iq
544
546
547 ! The multisystem class should never know about any specific quantities.
548 ! Only classes that extend it can know about specific quantities.
549 ! Such classes should override this method to add new supported quantities.
550 message(1) = "Trying to update a quantity in the multi-system container class"
551 call messages_fatal(1, namespace=this%namespace)
552
554 end subroutine multisystem_update_quantity
555
556 ! ---------------------------------------------------------
557 subroutine multisystem_init_interaction_as_partner(partner, interaction)
558 class(multisystem_t), intent(in) :: partner
559 class(interaction_surrogate_t), intent(inout) :: interaction
560
562
563 ! The multisystem class should never know about any specific interaction.
564 ! Only classes that extend it can know about specific interactions.
565 ! Such classes should override this method to add new supported interactions.
566 message(1) = "Trying to initialize an interaction as partner in the multi-system container class"
567 call messages_fatal(1, namespace=partner%namespace)
568
571
572 ! ---------------------------------------------------------
573 subroutine multisystem_copy_quantities_to_interaction(partner, interaction)
574 class(multisystem_t), intent(inout) :: partner
575 class(interaction_surrogate_t), intent(inout) :: interaction
576
578
579 ! The multisystem class should never know about any specific quantities.
580 ! Only classes that extend it can know about specific quantities.
581 ! Such classes should override this method to add new supported quantities.
582 message(1) = "Trying to copy quantities to interaction in the multi-system container class"
583 call messages_fatal(1, namespace=partner%namespace)
584
587
588 ! ---------------------------------------------------------
589 recursive logical function multisystem_process_is_slave(this) result(is_slave)
590 class(multisystem_t), intent(in) :: this
591
592 type(system_iterator_t) :: iter
593 class(system_t), pointer :: system
594
596
597 is_slave = .false.
598 call iter%start(this%list)
599 do while (iter%has_next())
600 system => iter%get_next()
601 if (system%process_is_slave()) is_slave = .true.
602 end do
603
606
607 !--------------------------------------------------------------------
611 recursive subroutine multisystem_update_kinetic_energy(this)
612 class(multisystem_t), intent(inout) :: this
613
615
616 ! We currently do not have the center of mass coordinates implemented for multisystems,
617 ! hence we set the kinetic energy to zero.
618 ! The kinetic energies of the constituents are contributing to the internal energy.
619
620 this%kinetic_energy = m_zero
621
624
625 !---------------------------------------------------------
626 recursive subroutine multisystem_update_internal_energy(this)
627 class(multisystem_t), intent(inout) :: this
628
629 class(system_t), pointer :: system
630 class(system_t), pointer :: system_2
631 type(system_iterator_t) :: system_iter
632 type(system_iterator_t) :: system_iter_2
633
635
636 ! The internal energy of the multisystem contains the kinetic and internal energies of the consistuents
637 !TODO: the kinetic energy wrt the center of mass motion should be subtracted.
638
639 this%internal_energy = m_zero
640
641 call system_iter%start(this%list)
642 do while (system_iter%has_next())
643
644 system => system_iter%get_next()
645
646 ! First add the kinetic energies of the subsystems
647 call system%update_kinetic_energy()
648 this%internal_energy = this%internal_energy + system%kinetic_energy
649
650 ! First add the internal energies of the subsystems
651 call system%update_internal_energy()
652 this%internal_energy = this%internal_energy + system%internal_energy
653
654 ! Now add the (inter-) interactions between the systems in the container.
655 call system_iter_2%start(this%list)
656 do while(system_iter_2%has_next())
657
658 system_2 => system_iter_2%get_next()
659
660 ! exclude self-interactions (intra-interactions) as they are included in the internal energy
661 ! of the subsystem, which was already added above.
662 if(.not. associated(system, system_2)) then
663 this%internal_energy = this%internal_energy + multisystem_pair_energy(system, system_2)
664 end if
665 end do ! system_iter_2
667 end do ! system_iter
668
671
672 ! ---------------------------------------------------------
686 class(multisystem_t), intent(inout) :: this
687
688 type(system_iterator_t) :: system_iter
689 class(system_t), pointer :: system
690 type(interaction_iterator_t) :: interaction_iter
691 class(interaction_t), pointer :: interaction
692 type(system_list_t) :: flat_list
693
695
696 this%potential_energy = m_zero
697
698 ! We need to handle interactions of the container itself:
700
701 ! generate a list of all systems inside the container and its subcontainers:
702 call this%get_flat_list(flat_list)
703
704 ! loop over all systems inside the container
705 call system_iter%start(flat_list)
706 do while (system_iter%has_next())
707
708 system => system_iter%get_next()
709
710 ! Even though we are not using the potential energy of the subsystems here, we need to trigger their calculation
711 call system%update_potential_energy()
712
713 ! loop over all interactions and discard those with partners inside the container
714 call interaction_iter%start(system%interactions)
715 do while (interaction_iter%has_next())
716 interaction => interaction_iter%get_next()
717 if(.not. flat_list%contains(interaction%partner) .and. .not. interaction%intra_interaction) then
718 call interaction%calculate_energy()
719 this%potential_energy = this%potential_energy + interaction%energy
720 end if
721 end do
722
723 end do
724
727
728 ! ---------------------------------------------------------
735 recursive real(real64) function multisystem_pair_energy(partner_A, partner_B) result(pair_energy)
736 class(interaction_partner_t), intent(in) :: partner_a
737 class(interaction_partner_t), intent(in) :: partner_b
738
739 class(system_t), pointer :: system_a
740 class(system_t), pointer :: system_b
741 type(system_iterator_t) :: system_iterator_a
742 type(system_iterator_t) :: system_iterator_b
743
745
746 pair_energy = m_zero
747
748 select type(partner_a)
749 class is (multisystem_t) ! partner_A is container
750
751 call system_iterator_a%start(partner_a%list)
752 do while( system_iterator_a%has_next() )
753
754 system_a => system_iterator_a%get_next()
755
756 select type(partner_b)
757 class is (multisystem_t)
758
759 call system_iterator_b%start(partner_b%list)
760 do while( system_iterator_b%has_next() )
761 system_b => system_iterator_b%get_next()
762 pair_energy = pair_energy + multisystem_pair_energy(system_a, system_b)
763 end do
764
765 class is (system_t)
766 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
767 class default
768 assert(.false.) ! partner_A must be a system_t
769 end select
770 end do
771
772 class is (system_t) ! partner_A is non-container system
773
774 select type(partner_b)
775 class is (multisystem_t) ! partner_B is container
776
777 call system_iterator_b%start(partner_b%list)
778 do while( system_iterator_b%has_next() )
779 system_b => system_iterator_b%get_next()
780 pair_energy = pair_energy + multisystem_pair_energy(partner_a, system_b)
781 end do
782
783 class default ! both partner_A and partner_B are explicit: we need to calculate
784 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
785 end select
786
787 class default
788 assert(.false.)
789 end select
790
792
793 contains
794
795 real(real64) function interaction_energy(system, partner) result (energy)
796 class(system_t), target, intent(in) :: system
797 class(interaction_partner_t), target, intent(in) :: partner
798
799 type(interaction_iterator_t) :: interaction_iterator
800 class(interaction_t), pointer :: interaction
801
802 energy = m_zero
803
804 call interaction_iterator%start(system%interactions)
805 do while(interaction_iterator%has_next())
806 interaction => interaction_iterator%get_next()
807 if( associated(interaction%partner, partner)) then
808 call interaction%calculate_energy()
809 energy = energy + interaction%energy
810 end if
811 end do
812 end function interaction_energy
813
814 end function multisystem_pair_energy
815
816
817 ! ---------------------------------------------------------
820 recursive subroutine multisystem_get_flat_list(this, flat_list)
821 class(multisystem_t), intent(in) :: this
822 type(system_list_t), intent(out) :: flat_list
823
824 class(interaction_partner_t), pointer :: partner
825 type(partner_iterator_t) :: iterator
826
829 call iterator%start(this%list)
830 do while (iterator%has_next())
831 partner => iterator%get_next()
832
833 call flat_list%add(partner)
834
835 select type (partner)
836 class is (multisystem_t)
837 ! Also include the subsystems of a multisystem
838 call partner%get_flat_list(flat_list)
839 end select
840
841 end do
842
844
845 end subroutine multisystem_get_flat_list
846
847 ! ---------------------------------------------------------
848 recursive subroutine multisystem_end(this)
849 class(multisystem_t), intent(inout) :: this
850
851 type(system_iterator_t) :: iter
852 class(system_t), pointer :: system
853
854 push_sub(multisystem_end)
855
856 call iter%start(this%list)
857 do while (iter%has_next())
858 system => iter%get_next()
859 if (associated(system)) then
860 deallocate(system)
861 end if
862 end do
863
864 call system_end(this)
865
866 pop_sub(multisystem_end)
867 end subroutine multisystem_end
868
869 ! ---------------------------------------------------------
870 recursive subroutine multisystem_start_barrier(this, target_time, barrier_index)
871 class(multisystem_t), intent(inout) :: this
872 real(real64), intent(in) :: target_time
873 integer, intent(in) :: barrier_index
874
875 type(system_iterator_t) :: iter
876 class(system_t), pointer :: system
877
879
880 call iter%start(this%list)
881 do while (iter%has_next())
882 system => iter%get_next()
883 call system%start_barrier(target_time, barrier_index)
884 end do
885
887 end subroutine multisystem_start_barrier
889 ! ---------------------------------------------------------
890 recursive subroutine multisystem_end_barrier(this, barrier_index)
891 class(multisystem_t), intent(inout) :: this
892 integer, intent(in) :: barrier_index
893
894 type(system_iterator_t) :: iter
895 class(system_t), pointer :: system
896
898
899 call iter%start(this%list)
900 do while (iter%has_next())
901 system => iter%get_next()
902 call system%end_barrier(barrier_index)
903 end do
904
906 end subroutine multisystem_end_barrier
907
908 ! ---------------------------------------------------------
909 recursive logical function multisystem_arrived_at_barrier(this, barrier_index)
910 class(multisystem_t), intent(inout) :: this
911 integer, intent(in) :: barrier_index
912
913 type(system_iterator_t) :: iter
914 class(system_t), pointer :: system
915
917
919 call iter%start(this%list)
920 do while (iter%has_next())
921 system => iter%get_next()
923 system%arrived_at_barrier(barrier_index)
924 end do
925
928
929 ! ---------------------------------------------------------
930 recursive subroutine multisystem_restart_write(this)
931 class(multisystem_t), intent(inout) :: this
932
933 type(system_iterator_t) :: iter
934 class(system_t), pointer :: system
935
937
938 ! do generic restart steps
939 call system_restart_write(this)
940
941 ! loop over all subsystems
942 call iter%start(this%list)
943 do while (iter%has_next())
944 system => iter%get_next()
945 call system%restart_write()
946 end do
947 message(1) = "Wrote restart data for multisystem "//trim(this%namespace%get())
948 call messages_info(1, namespace=this%namespace)
949
951 end subroutine multisystem_restart_write
952
953 ! ---------------------------------------------------------
954 recursive logical function multisystem_restart_read(this)
955 class(multisystem_t), intent(inout) :: this
956
957 type(system_iterator_t) :: iter
958 class(system_t), pointer :: system
959
961
962 ! read generic restart data
963 multisystem_restart_read = system_restart_read(this)
964 call iter%start(this%list)
965 do while (iter%has_next())
966 system => iter%get_next()
967 ! TODO: adapt logics here for consistent restarting
969 system%restart_read()
970 end do
971
973 message(1) = "Successfully read restart data for multisystem "//trim(this%namespace%get())
974 call messages_info(1, namespace=this%namespace)
975 end if
976
978 end function multisystem_restart_read
979
980 ! ---------------------------------------------------------
981 subroutine multisystem_restart_write_data(this)
982 class(multisystem_t), intent(inout) :: this
985
986 ! do not write restart data for multisystem_t
987
989 end subroutine multisystem_restart_write_data
990
991 ! ---------------------------------------------------------
992 ! this function returns true if restart data could be read
993 logical function multisystem_restart_read_data(this)
994 class(multisystem_t), intent(inout) :: this
995
997
999
1003end 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:187
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:420
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, 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_init_algorithm(this, factory)
recursive subroutine multisystem_update_internal_energy(this)
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_quantity(this, iq)
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)
subroutine multisystem_init_interaction_as_partner(partner, interaction)
recursive subroutine multisystem_propagation_start(this)
call the propagation_start routine for all contained systems
recursive logical function multisystem_is_tolerance_reached(this, tol)
recursive real(real64) function multisystem_next_time_on_largest_dt(this)
recursive subroutine multisystem_propagation_finish(this)
call the propagation_finish routine for all contained systems
recursive subroutine multisystem_initial_conditions(this)
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 implements the abstract system type.
Definition: system.F90:118
subroutine, public system_init_iteration_counters(this)
Initialize the iteration counters of the system and its interactions, algorithms and quantities.
Definition: system.F90:955
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:1291
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:1207
recursive subroutine, public system_create_interactions(this, interaction_factory, available_partners)
create the interactions of the system
Definition: system.F90:502
subroutine, public system_propagation_finish(this)
Definition: system.F90:1042
subroutine, public system_execute_algorithm(this)
perform one or more algorithmic operations
Definition: system.F90:331
subroutine, public system_propagation_start(this)
Definition: system.F90:988
subroutine, public system_reset_iteration_counters(this, accumulated_iterations)
Definition: system.F90:449
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:302
Abstract class for systems.
Definition: system.F90:172
int true(void)