LIMEX plugin
All Classes Functions Variables Typedefs Modules
time_integrator_impl.hpp
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2014: G-CSC, Goethe University Frankfurt
3 * SPDX-License-Identifier: LicenseRef-UG4-LGPL-3.0
4 *
5 * Author: Arne Naegel, Andreas Kreienbuehl
6 *
7 * This file is part of UG4.
8 *
9 * UG4 is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU Lesser General Public License version 3 (as published by the
11 * Free Software Foundation) with the following additional attribution
12 * requirements (according to LGPL/GPL v3 §7):
13 *
14 * (1) The following notice must be displayed in the Appropriate Legal Notices
15 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
16 *
17 * (2) The following notice must be displayed at a prominent place in the
18 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
19 *
20 * (3) The following bibliography is recommended for citation and must be
21 * preserved in all covered files:
22 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
23 * parallel geometric multigrid solver on hierarchically distributed grids.
24 * Computing and visualization in science 16, 4 (2013), 151-164"
25 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
26 * flexible software system for simulating pde based models on high performance
27 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU Lesser General Public License for more details.
33 */
34
35#ifndef __H__LIMEX__TIME_INTEGRATOR_IMPL_HPP__
36#define __H__LIMEX__TIME_INTEGRATOR_IMPL_HPP__
37
38namespace ug {
39
40template<typename TDomain, typename TAlgebra>
41bool LinearTimeIntegrator<TDomain, TAlgebra>::apply
42(
43 SmartPtr<grid_function_type> u1,
44 number t1,
45 ConstSmartPtr<grid_function_type> u0,
46 number t0
47)
48{
49
50 LIMEX_PROFILE_FUNC()
51 UG_COND_THROW(!base_type::m_spLinearSolver.valid(), "Linear solver invalid");
52
53 // short-cuts
54 GridLevel const &gl = u0->grid_level();
55 time_disc_type &tdisc = *tdisc_dep_type::m_spTimeDisc;
56
57 // create solution vector & right hand side
58 SmartPtr<typename base_type::vector_type> uold= u0->clone();
59 SmartPtr<typename base_type::vector_type> b= u0->clone_without_values();
60
61 // solution time series
62 SmartPtr<vector_time_series_type> m_spSolTimeSeries;
63 m_spSolTimeSeries=make_sp(new vector_time_series_type());
64 m_spSolTimeSeries->clear();
65 m_spSolTimeSeries->push(uold, t0);
66
67 // create matrix operator
68 SmartPtr<typename base_type::assembled_operator_type> spAssOp=make_sp(new typename base_type::assembled_operator_type(tdisc_dep_type::m_spTimeDisc, gl));
69
70 // integrate
71 if(!base_type::m_bNoLogOut)
72 UG_LOG("+++ Integrating: ["<< t0 <<", "<< t1 <<"]\n");
73
74 double t = t0;
75 number dt_assembled = -1.0; // invalid
76 int step = 1;
77
78 number currdt = base_type::m_dt;
79
80 while((t < t1) && (t1-t > base_type::m_precisionBound))
81 {
82
83 if(!base_type::m_bNoLogOut)
84 { UG_LOG("+++ Timestep +++" << step << "\n"); }
85
86 // determine step size
87 number dt = std::min(currdt, t1-t);
88
89 // prepare step
90 tdisc.prepare_step(m_spSolTimeSeries, dt);
91 if (fabs(dt-dt_assembled) > base_type::m_precisionBound)
92 {
93 // re-assemble operator
94 if(!base_type::m_bNoLogOut)
95 UG_LOG("+++ Reassemble (t=" << t << ", dt=" << dt <<")\n");
96
97 tdisc.assemble_linear(*spAssOp, *b, gl);
98 (base_type::m_spLinearSolver)->init(spAssOp, *u1);
99 dt_assembled = dt;
100 }
101 else
102 {
103 // keep old operator
104 tdisc.assemble_rhs(*b, gl);
105 }
106
107 // execute step
108 if (base_type::m_spLinearSolver->apply(*u1, *b))
109 {
110 // ACCEPTING:
111 // Notify observers (which could modify u1!)
112 this->notify_finalize_step(u1, step++, t+dt, dt);
113
114 // prepare next step.
115 // push updated solution into time series
116 t += dt;
117 SmartPtr<typename base_type::vector_type> tmp = m_spSolTimeSeries->oldest();
118 VecAssign(*tmp, *u1.template cast_dynamic<typename base_type::vector_type>());
119 m_spSolTimeSeries->push_discard_oldest(tmp, t);
120
121 }
122 else
123 {
124 // DISCARDING
125 currdt *= 0.5;
126 }
127
128 }
129
130 this->notify_end(u1, step, t1, currdt);
131
132 return true;
133};
134
135
136template<typename TDomain, typename TAlgebra>
137bool ConstStepLinearTimeIntegrator<TDomain, TAlgebra>::apply
138(
139 SmartPtr<grid_function_type> u1,
140 number t1,
141 ConstSmartPtr<grid_function_type> u0,
142 number t0
143)
144{
145 LIMEX_PROFILE_FUNC()
146 UG_COND_THROW(!base_type::m_spLinearSolver.valid(), "Linear solver invalid");
147
148 // short-cuts
149 GridLevel const &gl = u0->grid_level();
150 time_disc_type &tdisc = *tdisc_dep_type::m_spTimeDisc;
151
152 // create solution vector & right hand side
153 SmartPtr<typename base_type::vector_type> uold= u0->clone();
154 SmartPtr<typename base_type::vector_type> b= u0->clone_without_values();
155
156 // solution time series
157 SmartPtr<vector_time_series_type> m_spSolTimeSeries;
158 m_spSolTimeSeries=make_sp(new vector_time_series_type());
159 m_spSolTimeSeries->push(uold, t0);
160
161 SmartPtr<typename base_type::assembled_operator_type> spAssOp = SPNULL;
162
163 // select number of steps
164 double t = t0;
165 int numSteps = round((t1-t0) / base_type::m_dt);
166 number currdt = (t1-t0) / numSteps;
167
168
169
170 //std::cerr << "+++ Integrating: ["<< t0 <<", "<< t1 <<"] with dt=" << currdt << "("<< numSteps<< " iters)\n";
171 if(!base_type::m_bNoLogOut)
172 {
173 UG_LOG("+++ Integrating: [\t"<< t0 <<"\t, \t"<< t1 <<"\t] with dt=\t" << currdt << "("<< numSteps<< " iters)" << std::endl);
174 }
175
176 // integrate
177 for(int step = 1; step<=numSteps; ++step)
178 {
179 // determine step size
180 // number dt = std::min(currdt, t1-t);
181 const number dt = currdt;
182
183 if(!base_type::m_bNoLogOut)
184 {
185 UG_LOG("+++ Const timestep +++" << step<< "(t=" << t << ", dt=" << dt << ")"<< std::endl);
186 }
187 this->notify_init_step(u1, step, t, dt);
188
189 // prepare step
190 tdisc.prepare_step(m_spSolTimeSeries, dt);
191 if (spAssOp==SPNULL)
192 {
193 // Assemble operator.
194 if(!base_type::m_bNoLogOut) UG_LOG("+++ Assemble (t=" << t << ", dt=" << dt <<")" << std::endl);
195
196 spAssOp=make_sp(new typename base_type::assembled_operator_type(tdisc_dep_type::m_spTimeDisc, gl));
197 tdisc.assemble_linear(*spAssOp, *b, gl);
198 (base_type::m_spLinearSolver)->init(spAssOp, *u1);
199 }
200 else
201 {
202 // Recycle existing operator.
203 // std::cerr << "Recycling timestep " << step << "\n";
204 tdisc.assemble_rhs(*b, gl);
205 }
206
207 // execute step
208 if (base_type::m_spLinearSolver->apply(*u1, *b))
209 {
210 // ACCEPTING:
211 // Notify observers (which could modify u1!)
212 this->notify_finalize_step(u1, step, t+dt, dt);
213
214 // push updated solution into time series
215 t += dt; // Update time.
216 SmartPtr<typename base_type::vector_type> tmp = m_spSolTimeSeries->oldest();
217 VecAssign(*tmp, *u1.template cast_dynamic<typename base_type::vector_type>());
218 m_spSolTimeSeries->push_discard_oldest(tmp, t);
219
220 }
221 else
222 {
223 UG_THROW("ConstStepLinearTimeIntegrator::apply failed!!!");
224 this->notify_rewind_step(u1, step, t+dt, dt);
225 }
226
227 }
228
229 this->notify_end(u1, numSteps, t1, currdt);
230
231 return true;
232};
233
234template<typename TDomain, typename TAlgebra>
235bool TimeIntegratorLinearAdaptive<TDomain, TAlgebra>::apply
236(
237 SmartPtr<grid_function_type> u1,
238 number t1,
239 ConstSmartPtr<grid_function_type> u0,
240 number t0
241)
242{
243 // short-cuts
244 GridLevel const &gl = u0->grid_level();
245 time_disc_type &tdisc = *tdisc_dep_type::m_spTimeDisc;
246 time_disc_type &tdisc2 = *m_spTimeDisc2;
247
248 // create solution vector & right hand side
249 SmartPtr<typename base_type::vector_type> uold= u0->clone();
250 SmartPtr<typename base_type::vector_type> b= u0->clone_without_values();
251
252 // create matrix operator
253 SmartPtr<typename base_type::assembled_operator_type> spAssOp=make_sp(new typename base_type::assembled_operator_type(tdisc_dep_type::m_spTimeDisc, gl));
254
255 // create additional solutions
256 SmartPtr<typename base_type::grid_function_type> u2old = u0->clone();
257 SmartPtr<typename base_type::grid_function_type> u2 = u0->clone();
258
259 // solution time series
260 SmartPtr<vector_time_series_type> m_spSolTimeSeries;
261 m_spSolTimeSeries=make_sp(new vector_time_series_type());
262 m_spSolTimeSeries->push(uold, t0);
263
264 SmartPtr<vector_time_series_type> m_spSolTimeSeries2;
265 m_spSolTimeSeries2=make_sp(new vector_time_series_type());
266 m_spSolTimeSeries2->push(u2old, t0);
267
268 // automatic selection of min/max time step
269 if (m_dtmin <= 0.0) { m_dtmin = (t1 - t0)/1.0e+5; }
270 if (m_dtmax <= 0.0) { m_dtmax = (t1 - t0)/10.0; }
271
272 // Aitken Neville extrapolation
273 const size_t tsteps[2] = {1,2};
274 std::vector<size_t> vsteps (tsteps, tsteps+2);
276
277 // integrate
278 if(!base_type::m_bNoLogOut)
279 UG_LOG("+++ Integrating: ["<< t0 <<", "<< t1 <<"]\n");
280
281 double t = t0;
282 int step = 0;
283
284 number dt = base_type::m_dt;
285 while((t < t1) && (t1-t > base_type::m_precisionBound))
286 {
287 // step: t -> t+dt
288 bool bSuccess = false;
289 while (!bSuccess){
290
291 // determine step size
292 if (dt<m_dtmin){
293 if(!base_type::m_bNoLogOut)
294 UG_LOG("Step size below minimum")
295 }
296 dt = std::min(dt, t1-t);
297
298 // basic step
299 if(!base_type::m_bNoLogOut)
300 UG_LOG("+++ Timestep: " << ++step << "\n");
301
302 tdisc.prepare_step(m_spSolTimeSeries, dt);
303 tdisc.assemble_linear(*spAssOp, *b, gl);
304 base_type::m_spLinearSolver->init(spAssOp, *u1);
305 base_type::m_spLinearSolver->apply(*u1, *b);
306
307
308 // control 1/2
309 if(!base_type::m_bNoLogOut)
310 UG_LOG("+++ Control: " << step << "\n");
311
312 tdisc2.prepare_step(m_spSolTimeSeries, 0.5*dt);
313 tdisc2.assemble_linear(*spAssOp, *b, gl);
314 base_type::m_spLinearSolver->init(spAssOp, *u2);
315 base_type::m_spLinearSolver->apply(*u2, *b);
316
317 // push back solution
318 SmartPtr<typename base_type::vector_type> tmp2 = m_spSolTimeSeries2->oldest();
319 (*tmp2)=*(u2.template cast_static<typename base_type::vector_type>());
320 m_spSolTimeSeries2->push_discard_oldest(tmp2, t + 0.5*dt);
321
322 // control 2/2
323 tdisc2.prepare_step(m_spSolTimeSeries2, 0.5*dt);
324 tdisc2.assemble_linear(*spAssOp, *b, gl);
325 base_type::m_spLinearSolver->init(spAssOp, *u2);
326 base_type::m_spLinearSolver->apply(*u2, *b);
327
328 // obtain extrapolated solution
329 timex.set_solution(u1, 0);
330 timex.set_solution(u2, 1);
331 timex.apply();
332
333 // predict (subsequent) time step
334 number eps = timex.get_error_estimates()[0];
335 number lambda = std::pow(0.8* m_tol/eps, 0.5);
336
337 number dtEst= dt*lambda;
338 dtEst = std::min(dtEst, 1.5*dt);
339 dtEst = std::min(dtEst, m_dtmax);
340
341 dt = dtEst;
342 if (eps <= m_tol)
343 {
344 // ACCEPT STEP (and thus solution u2)
345 if(!base_type::m_bNoLogOut)
346 UG_LOG("ACCEPTING solution, dtnew=" << dt);
347
348 bSuccess = true;
349 }
350 else
351 {
352 // DISCARD step
353 if(!base_type::m_bNoLogOut)
354 UG_LOG("DISCARDING solution, dtnew=" << dt);
355
356 // => reset solutions
357 VecAssign(*u1.template cast_dynamic<typename base_type::vector_type>(), *uold);
358
359 // => timeSeries2 has been updated...
360 SmartPtr<typename base_type::vector_type> tmp = m_spSolTimeSeries2->oldest();
361 VecAssign(*tmp, *uold);
362 m_spSolTimeSeries2->push_discard_oldest(tmp, t);
363
364 }
365
366 }
367
368
369 // prepare next loop
370 t += dt;
371
372 // push updated solution into time series (and continue)
373 SmartPtr<typename base_type::vector_type> tmp = m_spSolTimeSeries->oldest();
374 VecAssign(*tmp, static_cast<typename base_type::vector_type> (*u2));
375 m_spSolTimeSeries->push_discard_oldest(tmp, t);
376
377 }
378
379 return true;
380};
381
382} // namespace ug
383
384#endif /* __H__LIMEX__TIME_INTEGRATOR_IMPL_HPP__ */
Definition time_extrapolation.h:986