Line data Source code
1 : /*
2 : * Copyright (c) 2010-2020: G-CSC, Goethe University Frankfurt
3 : * Author: Tim Schön
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__LIB_DISC__TIME_DISC__TIME_INTEGRATOR_SUBJECT
34 : #define __H__UG__LIB_DISC__TIME_DISC__TIME_INTEGRATOR_SUBJECT
35 :
36 : #include "./time_integrator_observers/time_integrator_observer_interface.h"
37 :
38 : namespace ug {
39 :
40 : /// Base class for a subject notifying observers attachment.
41 : /** Provides the option to perform pre-/postprocessing for a (tentative step for evolving from t -> t+dt). Seven cases are distinguished
42 : * 1) INIT (STEP) : Called at t=t_i before time step is executed. Contains solution u0=u(t0).
43 : * 2) FINALIZE (STEP) : Called at t=t_i+dt, after time step has been executed and can be accepted. Provides solution u = u(t+dt).
44 : * 3) REWIND (STEP) : Called at t=t_i+dt, after time step has been executed, but must be rejected. Provides (rejected) solution u = u(t+dt).
45 : * 4) PREPROCESS (STEP) : Called at t=t_i before newton solver is executed (if applicable). Contains solution u0=u(t0). This may happen multiple times per time step.
46 : * 5) POSTPROCESS (STEP) : Called at t=t_i+dt, after newton solver has been executed (if applicable). Provides solution u = u(t+dt). This may happen multiple times per time step.
47 : * 6) START : Called at t=t_0, at the beginning of the time integration process (start of the simulation)
48 : * 7) END : Called at t=T, at the end of the time integration process (end of the simulation)
49 : */
50 : template<class TDomain, class TAlgebra>
51 : class TimeIntegratorSubject
52 : {
53 : public:
54 : typedef GridFunction<TDomain, TAlgebra> grid_function_type;
55 : typedef ITimeIntegratorObserver<TDomain, TAlgebra> process_observer_type;
56 : typedef ITimeIntegratorStageObserver_init<TDomain, TAlgebra> init_observer_type;
57 : typedef ITimeIntegratorStageObserver_rewind<TDomain, TAlgebra> rewind_observer_type;
58 : typedef ITimeIntegratorStageObserver_finalize<TDomain, TAlgebra> finalize_observer_type;
59 : typedef ITimeIntegratorStageObserver_preprocess<TDomain, TAlgebra> preprocess_observer_type;
60 : typedef ITimeIntegratorStageObserver_postprocess<TDomain, TAlgebra> postprocess_observer_type;
61 : typedef ITimeIntegratorStageObserver_start<TDomain, TAlgebra> start_observer_type;
62 : typedef ITimeIntegratorStageObserver_end<TDomain, TAlgebra> end_observer_type;
63 : typedef typename std::vector<SmartPtr<process_observer_type> > process_observer_container_type;
64 :
65 : enum observer_group_type {
66 : TIO_GROUP_INIT_STEP=0,
67 : TIO_GROUP_REWIND_STEP,
68 : TIO_GROUP_FINALIZE_STEP,
69 : TIO_GROUP_PREPROCESS_STEP,
70 : TIO_GROUP_POSTPROCESS_STEP,
71 : TIO_GROUP_START,
72 : TIO_GROUP_END,
73 : TIO_GROUP_SIZE};
74 :
75 : protected:
76 : // process_observer_container_type m_vProcessObservers;
77 : process_observer_container_type m_vProcessObservers[TIO_GROUP_SIZE];
78 :
79 : // container for statically mapped observers
80 : std::vector<SmartPtr<init_observer_type> > m_vInitObservers;
81 : std::vector<SmartPtr<rewind_observer_type> > m_vRewindObservers;
82 : std::vector<SmartPtr<finalize_observer_type> > m_vFinalizeObservers;
83 : std::vector<SmartPtr<preprocess_observer_type> > m_vPreprocessObservers;
84 : std::vector<SmartPtr<postprocess_observer_type> > m_vPostprocessObservers;
85 : std::vector<SmartPtr<start_observer_type> > m_vStartObservers;
86 : std::vector<SmartPtr<end_observer_type> > m_vEndObservers;
87 :
88 :
89 : protected:
90 : //! register observer (default: postprocess)
91 : template<int tGroup>
92 : void attach_to_group(SmartPtr<process_observer_type> obs)
93 : {
94 : //UG_LOG("TimeIntegratorSubject::attach_observer[" << tGroup <<"]" << this << std::endl);
95 0 : m_vProcessObservers[tGroup].push_back(obs);
96 0 : }
97 :
98 : //! register observer (default: postprocess)
99 : void attach_to_group(int tGroup, SmartPtr<process_observer_type> obs)
100 : {
101 : //UG_LOG("TimeIntegratorSubject::attach_observer[" << tGroup <<"]" << this << std::endl);
102 : m_vProcessObservers[tGroup].push_back(obs);
103 : }
104 : public:
105 :
106 : #define DECLARE_CHECK_STATIC_ATTACH(stage, container) \
107 : bool check_attach_##stage(SmartPtr<process_observer_type> obs)\
108 : {\
109 : SmartPtr<stage##_observer_type> sp_staticObs = obs.template cast_dynamic<stage##_observer_type>();\
110 : if (sp_staticObs.valid())\
111 : {\
112 : (container).push_back(sp_staticObs);\
113 : return true;\
114 : }\
115 : return false;\
116 : }
117 :
118 0 : DECLARE_CHECK_STATIC_ATTACH(init, m_vInitObservers)
119 0 : DECLARE_CHECK_STATIC_ATTACH(rewind, m_vRewindObservers)
120 0 : DECLARE_CHECK_STATIC_ATTACH(finalize, m_vFinalizeObservers)
121 0 : DECLARE_CHECK_STATIC_ATTACH(preprocess, m_vPreprocessObservers)
122 0 : DECLARE_CHECK_STATIC_ATTACH(postprocess, m_vPostprocessObservers)
123 0 : DECLARE_CHECK_STATIC_ATTACH(start, m_vStartObservers)
124 0 : DECLARE_CHECK_STATIC_ATTACH(end, m_vEndObservers)
125 :
126 : //! Attach statically mapped observers to their respective stages.
127 : //! Other observers are mapped to the finalize stage.
128 0 : void attach_observer(SmartPtr<process_observer_type> obs)
129 : {
130 : const bool isStaticallyAttached =
131 0 : check_attach_init(obs) ||
132 0 : check_attach_rewind(obs) ||
133 0 : check_attach_finalize(obs) ||
134 0 : check_attach_preprocess(obs) ||
135 0 : check_attach_postprocess(obs) ||
136 0 : check_attach_start(obs) ||
137 0 : check_attach_end(obs);
138 :
139 0 : if (!isStaticallyAttached)
140 0 : attach_finalize_observer(obs);
141 0 : }
142 :
143 0 : void attach_init_observer(SmartPtr<process_observer_type> obs)
144 0 : { attach_to_group<TIO_GROUP_INIT_STEP>(obs); }
145 :
146 0 : void attach_rewind_observer(SmartPtr<process_observer_type> obs)
147 0 : { attach_to_group<TIO_GROUP_REWIND_STEP>(obs); }
148 :
149 0 : void attach_finalize_observer(SmartPtr<process_observer_type> obs)
150 0 : { attach_to_group<TIO_GROUP_FINALIZE_STEP>(obs); }
151 :
152 0 : void attach_preprocess_observer(SmartPtr<process_observer_type> obs)
153 0 : { attach_to_group<TIO_GROUP_PREPROCESS_STEP>(obs); }
154 :
155 0 : void attach_postprocess_observer(SmartPtr<process_observer_type> obs)
156 0 : { attach_to_group<TIO_GROUP_POSTPROCESS_STEP>(obs); }
157 :
158 0 : void attach_start_observer(SmartPtr<process_observer_type> obs)
159 0 : { attach_to_group<TIO_GROUP_START>(obs); }
160 :
161 0 : void attach_end_observer(SmartPtr<process_observer_type> obs)
162 0 : { attach_to_group<TIO_GROUP_END>(obs); }
163 :
164 0 : void reset_observers()
165 : {
166 : m_vProcessObservers[TIO_GROUP_INIT_STEP].clear();
167 : m_vProcessObservers[TIO_GROUP_REWIND_STEP].clear();
168 : m_vProcessObservers[TIO_GROUP_FINALIZE_STEP].clear();
169 : m_vProcessObservers[TIO_GROUP_PREPROCESS_STEP].clear();
170 : m_vProcessObservers[TIO_GROUP_POSTPROCESS_STEP].clear();
171 : m_vProcessObservers[TIO_GROUP_START].clear();
172 : m_vProcessObservers[TIO_GROUP_END].clear();
173 :
174 : m_vInitObservers.clear();
175 : m_vRewindObservers.clear();
176 : m_vFinalizeObservers.clear();
177 : m_vPreprocessObservers.clear();
178 : m_vPostprocessObservers.clear();
179 : m_vStartObservers.clear();
180 : m_vEndObservers.clear();
181 0 : }
182 :
183 : protected:
184 : /// Notify all observers for a certain group.
185 : template<int tGroup>
186 0 : bool notify_group(SmartPtr<grid_function_type> u, int step, number time, number dt)
187 : {
188 : process_observer_container_type &observers = m_vProcessObservers[tGroup];
189 :
190 : bool result = true;
191 0 : for (typename process_observer_container_type::iterator it = observers.begin(); it!= observers.end(); ++it)
192 : {
193 0 : result = (*it)->step_process(u, step, time, dt) && result;
194 : }
195 :
196 0 : return result;
197 : }
198 :
199 :
200 : public:
201 :
202 : #define DECLARE_NOTIFY_STEP(functionName, stageName, stageID, container) \
203 : bool notify_##functionName(SmartPtr<grid_function_type> u, int step, number time, number dt)\
204 : {\
205 : bool res = notify_group<(stageID)>(u, step, time, dt);\
206 : const size_t numObs = (container).size();\
207 : for (size_t o = 0; o < numObs; ++o)\
208 : res &= (container)[o]->stageName##_action(u, step, time, dt);\
209 : return res;\
210 : }
211 :
212 : /// notify all observers that time step evolution starts
213 0 : DECLARE_NOTIFY_STEP(init_step, init, TIO_GROUP_INIT_STEP, m_vInitObservers)
214 :
215 : /// Notify all observers that time step must be rewinded.
216 0 : DECLARE_NOTIFY_STEP(rewind_step, rewind, TIO_GROUP_REWIND_STEP, m_vRewindObservers)
217 :
218 : /// notify all observers that time step has been evolved (successfully)
219 0 : DECLARE_NOTIFY_STEP(finalize_step, finalize, TIO_GROUP_FINALIZE_STEP, m_vFinalizeObservers)
220 :
221 : /// notify all observers that newton solver is about to start (may happen multiple times per time step)
222 0 : DECLARE_NOTIFY_STEP(preprocess_step, preprocess, TIO_GROUP_PREPROCESS_STEP, m_vPreprocessObservers)
223 :
224 : /// notify all observers that newton solver has finished (may happen multiple times per time step)
225 0 : DECLARE_NOTIFY_STEP(postprocess_step, postprocess, TIO_GROUP_POSTPROCESS_STEP, m_vPostprocessObservers)
226 :
227 : /// notify all observers that the simulation has started
228 0 : DECLARE_NOTIFY_STEP(start, start, TIO_GROUP_START, m_vStartObservers)
229 :
230 : /// notify all observers that the simulation has ended
231 0 : DECLARE_NOTIFY_STEP(end, end, TIO_GROUP_END, m_vEndObservers)
232 : };
233 :
234 : }
235 :
236 : #endif
|