10 #ifndef TEMPUS_CONVERGENCE_TEST_UTILS_HPP
11 #define TEMPUS_CONVERGENCE_TEST_UTILS_HPP
19 #include "Tempus_Stepper.hpp"
21 namespace Tempus_Test {
26 template <
class Scalar>
30 void setData(std::vector<Scalar>& x, std::vector<Scalar>& y);
40 std::vector<Scalar>
x_;
41 std::vector<Scalar>
y_;
49 template <
class Scalar>
52 isInitialized_ =
false;
55 template <
class Scalar>
57 std::vector<Scalar>& y)
59 validateXYData_(x, y);
62 isInitialized_ =
true;
66 template <
class Scalar>
68 std::vector<Scalar>& y)
71 x.size() != y.size(), std::logic_error,
72 "x and y data are note the same size for linear regression\n");
74 "Not enough data points for linear regression!\n");
75 int N = Teuchos::as<int>(x.size());
79 for (
int i = 1; i < N; ++i) {
87 template <
class Scalar>
94 template <
class Scalar>
101 template <
class Scalar>
107 int N = Teuchos::as<int>(x_.size());
109 Scalar sum1 = ST::zero();
110 Scalar sum2 = ST::zero();
111 for (
int i = 0; i < N; ++i) {
112 sum1 += x_[i] * y_[i];
113 sum2 += x_[i] * x_[i];
115 sum1 *= Scalar(-2 * ST::one());
116 sum2 *= Scalar(-2 * ST::one());
118 Scalar sum3 = ST::zero();
119 Scalar sum4 = ST::zero();
120 for (
int i = 0; i < N; ++i) {
121 for (
int j = 0; j < N; ++j) {
122 sum3 += x_[i] * y_[j];
123 sum4 += x_[i] * x_[j];
126 sum3 *= Scalar(2 * ST::one() / Scalar(N));
127 sum4 *= Scalar(2 * ST::one() / Scalar(N));
129 slope_ = (sum3 + sum1) / (sum4 + sum2);
131 yIntercept_ = ST::zero();
132 for (
int i = 0; i < N; ++i) {
133 yIntercept_ += y_[i] - slope_ * x_[i];
135 yIntercept_ *= Scalar(ST::one() / Scalar(N));
139 template <
class Scalar>
147 template <
class Scalar>
149 Scalar& slope, Scalar& yIntercept)
158 template <
class Scalar>
160 std::vector<Scalar>& y)
163 int N = Teuchos::as<int>(x.size());
164 std::vector<Scalar> xlog;
165 std::vector<Scalar> ylog;
167 for (
int i = 0; i < N; ++i) {
169 xlog.push_back(log(x[i]));
170 ylog.push_back(log(y[i]));
179 template <
class Scalar>
187 template <
class Scalar>
190 std::vector<Scalar>& StepSize,
192 std::vector<Scalar>& xErrorNorm, Scalar& xSlope,
194 std::vector<Scalar>& xDotErrorNorm, Scalar& xDotSlope,
196 std::vector<Scalar>& xDotDotErrorNorm, Scalar& xDotDotSlope,
199 if (solutions.empty()) {
200 out <<
"No solutions to write out!\n"
204 std::size_t lastElem = solutions.size() - 1;
205 std::vector<Scalar> dt;
207 auto ref_solution = solutions[lastElem];
208 for (std::size_t i = 0; i < lastElem; ++i) {
209 dt.push_back(StepSize[i]);
210 auto tmp = solutions[i];
211 Thyra::Vp_StV(tmp.ptr(), -1.0, *ref_solution);
212 Scalar L2norm = Thyra::norm_2(*tmp);
213 xErrorNorm.push_back(L2norm);
215 xSlope = computeLinearRegressionLogLog<Scalar>(dt, xErrorNorm);
217 if (!solutionsDot.empty()) {
218 auto ref_solutionDot = solutionsDot[lastElem];
219 for (std::size_t i = 0; i < lastElem; ++i) {
220 auto tmp = solutionsDot[i];
221 Thyra::Vp_StV(tmp.ptr(), -1.0, *ref_solutionDot);
222 Scalar L2norm = Thyra::norm_2(*tmp);
223 xDotErrorNorm.push_back(L2norm);
225 xDotSlope = computeLinearRegressionLogLog<Scalar>(dt, xDotErrorNorm);
228 if (!solutionsDotDot.empty()) {
229 auto ref_solutionDotDot = solutionsDotDot[solutions.size() - 1];
230 for (std::size_t i = 0; i < lastElem; ++i) {
231 auto tmp = solutionsDotDot[i];
232 Thyra::Vp_StV(tmp.ptr(), -1.0, *ref_solutionDotDot);
233 Scalar L2norm = Thyra::norm_2(*tmp);
234 xDotDotErrorNorm.push_back(L2norm);
236 xDotDotSlope = computeLinearRegressionLogLog<Scalar>(dt, xDotDotErrorNorm);
239 Scalar order = stepper->getOrder();
240 out <<
" Stepper = " << stepper->description() << std::endl;
241 out <<
" =================================" << std::endl;
242 out <<
" Expected Order = " << order << std::endl;
243 out <<
" x Order = " << xSlope << std::endl;
244 if (!solutionsDot.empty())
245 out <<
" xDot Order = " << xDotSlope << std::endl;
246 if (!solutionsDotDot.empty())
247 out <<
" xDotDot Order = " << xDotDotSlope << std::endl;
248 out <<
" =================================" << std::endl;
250 std::ofstream ftmp(filename);
252 for (std::size_t n = 0; n < lastElem; n++) {
253 factor = 0.8 * (pow(dt[n] / dt[0], order));
254 ftmp << dt[n] <<
" " << xErrorNorm[n] <<
" " << factor * xErrorNorm[0];
255 if (xDotErrorNorm.size() == lastElem)
256 ftmp <<
" " << xDotErrorNorm[n] <<
" " << factor * xDotErrorNorm[0];
257 if (xDotDotErrorNorm.size() == lastElem)
258 ftmp <<
" " << xDotDotErrorNorm[n] <<
" "
259 << factor * xDotDotErrorNorm[0];
265 template <
class Scalar>
268 std::vector<Scalar>& StepSize,
270 std::vector<Scalar>& xErrorNorm, Scalar& xSlope,
272 std::vector<Scalar>& xDotErrorNorm, Scalar& xDotSlope,
275 std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar>>> solutionsDotDot;
276 std::vector<Scalar> xDotDotErrorNorm;
277 Scalar xDotDotSlope = Scalar(0.0);
278 writeOrderError(filename, stepper, StepSize, solutions, xErrorNorm, xSlope,
279 solutionsDot, xDotErrorNorm, xDotSlope, solutionsDotDot,
280 xDotDotErrorNorm, xDotDotSlope, out);
283 template <
class Scalar>
286 std::vector<Scalar>& StepSize,
290 std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar>>> solutionsDot;
291 std::vector<Scalar> xDotErrorNorm;
292 Scalar xDotSlope = Scalar(0.0);
293 std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar>>> solutionsDotDot;
294 std::vector<Scalar> xDotDotErrorNorm;
295 Scalar xDotDotSlope = Scalar(0.0);
296 writeOrderError(filename, stepper, StepSize, solutions, xErrorNorm, xSlope,
297 solutionsDot, xDotErrorNorm, xDotSlope, solutionsDotDot,
298 xDotDotErrorNorm, xDotDotSlope, out);
301 template <
class Scalar>
303 const std::string filename,
306 std::ofstream ftmp(filename);
310 for (
int i = 0; i < solutionHistory->getNumStates(); i++) {
312 (*solutionHistory)[i];
313 Scalar time = solutionState->getTime();
314 x = solutionState->getX();
315 xDot = solutionState->getXDot();
316 xDotDot = solutionState->getXDotDot();
317 int J = x->space()->dim();
320 for (
int j = 0; j < J; j++) ftmp <<
" " << get_ele(*x, j);
321 if (xDot != Teuchos::null)
322 for (
int j = 0; j < J; j++) ftmp <<
" " << get_ele(*xDot, j);
323 if (xDotDot != Teuchos::null)
324 for (
int j = 0; j < J; j++) ftmp <<
" " << get_ele(*xDotDot, j);
330 template <
class Scalar>
332 const std::string filename,
341 #endif // TEMPUS_CONVERGENCE_TEST_UTILS_HPP
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Scalar getYIntercept() const
void writeOrderError(const std::string filename, Teuchos::RCP< Tempus::Stepper< Scalar >> stepper, std::vector< Scalar > &StepSize, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutions, std::vector< Scalar > &xErrorNorm, Scalar &xSlope, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutionsDot, std::vector< Scalar > &xDotErrorNorm, Scalar &xDotSlope, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutionsDotDot, std::vector< Scalar > &xDotDotErrorNorm, Scalar &xDotDotSlope, Teuchos::FancyOStream &out)
void writeSolution(const std::string filename, Teuchos::RCP< const Tempus::SolutionHistory< Scalar >> solutionHistory)
Thyra Base interface for time steppers.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Scalar computeLinearRegressionLogLog(std::vector< Scalar > &x, std::vector< Scalar > &y)
Teuchos::RCP< LinearRegression< Scalar > > linearRegression()
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
void validateXYData_(std::vector< Scalar > &x, std::vector< Scalar > &y)
Scalar computeLinearRegression(std::vector< Scalar > &x, std::vector< Scalar > &y)
void setData(std::vector< Scalar > &x, std::vector< Scalar > &y)
bool approxZero(Scalar value, Scalar tol=Teuchos::ScalarTraits< Scalar >::sfmin())
Test if value is approximately zero within tolerance.
Linear regression class. Copied and modified from Rythmos.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)