@@ -66,28 +66,12 @@ class ParsedFunction : public FunctionBase<Output>
66
66
const std::vector<Output> * initial_vals=nullptr );
67
67
68
68
/* *
69
- * This class cannot be (default) copy assigned because the
70
- * underlying FunctionParserADBase class does not define a custom
71
- * copy assignment operator, and manually manages memory.
69
+ * Special functions
70
+ * - This class contains unique_ptrs so it can't be default copy constructed or assigned.
72
71
*/
73
- ParsedFunction & operator = (const ParsedFunction &) = delete ;
74
-
75
- /* *
76
- * The remaining special functions can be defaulted for this class.
77
- *
78
- * \note Despite the fact that the underlying FunctionParserADBase
79
- * class is not move-assignable or move-constructible, it is still
80
- * possible for _this_ class to be move-assigned and
81
- * move-constructed, because FunctionParserADBase objects only
82
- * appear within std::vectors in this class, and std::vectors can
83
- * generally still be move-assigned and move-constructed even when
84
- * their contents cannot. There are some allocator-specific
85
- * exceptions to this, but it should be guaranteed to work for
86
- * std::allocator in C++14 and beyond. See also:
87
- * https://stackoverflow.com/q/42051917/659433
88
- */
89
- ParsedFunction (const ParsedFunction &) = default ;
72
+ ParsedFunction (const ParsedFunction &) = delete ;
90
73
ParsedFunction (ParsedFunction &&) = default ;
74
+ ParsedFunction & operator = (const ParsedFunction &) = delete ;
91
75
ParsedFunction & operator = (ParsedFunction &&) = default ;
92
76
virtual ~ParsedFunction () = default ;
93
77
@@ -183,18 +167,18 @@ class ParsedFunction : public FunctionBase<Output>
183
167
184
168
std::string _expression;
185
169
std::vector<std::string> _subexpressions;
186
- std::vector<FunctionParserADBase<Output>> parsers;
170
+ std::vector<std::unique_ptr< FunctionParserADBase<Output> >> parsers;
187
171
std::vector<Output> _spacetime;
188
172
189
173
// derivative functions
190
- std::vector<FunctionParserADBase<Output>> dx_parsers;
174
+ std::vector<std::unique_ptr< FunctionParserADBase<Output> >> dx_parsers;
191
175
#if LIBMESH_DIM > 1
192
- std::vector<FunctionParserADBase<Output>> dy_parsers;
176
+ std::vector<std::unique_ptr< FunctionParserADBase<Output> >> dy_parsers;
193
177
#endif
194
178
#if LIBMESH_DIM > 2
195
- std::vector<FunctionParserADBase<Output>> dz_parsers;
179
+ std::vector<std::unique_ptr< FunctionParserADBase<Output> >> dz_parsers;
196
180
#endif
197
- std::vector<FunctionParserADBase<Output>> dt_parsers;
181
+ std::vector<std::unique_ptr< FunctionParserADBase<Output> >> dt_parsers;
198
182
bool _valid_derivatives;
199
183
200
184
// Variables/values that can be parsed and handled by the function parser
@@ -262,7 +246,7 @@ Output
262
246
ParsedFunction<Output,OutputGradient>::operator () (const Point & p, const Real time)
263
247
{
264
248
set_spacetime (p, time );
265
- return eval (parsers[0 ], " f" , 0 );
249
+ return eval (* parsers[0 ], " f" , 0 );
266
250
}
267
251
268
252
template <typename Output, typename OutputGradient>
@@ -271,7 +255,7 @@ Output
271
255
ParsedFunction<Output,OutputGradient>::dot (const Point & p, const Real time)
272
256
{
273
257
set_spacetime (p, time );
274
- return eval (dt_parsers[0 ], " df/dt" , 0 );
258
+ return eval (* dt_parsers[0 ], " df/dt" , 0 );
275
259
}
276
260
277
261
template <typename Output, typename OutputGradient>
@@ -282,12 +266,12 @@ ParsedFunction<Output,OutputGradient>::gradient (const Point & p, const Real tim
282
266
OutputGradient grad;
283
267
set_spacetime (p, time );
284
268
285
- grad (0 ) = eval (dx_parsers[0 ], " df/dx" , 0 );
269
+ grad (0 ) = eval (* dx_parsers[0 ], " df/dx" , 0 );
286
270
#if LIBMESH_DIM > 1
287
- grad (1 ) = eval (dy_parsers[0 ], " df/dy" , 0 );
271
+ grad (1 ) = eval (* dy_parsers[0 ], " df/dy" , 0 );
288
272
#endif
289
273
#if LIBMESH_DIM > 2
290
- grad (2 ) = eval (dz_parsers[0 ], " df/dz" , 0 );
274
+ grad (2 ) = eval (* dz_parsers[0 ], " df/dz" , 0 );
291
275
#endif
292
276
293
277
return grad;
@@ -310,7 +294,7 @@ ParsedFunction<Output,OutputGradient>::operator()
310
294
// The remaining locations in _spacetime are currently fixed at construction
311
295
// but could potentially be made dynamic
312
296
for (unsigned int i=0 ; i != size; ++i)
313
- output (i) = eval (parsers[i], " f" , i);
297
+ output (i) = eval (* parsers[i], " f" , i);
314
298
}
315
299
316
300
/* *
@@ -330,7 +314,7 @@ ParsedFunction<Output,OutputGradient>::component (unsigned int i,
330
314
// The remaining locations in _spacetime are currently fixed at construction
331
315
// but could potentially be made dynamic
332
316
libmesh_assert_less (i, parsers.size ());
333
- return eval (parsers[i], " f" , i);
317
+ return eval (* parsers[i], " f" , i);
334
318
}
335
319
336
320
/* *
@@ -541,51 +525,53 @@ ParsedFunction<Output,OutputGradient>::partial_reparse (const std::string & expr
541
525
542
526
// Parse (and optimize if possible) the subexpression.
543
527
// Add some basic constants, to Real precision.
544
- FunctionParserADBase<Output> fp ;
545
- fp. AddConstant (" NaN" , std::numeric_limits<Real>::quiet_NaN ());
546
- fp. AddConstant (" pi" , std::acos (Real (-1 )));
547
- fp. AddConstant (" e" , std::exp (Real (1 )));
528
+ auto fp = libmesh_make_unique< FunctionParserADBase<Output>>() ;
529
+ fp-> AddConstant (" NaN" , std::numeric_limits<Real>::quiet_NaN ());
530
+ fp-> AddConstant (" pi" , std::acos (Real (-1 )));
531
+ fp-> AddConstant (" e" , std::exp (Real (1 )));
548
532
libmesh_error_msg_if
549
- (fp. Parse (_subexpressions.back (), variables) != -1 , // -1 for success
533
+ (fp-> Parse (_subexpressions.back (), variables) != -1 , // -1 for success
550
534
" ERROR: FunctionParser is unable to parse expression: "
551
- << _subexpressions.back () << ' \n ' << fp. ErrorMsg ());
535
+ << _subexpressions.back () << ' \n ' << fp-> ErrorMsg ());
552
536
553
537
// use of derivatives is optional. suppress error output on the console
554
538
// use the has_derivatives() method to check if AutoDiff was successful.
555
539
// also enable immediate optimization
556
- fp. SetADFlags (FunctionParserADBase<Output>::ADSilenceErrors |
540
+ fp-> SetADFlags (FunctionParserADBase<Output>::ADSilenceErrors |
557
541
FunctionParserADBase<Output>::ADAutoOptimize);
558
542
559
543
// optimize original function
560
- fp.Optimize ();
561
- parsers.push_back (fp);
544
+ fp->Optimize ();
562
545
563
546
// generate derivatives through automatic differentiation
564
- FunctionParserADBase<Output> dx_fp ( fp);
565
- if (dx_fp. AutoDiff (" x" ) != -1 ) // -1 for success
547
+ auto dx_fp = libmesh_make_unique< FunctionParserADBase<Output>>(* fp);
548
+ if (dx_fp-> AutoDiff (" x" ) != -1 ) // -1 for success
566
549
_valid_derivatives = false ;
567
- dx_parsers.push_back (dx_fp);
550
+ dx_parsers.push_back (std::move ( dx_fp) );
568
551
#if LIBMESH_DIM > 1
569
- FunctionParserADBase<Output> dy_fp ( fp);
570
- if (dy_fp. AutoDiff (" y" ) != -1 ) // -1 for success
552
+ auto dy_fp = libmesh_make_unique< FunctionParserADBase<Output>>(* fp);
553
+ if (dy_fp-> AutoDiff (" y" ) != -1 ) // -1 for success
571
554
_valid_derivatives = false ;
572
- dy_parsers.push_back (dy_fp);
555
+ dy_parsers.push_back (std::move ( dy_fp) );
573
556
#endif
574
557
#if LIBMESH_DIM > 2
575
- FunctionParserADBase<Output> dz_fp ( fp);
576
- if (dz_fp. AutoDiff (" z" ) != -1 ) // -1 for success
558
+ auto dz_fp = libmesh_make_unique< FunctionParserADBase<Output>>(* fp);
559
+ if (dz_fp-> AutoDiff (" z" ) != -1 ) // -1 for success
577
560
_valid_derivatives = false ;
578
- dz_parsers.push_back (dz_fp);
561
+ dz_parsers.push_back (std::move ( dz_fp) );
579
562
#endif
580
- FunctionParserADBase<Output> dt_fp ( fp);
581
- if (dt_fp. AutoDiff (" t" ) != -1 ) // -1 for success
563
+ auto dt_fp = libmesh_make_unique< FunctionParserADBase<Output>>(* fp);
564
+ if (dt_fp-> AutoDiff (" t" ) != -1 ) // -1 for success
582
565
_valid_derivatives = false ;
583
- dt_parsers.push_back (dt_fp);
566
+ dt_parsers.push_back (std::move ( dt_fp) );
584
567
585
568
// If at end, use nextstart=maxSize. Else start at next
586
569
// character.
587
570
nextstart = (end == std::string::npos) ?
588
571
std::string::npos : end + 1 ;
572
+
573
+ // Store fp for later use
574
+ parsers.push_back (std::move (fp));
589
575
}
590
576
}
591
577
0 commit comments