Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102273353
AbstractSolver.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Feb 18, 23:56
Size
6 KB
Mime Type
text/x-c
Expires
Thu, Feb 20, 23:56 (2 d)
Engine
blob
Format
Raw Data
Handle
24320721
Attached To
R9686 PCSCproject
AbstractSolver.cpp
View Options
//
// Created by lionel on 25.11.19.
//
#include <cassert>
#include <sstream>
#include <iostream>
#include "AbstractSolver.h"
AbstractSolver::AbstractSolver(){
stepSize=0;
initialTime=0;
finalTime=0;
dimension=0;
nSteps=0;
};
AbstractSolver::AbstractSolver(double t0,double tf,int n,Eigen::VectorXd& y0):AbstractSolver(){
setInitialTime(t0);
setFinalTime(tf);
setNumberOfSteps(n);
setInitialValue(y0);
}
AbstractSolver::~AbstractSolver(){};
void AbstractSolver::setInitialTime(const double t0) {
initialTime = t0;
}
void AbstractSolver::setFinalTime(const double tf) {
finalTime = tf;
}
void AbstractSolver::setStepSize(const double h) {
checkStepSize(h);
if (stepSize!=0){ // need to warn user that the stepsize was changed to avoid confusion
std::cerr << "[WARNING] : Step size " << stepSize << " was already assigned, new step size is now " << h << std::endl;
}
stepSize = h;
}
void AbstractSolver::checkStepSize(double h) {
if (h <= 0) { // negative step size will make our solver fail
throw std::domain_error("Step size h must be strictly positive");
}
}
void AbstractSolver::checkTimes() {
if (finalTime <= initialTime){ // final time must be larger for the solve method to work
throw std::domain_error("Initial time is not smaller than the final time.");
}
}
void AbstractSolver::setNumberOfSteps(int n){
if (n < 1){
throw std::domain_error("Number of step must be strictly positive ");
} else {
double h = (finalTime - initialTime)/ (double) n; // linearly spaced steps
setStepSize(h);
}
nSteps=n;
}
void AbstractSolver::checkSpaceDimension(int dim) {
if (dim < 1) {
throw std::domain_error("Dimension must be greater than 0");
} else{
if (dimension == 0) { // the dimension was never specified if it is 0, so we set it to dim
dimension = dim;
} else if (dimension != dim){ // return an error with the conflicting values of dimension
std::stringstream errorMessage;
errorMessage << "Invalid dimension : " << dim << ", it was already assigned " << dimension << ".";
throw std::length_error(errorMessage.str());
} else { // do nothing if the values of dimension match
;
}
}
}
void AbstractSolver::setInitialValue(Eigen::VectorXd & y0) {
// check it is a valid input
checkSpaceDimension(y0.size());
initialValue = y0;
}
void AbstractSolver::setRightHandSide(Eigen::MatrixXd & rhsMatrix, Eigen::VectorXd (*g_)(double t)){
// check the right hand side matrix is valid before storing it
try {
checkSpaceDimension(rhsMatrix.rows());
checkSpaceDimension(rhsMatrix.cols());
} catch (const std::length_error& e){
std::stringstream errorMessage; // creates a more complex message to help the user correcting his error
errorMessage << "The linear Matrix has dimension ("<< rhsMatrix.rows() <<","<< rhsMatrix.cols() <<
") which is invalid : "<< e.what();
throw std::length_error(errorMessage.str());
}
A = rhsMatrix;
// check if the function is callable and that it returns object of desired dimension
try {
// checks if no exception happens for final and initial time, hope no exception will happen for in between times
auto testVector = g_(initialTime);
auto testVectorCopy = g_(finalTime);
} catch(const std::exception& e) {
std::stringstream errorMessage;
errorMessage << "Function g(t) could not be evaluated, an exception was caught with message : " << e.what();
throw std::runtime_error(errorMessage.str());
} catch (...) { // any other type of error will make our solver fail
throw std::runtime_error("Function g(t) could not be evaluated. No exception was caught.");
}
// checks the output of g is in the required format
try {
checkSpaceDimension(g_(initialTime).size());
} catch (const std::length_error& e){
std::stringstream errorMessage;
errorMessage << "Function g(t) has invalid dimension in output : " << e.what();
throw std::length_error(errorMessage.str());
}
g = g_;
}
double AbstractSolver::getInitialTime() const{
return initialTime;
}
double AbstractSolver::getFinalTime() const{
return finalTime;
}
double AbstractSolver::getStepSize() const{
return stepSize;
}
int AbstractSolver::getSpaceDimension() const {
return dimension;
}
void AbstractSolver::solve(std::ostream &stream) {
auto y = initialValue;
double t = initialTime;
assert(initialTime < finalTime && stepSize > 0); // ensures next while loop will not be infinite
stream << t << " " << y.transpose() << std::endl; //write the initial time
while(t< finalTime){
step(y,t); // step updates the y values
t += stepSize;
stream << t << " " << y.transpose() << std::endl;
}
}
void AbstractSolver::setRightHandSide(Eigen::MatrixXd &rhsMatrix, std::function<Eigen::VectorXd(double)> g_) {
// check the right hand side matrix is valid before storing it
try {
checkSpaceDimension(rhsMatrix.rows());
checkSpaceDimension(rhsMatrix.cols());
} catch (const std::length_error& e){
std::stringstream errorMessage; // creates a more complex message to help the user correcting his error
errorMessage << "The linear Matrix has dimension ("<< rhsMatrix.rows() <<","<< rhsMatrix.cols() <<
") which is invalid : "<< e.what();
throw std::length_error(errorMessage.str());
}
A = rhsMatrix;
// check if the function is callable and that it returns object of desired dimension
try {
// checks if no exception happens for final and initial time, hope no exception will happen for in between times
auto testVector = g_(initialTime);
auto testVectorCopy = g_(finalTime);
} catch(const std::exception& e) {
std::stringstream errorMessage;
errorMessage << "Function g(t) could not be evaluated, an exception was caught with message : " << e.what();
throw std::runtime_error(errorMessage.str());
} catch (...) { // any other type of error will make our solver fail
throw std::runtime_error("Function g(t) could not be evaluated. No exception was caught.");
}
// checks the output of g is in the required format
try {
checkSpaceDimension(g_(initialTime).size());
} catch (const std::length_error& e){
std::stringstream errorMessage;
errorMessage << "Function g(t) has invalid dimension in output : " << e.what();
throw std::length_error(errorMessage.str());
}
g = g_;
}
Event Timeline
Log In to Comment