Octopus
ensemble.F90
Go to the documentation of this file.
1!! Copyright (C) 2024 S. de la Pena, M. Lueders
2!!
3!! This Source Code Form is subject to the terms of the Mozilla Public
4!! License, v. 2.0. If a copy of the MPL was not distributed with this
5!! file, You can obtain one at https://mozilla.org/MPL/2.0/.
6!!
7#include "global.h"
8
13!
14module ensemble_oct_m
15
17 use debug_oct_m
18 use global_oct_m
21 use io_oct_m
23 use mpi_oct_m
28 use system_oct_m
29 use parser_oct_m
31
32 implicit none
33
34 private
35 public :: &
37
46 type, extends(multisystem_t) :: ensemble_t
47 private
48 integer :: nreplica
49 ! !!
50 ! !! This is the number of replicas in, planned for a calculation.
51 ! !! The actual number of replicas in one run is determined by
52 ! !! last-first+1.
53 ! !!
54 ! !! The total number of replicas can be different can differ if
55 ! !! further runs have been added to improve the convergence.
56 integer :: first
57 integer :: last
58 real(real64), allocatable :: weights(:)
59
60 contains
61 procedure :: create_interactions => ensemble_create_interactions
62 procedure :: add_partners_to_list => ensemble_add_partners_to_list
63 final :: ensemble_finalizer
64 end type ensemble_t
65
66 interface ensemble_t
67 procedure ensemble_constructor
68 end interface ensemble_t
69
70contains
71
72 ! ---------------------------------------------------------
78 !
79 recursive function ensemble_constructor(namespace, n_replicas, first, last, system_factory, names, types, calc_mode_id, grp) &
80 result(sys)
81 type(namespace_t), intent(in) :: namespace
82 integer, intent(in) :: n_replicas
83 class(system_factory_abst_t), intent(in) :: system_factory
84 integer, intent(in) :: first
85 integer, intent(in) :: last
86 character(len=128), intent(in) :: names(:)
87 integer, intent(in) :: types(:)
88 integer, intent(in) :: calc_mode_id
89 type(mpi_grp_t), intent(in) :: grp
90 class(ensemble_t), pointer :: sys
91
92 integer :: ireplica
93 class(system_t), pointer :: replica
94 character(len=128) :: replica_name
95
96 push_sub(ensemble_constructor)
97
98 allocate(sys)
99 sys%namespace = namespace
100 sys%nreplica = n_replicas
101 sys%first = max(1, first)
102 sys%last = min(n_replicas, last)
103
104
105 ! No interaction directly supported by this system (but classes that extend it can add their own)
106 allocate(sys%supported_interactions(0))
107 allocate(sys%supported_interactions_as_partner(0))
108
109 do ireplica = sys%first, sys%last
110 write(replica_name, '(I8.8)') ireplica
111
112 ! Be aware that we need to use `sys%namespace` here. Passing only `namespace` leads to an error,
113 ! as `namespace` seems to be deleted when the routine exits.
114 !
115 replica => multisystem_basic_t(namespace_t(replica_name, parent=sys%namespace), names, types, &
116 system_factory, calc_mode_id, grp)
117
118 call sys%list%add(replica)
119
120 end do
121
122 ! Initialize weights to uniform distribution
123
124 safe_allocate(sys%weights(1:sys%nreplica))
125 sys%weights = 1.0_real64/sys%nreplica
126
127 pop_sub(ensemble_constructor)
128 end function ensemble_constructor
129
130 recursive subroutine ensemble_finalizer(this)
131 type(ensemble_t), intent(inout) :: this
132
133 push_sub(ensemble_finalizer)
134
135 call ensemble_end(this)
136
137 pop_sub(ensemble_finalizer)
138 end subroutine ensemble_finalizer
139
140 recursive subroutine ensemble_end(this)
141 type(ensemble_t), intent(inout) :: this
142
143 push_sub(ensemble_end)
144
145 safe_deallocate_a(this%weights)
146 call multisystem_end(this)
147
148 pop_sub(ensemble_end)
149 end subroutine ensemble_end
150
151 ! ---------------------------------------------------------
160 !
161 recursive subroutine ensemble_create_interactions(this, interaction_factory, available_partners)
162 class(ensemble_t), intent(inout) :: this
163 class(interactions_factory_abst_t), intent(in) :: interaction_factory
164 class(partner_list_t), target, intent(in) :: available_partners
165
166 type(system_iterator_t) :: iter
167 class(system_t), pointer :: subsystem
168 type(partner_list_t) :: partners
169
171
172 ! Create interactions of the ensemble container
173 call system_create_interactions(this, interaction_factory, available_partners)
175 ! Create the subsystems interactions
176 call iter%start(this%list)
177 do while (iter%has_next())
178 subsystem => iter%get_next()
179 ! partners = available_partners
180 ! the above line would provide inter-replica ghost interactions, which does not seem
181 ! to be necessary, as the replicas can propagate independent of each other.
182 ! If we need more synchronization, e.g. for averages, this should be provided by the
183 ! real interaction.
184 ! In order to restore the inter-replica ghost, uncomment the line above and remove
185 ! the line below (partners.empty()).
186 call partners%empty()
187 call partners%add(subsystem)
188 call subsystem%create_interactions(interaction_factory, partners)
189 end do
190
192 end subroutine ensemble_create_interactions
193
194
199 recursive subroutine ensemble_add_partners_to_list(this, list, interaction_type)
200 class(ensemble_t), intent(in) :: this
201 class(partner_list_t), intent(inout) :: list
202 integer, optional, intent(in) :: interaction_type
203
204 type(system_iterator_t) :: iter
205 class(system_t), pointer :: system
206
208
209 if (present(interaction_type)) then
210 if (any(this%supported_interactions_as_partner == interaction_type)) then
211 call list%add(this)
212 end if
213 else
214 call list%add(this)
215
216 call iter%start(this%list)
217 do while (iter%has_next())
218 system => iter%get_next()
219 call system%add_partners_to_list(list)
220 end do
221
222 end if
223
226
227end module ensemble_oct_m
This module implements the basic elements defining algorithms.
Definition: algorithm.F90:143
This module implements the ensemble class.
Definition: ensemble.F90:109
recursive subroutine ensemble_create_interactions(this, interaction_factory, available_partners)
create the interactions of the ensemble
Definition: ensemble.F90:257
recursive subroutine ensemble_finalizer(this)
Definition: ensemble.F90:226
recursive subroutine ensemble_end(this)
Definition: ensemble.F90:236
recursive subroutine ensemble_add_partners_to_list(this, list, interaction_type)
add the container to the flat list.
Definition: ensemble.F90:295
recursive class(ensemble_t) function, pointer ensemble_constructor(namespace, n_replicas, first, last, system_factory, names, types, calc_mode_id, grp)
Constructor for the ensemble_t class.
Definition: ensemble.F90:176
This module defines classes and functions for interaction partners.
This module defines the abstract class for the interaction factory.
Definition: io.F90:116
This module implements the basic mulsisystem class, a container system for other systems.
This module implements the abstract multisystem class.
recursive subroutine, public multisystem_end(this)
This module defines the abstract class for the system factory.
This module implements the abstract system type.
Definition: system.F90:120
recursive subroutine, public system_create_interactions(this, interaction_factory, available_partners)
create the interactions of the system
Definition: system.F90:519
the ensemble class
Definition: ensemble.F90:141
Container class for lists of system_oct_m::system_t.
the abstract multisystem class
Abstract class for systems.
Definition: system.F90:175