Skip to content

Commit 96ce86c

Browse files
committed
Merge branch 'development' into feature/cleanup-scalar
Signed-off-by: Torbjörn Klatt <[email protected]> Conflicts: examples/scalar/scalar_sweeper.hpp
2 parents 0feb7c7 + 00462bd commit 96ce86c

File tree

11 files changed

+287
-53
lines changed

11 files changed

+287
-53
lines changed

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
# Changelog {#page_changelog}
22

3+
## v0.2.0 -- MPI PFASST (2014/XX/XX)
4+
5+
XXX: DOI: [10.5281/zenodo.11047](http://dx.doi.org/10.5281/zenodo.11047)
6+
7+
### Notable Features
8+
9+
* Addition of MPI based PFASST.
10+
11+
### Details
12+
13+
* Addition of MPI based PFASST algorithm using the standard predictor
14+
stage in a block mode with fixed iterations.
15+
([#46][], [#57][], [#59][])
16+
17+
* Addition of a simple scalar example.
18+
([#61][])
19+
20+
* Various tidying
21+
()
22+
23+
[#46]: https://github.com/Parallel-in-Time/PFASST/pull/46
24+
[#57]: https://github.com/Parallel-in-Time/PFASST/pull/56
25+
[#59]: https://github.com/Parallel-in-Time/PFASST/pull/59
26+
[#61]: https://github.com/Parallel-in-Time/PFASST/pull/61
27+
28+
### Contributors
29+
30+
* Matthew Emmett, Lawrence Berkeley National Laboratory ([memmett][])
31+
* Torbjörn Klatt, Jülich Supercomputing Centre ([torbjoernk][])
32+
* Daniel Ruprecht, Institute of Computational Science, University of Lugano ([danielru][])
33+
34+
[memmett]: https://github.com/memmett
35+
[torbjoernk]: https://github.com/torbjoernk
36+
[danielru]: https://github.com/danielru
37+
338
## v0.1.0 -- First Release (2014/07/25)
439

540
DOI: [10.5281/zenodo.11047](http://dx.doi.org/10.5281/zenodo.11047)

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
PFASST {#mainpage}
22
======
33

4-
The PFASST algorithm is a time-parallel algorithm for solving ODEs and PDEs.
5-
6-
The PFASST project is a C++ implementation of the *parallel full approximation scheme in space and
7-
time* (PFASST) algorithm.
8-
It also contains basic implementations of the *spectral deferred correction* (SDC) and
9-
*multi-level spectral deferred correction* (MLSDC) algorithms.
4+
The PFASST project is a C++ implementation of the *parallel full approximation scheme in space and
5+
time* (PFASST) algorithm, which in turn is a time-parallel algorithm for solving ODEs and PDEs. It
6+
also contains basic implementations of the *spectral deferred correction* (SDC) and *multi-level
7+
spectral deferred correction* (MLSDC) algorithms.
108

119

1210
News
1311
----
1412

15-
* July 25, 2014: PFASST v0.1.0 released. Please see the [release notes](#releases) for more
13+
* July 25, 2014: PFASST v0.1.0 released. Please see the [release notes](#releases) for more
1614
information.
1715

1816

@@ -39,8 +37,8 @@ Releases
3937

4038
* **v0.1.0** First Release (2014/07/25)
4139

42-
Initial release with basic implementations of SDC and MLSDC.
43-
DOI: [10.5281/zenodo.11047][DOI_v010]
40+
Initial release with basic implementations of SDC and MLSDC.
41+
DOI: [10.5281/zenodo.11047][DOI_v010]
4442
See \subpage #page_changelog "the Changelog" for details.
4543

4644
[DOI_v010]: http://dx.doi.org/10.5281/zenodo.11047

examples/scalar/scalar_sdc.cpp

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/*
2+
* Scalar test equation example using an encapsulated IMEX sweeper.
3+
* Solves Dahlquist's test equation
4+
* y' = a y + i b y
5+
* treating the real part implicitly and the imaginary part explicitly.
6+
*/
7+
18
#include<complex>
29

310
#include<pfasst.hpp>
@@ -6,32 +13,45 @@
613

714
#include "scalar_sweeper.hpp"
815

9-
int main(int, char**)
16+
/*
17+
* A simple run routine with preset parameters
18+
*/
19+
20+
double run_scalar_sdc(const size_t nsteps, const double dt, const size_t nnodes,
21+
const size_t niters, const complex<double> lambda)
1022
{
23+
1124
pfasst::SDC<> sdc;
1225

13-
const size_t nsteps = 2;
14-
const double dt = 1.0;
15-
const size_t nnodes = 4;
16-
const size_t niters = 6;
17-
const complex<double> lambda = complex<double>(-1.0, 1.0);
1826
const complex<double> y0 = complex<double>(1.0, 0.0);
19-
20-
// so far, only lobatto nodes appear to be working
21-
auto nodes = pfasst::compute_nodes(nnodes, "gauss-lobatto");
27+
auto nodes = pfasst::compute_nodes(nnodes, "gauss-lobatto");
2228
auto factory = make_shared<pfasst::encap::VectorFactory<complex<double>>>(1);
23-
auto sweeper = make_shared<ScalarSweeper<>>(lambda, y0);
24-
29+
auto sweeper = make_shared<ScalarSweeper<>>(lambda,y0);
30+
2531
sweeper->set_nodes(nodes);
2632
sweeper->set_factory(factory);
27-
33+
2834
sdc.add_level(sweeper);
29-
sdc.set_duration(0.0, dt * nsteps, dt, niters);
35+
sdc.set_duration(0.0, dt*nsteps, dt, niters);
3036
sdc.setup();
31-
37+
3238
auto q0 = sweeper->get_state(0);
3339
sweeper->exact(q0, 0.0);
34-
40+
3541
sdc.run();
42+
43+
return sweeper->get_errors();
44+
}
3645

46+
#ifndef PFASST_UNIT_TESTING
47+
int main(int /*argc*/, char** /*argv*/)
48+
{
49+
const size_t nsteps = 2;
50+
const double dt = 1.0;
51+
const size_t nnodes = 4;
52+
const size_t niters = 6;
53+
const complex<double> lambda = complex<double>(-1.0, 1.0);
54+
55+
run_scalar_sdc(nsteps, dt, nnodes, niters, lambda);
3756
}
57+
#endif

examples/scalar/scalar_sweeper.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,21 @@ class ScalarSweeper
2424
complex<double> _lambda, _u0;
2525
int _n_f_expl_eval, _n_f_impl_eval, _n_impl_solve;
2626
const complex<double> i_complex = complex<double>(0, 1);
27+
double _error;
2728

2829
public:
29-
3030
ScalarSweeper(complex<double> lambda, complex<double> u0)
3131
: _lambda(lambda)
3232
, _u0(u0)
3333
, _n_f_expl_eval(0)
3434
, _n_f_impl_eval(0)
3535
, _n_impl_solve(0)
36+
, _error(0.0)
3637
{}
3738

3839
virtual ~ScalarSweeper()
3940
{
41+
cout << "Final error: " << scientific << this->_error << endl;
4042
cout << "Number of explicit evaluations: " << this->_n_f_expl_eval << endl;
4143
cout << "Number of implicit evaluations: " << this->_n_f_impl_eval << endl;
4244
cout << "Number of implicit solves: " << this->_n_impl_solve << endl;
@@ -51,6 +53,12 @@ class ScalarSweeper
5153
this->exact(qex, t);
5254
double max_err = abs(qend[0] - qex[0]) / abs(qex[0]);
5355
cout << "err: " << scientific << max_err << endl;
56+
this->_error = max_err;
57+
}
58+
59+
double get_errors()
60+
{
61+
return this->_error;
5462
}
5563

5664
void predict(bool initial) override

include/pfasst/encap/encap_sweeper.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace pfasst
2525
{
2626
//! @{
2727
vector<time> nodes;
28+
vector<bool> is_proper;
2829
shared_ptr<EncapFactory<time>> factory;
2930
//! @}
3031

@@ -69,14 +70,21 @@ namespace pfasst
6970
//! @{
7071
void set_nodes(vector<time> nodes)
7172
{
72-
this->nodes = nodes;
73+
auto augmented = pfasst::augment_nodes(nodes);
74+
this->nodes = get<0>(augmented);
75+
this->is_proper = get<1>(augmented);
7376
}
7477

7578
const vector<time> get_nodes() const
7679
{
7780
return nodes;
7881
}
7982

83+
const vector<bool> get_is_proper() const
84+
{
85+
return is_proper;
86+
}
87+
8088
void set_factory(shared_ptr<EncapFactory<time>> factory)
8189
{
8290
this->factory = shared_ptr<EncapFactory<time>>(factory);

include/pfasst/encap/imex_sweeper.hpp

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ namespace pfasst
3030
* explicitly and the stiff part implicitly.
3131
* Therefore, we define the splitting \\( F(t,u) = F_{expl}(t,u) + F_{impl}(t,u) \\).
3232
*
33-
* This sweeper requires three interfaces to be implement for such ODEs: two routines to
34-
* evaluate the explicit \\( F_{\\rm expl} \\) and implicit \\( F_{\\rm impl} \\) pieces for a
35-
* given state, and one that solves (perhaps with an external solver) the backward-Euler
33+
* This sweeper requires three interfaces to be implement for such ODEs: two routines to
34+
* evaluate the explicit \\( F_{\\rm expl} \\) and implicit \\( F_{\\rm impl} \\) pieces for a
35+
* given state, and one that solves (perhaps with an external solver) the backward-Euler
3636
* equation \\( U^{n+1} - \\Delta t F_{\\rm impl}(U^{n+1}) = RHS \\) for \\( U^{n+1} \\).
3737
*
3838
* @tparam time precision type of the time dimension
@@ -86,6 +86,11 @@ namespace pfasst
8686
*/
8787
matrix<time> s_mat;
8888

89+
/**
90+
* quadrature matrix containing weights for 0-to-last node integration
91+
*/
92+
matrix<time> b_mat;
93+
8994
/**
9095
* quadrature matrix containing weights for node-to-node integration of explicit part
9196
*
@@ -101,6 +106,24 @@ namespace pfasst
101106
matrix<time> s_mat_impl;
102107
//! @}
103108

109+
110+
/**
111+
* Set end state to \\( U_0 + \\int F_{expl} + F_{expl} \\).
112+
*/
113+
void integrate_end_state(time dt)
114+
{
115+
vector<shared_ptr<Encapsulation<time>>> dst = { this->u_state.back() };
116+
dst[0]->copy(this->u_state.front());
117+
dst[0]->mat_apply(dst, dt, this->b_mat, this->fs_expl, false);
118+
dst[0]->mat_apply(dst, dt, this->b_mat, this->fs_impl, false);
119+
}
120+
121+
inline bool last_node_is_virtual()
122+
{
123+
return !this->get_is_proper().back();
124+
}
125+
126+
104127
public:
105128
//! @{
106129
virtual ~IMEXSweeper()
@@ -173,9 +196,16 @@ namespace pfasst
173196
virtual void setup(bool coarse) override
174197
{
175198
auto nodes = this->get_nodes();
199+
auto is_proper = this->get_is_proper();
176200
assert(nodes.size() >= 1);
177201

178-
this->s_mat = compute_quadrature(nodes, nodes, 's');
202+
this->s_mat = compute_quadrature(nodes, nodes, is_proper, 's');
203+
204+
auto q_mat = compute_quadrature(nodes, nodes, is_proper, 'q');
205+
this->b_mat = matrix<time>(1, nodes.size());
206+
for (size_t m = 0; m < nodes.size(); m++) {
207+
this->b_mat(0, m) = q_mat(nodes.size() - 2, m);
208+
}
179209

180210
this->s_mat_expl = this->s_mat;
181211
this->s_mat_impl = this->s_mat;
@@ -190,6 +220,7 @@ namespace pfasst
190220
if (coarse) {
191221
this->previous_u_state.push_back(this->get_factory()->create(pfasst::encap::solution));
192222
}
223+
// XXX: can prolly save some f's here for virtual nodes...
193224
this->fs_expl.push_back(this->get_factory()->create(pfasst::encap::function));
194225
this->fs_impl.push_back(this->get_factory()->create(pfasst::encap::function));
195226
}
@@ -211,14 +242,11 @@ namespace pfasst
211242
time dt = this->get_controller()->get_time_step();
212243
time t = this->get_controller()->get_time();
213244

214-
if (initial) {
215-
this->f_expl_eval(this->fs_expl[0], this->u_state[0], t);
216-
this->f_impl_eval(this->fs_impl[0], this->u_state[0], t);
217-
}
245+
if (initial) { this->evaluate(0); }
218246

219247
shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
220248

221-
for (size_t m = 0; m < nnodes - 1; m++) {
249+
for (size_t m = 0; m < nnodes - (this->last_node_is_virtual() ? 2 : 1); m++) {
222250
time ds = dt * (nodes[m + 1] - nodes[m]);
223251
rhs->copy(this->u_state[m]);
224252
rhs->saxpy(ds, this->fs_expl[m]);
@@ -227,6 +255,8 @@ namespace pfasst
227255

228256
t += ds;
229257
}
258+
259+
if (this->last_node_is_virtual()) { this->integrate_end_state(dt); }
230260
}
231261

232262
virtual void sweep()
@@ -250,7 +280,7 @@ namespace pfasst
250280
// sweep
251281
shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
252282

253-
for (size_t m = 0; m < nnodes - 1; m++) {
283+
for (size_t m = 0; m < nnodes - (this->last_node_is_virtual() ? 2 : 1); m++) {
254284
time ds = dt * (nodes[m + 1] - nodes[m]);
255285

256286
rhs->copy(this->u_state[m]);
@@ -261,6 +291,8 @@ namespace pfasst
261291

262292
t += ds;
263293
}
294+
295+
if (this->last_node_is_virtual()) { this->integrate_end_state(dt); }
264296
}
265297

266298
virtual void advance() override
@@ -281,11 +313,23 @@ namespace pfasst
281313
}
282314
}
283315

316+
/**
317+
* @copybrief EncapSweeper::evaluate()
318+
*
319+
* If the node `m` is virtual (not proper), we can save some
320+
* implicit/explicit evaluations.
321+
*/
284322
virtual void evaluate(size_t m) override
285323
{
286-
time t = this->get_nodes()[m]; // XXX
287-
this->f_expl_eval(this->fs_expl[m], this->u_state[m], t);
288-
this->f_impl_eval(this->fs_impl[m], this->u_state[m], t);
324+
time t0 = this->get_controller()->get_time();
325+
time dt = this->get_controller()->get_time_step();
326+
time t = t0 + dt * this->get_nodes()[m];
327+
if ((m == 0) || this->get_is_proper()[m]) {
328+
this->f_expl_eval(this->fs_expl[m], this->u_state[m], t);
329+
}
330+
if (this->get_is_proper()[m]) {
331+
this->f_impl_eval(this->fs_impl[m], this->u_state[m], t);
332+
}
289333
}
290334

291335
/**

0 commit comments

Comments
 (0)