@@ -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 ()
@@ -178,6 +201,12 @@ namespace pfasst
178201
179202 this ->s_mat = compute_quadrature (nodes, nodes, is_proper, ' s' );
180203
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+ }
209+
181210 this ->s_mat_expl = this ->s_mat ;
182211 this ->s_mat_impl = this ->s_mat ;
183212 for (size_t m = 0 ; m < nodes.size () - 1 ; m++) {
@@ -191,7 +220,12 @@ namespace pfasst
191220 if (coarse) {
192221 this ->previous_u_state .push_back (this ->get_factory ()->create (pfasst::encap::solution));
193222 }
194- this ->fs_expl .push_back (this ->get_factory ()->create (pfasst::encap::function));
223+ // XXX: can prolly save some f's here...
224+ // if ((m == 0) || this->get_is_proper()[m]) {
225+ this ->fs_expl .push_back (this ->get_factory ()->create (pfasst::encap::function));
226+ // } else {
227+ // this->fs_expl.push_back(nullptr);
228+ // }
195229 this ->fs_impl .push_back (this ->get_factory ()->create (pfasst::encap::function));
196230 }
197231
@@ -212,14 +246,11 @@ namespace pfasst
212246 time dt = this ->get_controller ()->get_time_step ();
213247 time t = this ->get_controller ()->get_time ();
214248
215- if (initial) {
216- this ->f_expl_eval (this ->fs_expl [0 ], this ->u_state [0 ], t);
217- this ->f_impl_eval (this ->fs_impl [0 ], this ->u_state [0 ], t);
218- }
249+ if (initial) { this ->evaluate (0 ); }
219250
220251 shared_ptr<Encapsulation<time>> rhs = this ->get_factory ()->create (pfasst::encap::solution);
221252
222- for (size_t m = 0 ; m < nnodes - 1 ; m++) {
253+ for (size_t m = 0 ; m < nnodes - ( this -> last_node_is_virtual () ? 2 : 1 ) ; m++) {
223254 time ds = dt * (nodes[m + 1 ] - nodes[m]);
224255 rhs->copy (this ->u_state [m]);
225256 rhs->saxpy (ds, this ->fs_expl [m]);
@@ -228,6 +259,8 @@ namespace pfasst
228259
229260 t += ds;
230261 }
262+
263+ if (this ->last_node_is_virtual ()) { this ->integrate_end_state (dt); }
231264 }
232265
233266 virtual void sweep ()
@@ -251,7 +284,7 @@ namespace pfasst
251284 // sweep
252285 shared_ptr<Encapsulation<time>> rhs = this ->get_factory ()->create (pfasst::encap::solution);
253286
254- for (size_t m = 0 ; m < nnodes - 1 ; m++) {
287+ for (size_t m = 0 ; m < nnodes - ( this -> last_node_is_virtual () ? 2 : 1 ) ; m++) {
255288 time ds = dt * (nodes[m + 1 ] - nodes[m]);
256289
257290 rhs->copy (this ->u_state [m]);
@@ -262,6 +295,8 @@ namespace pfasst
262295
263296 t += ds;
264297 }
298+
299+ if (this ->last_node_is_virtual ()) { this ->integrate_end_state (dt); }
265300 }
266301
267302 virtual void advance () override
@@ -282,11 +317,23 @@ namespace pfasst
282317 }
283318 }
284319
320+ /* *
321+ * @copybrief EncapSweeper::evaluate()
322+ *
323+ * If the node `m` is virtual (not proper), we can save some
324+ * implicit/explicit evaluations.
325+ */
285326 virtual void evaluate (size_t m) override
286327 {
287- time t = this ->get_nodes ()[m]; // XXX
288- this ->f_expl_eval (this ->fs_expl [m], this ->u_state [m], t);
289- this ->f_impl_eval (this ->fs_impl [m], this ->u_state [m], t);
328+ time t0 = this ->get_controller ()->get_time ();
329+ time dt = this ->get_controller ()->get_time_step ();
330+ time t = t0 + dt * this ->get_nodes ()[m];
331+ if ((m == 0 ) || this ->get_is_proper ()[m]) {
332+ this ->f_expl_eval (this ->fs_expl [m], this ->u_state [m], t);
333+ }
334+ if (this ->get_is_proper ()[m]) {
335+ this ->f_impl_eval (this ->fs_impl [m], this ->u_state [m], t);
336+ }
290337 }
291338
292339 /* *
0 commit comments