Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F121136004
MultistepAbstractSolver.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, Jul 8, 21:29
Size
4 KB
Mime Type
text/x-c
Expires
Thu, Jul 10, 21:29 (2 d)
Engine
blob
Format
Raw Data
Handle
27289525
Attached To
R9686 PCSCproject
MultistepAbstractSolver.cpp
View Options
#include "MultistepAbstractSolver.h"
MultistepAbstractSolver
::
MultistepAbstractSolver
(){
initialTime
=
0
;
finalTime
=
0
;
nSteps
=
0
;
stepSize
=
0
;
stepsAlgo
=
0
;
dimension
=
0
;
convergenceRate
=
0
;
};
MultistepAbstractSolver
::
MultistepAbstractSolver
(
double
t0
,
double
tf
,
int
n
,
int
steps
,
Eigen
::
VectorXd
&
y0
)
:
AbstractSolver
(
t0
,
tf
,
n
,
y0
)
{
stepsAlgo
=
steps
;
yInitialConditions
.
push_back
(
y0
);
};
int
MultistepAbstractSolver
::
getStepsAlgo
(){
return
stepsAlgo
;
};
void
MultistepAbstractSolver
::
computeMissingInitialValues
(
int
orderRK
){
//The coefficients for computing missing initial conditions through Runge Kutta are initialized.
Eigen
::
Vector4d
aCoeff
;
switch
(
orderRK
){
case
0
:
{
rhsPreviousSteps
.
clear
();
Eigen
::
VectorXd
rhsStart
=
A
*
initialValue
+
g
(
initialTime
);
rhsPreviousSteps
.
push_back
(
rhsStart
);
return
;
}
break
;
case
1
:
aCoeff
[
0
]
=
1
,
aCoeff
[
1
]
=
0
,
aCoeff
[
2
]
=
0
,
aCoeff
[
3
]
=
0
;
break
;
case
2
:
aCoeff
[
0
]
=
0.5
,
aCoeff
[
1
]
=
0.5
,
aCoeff
[
2
]
=
0
,
aCoeff
[
3
]
=
0
;
break
;
case
3
:
aCoeff
[
0
]
=
1.
/
6.
,
aCoeff
[
1
]
=
4.
/
6.
,
aCoeff
[
2
]
=
1.
/
6.
,
aCoeff
[
3
]
=
0
;
break
;
case
4
:
aCoeff
[
0
]
=
1.
/
4.
,
aCoeff
[
1
]
=
1.
/
4.
,
aCoeff
[
2
]
=
1.
/
4.
,
aCoeff
[
3
]
=
1.
/
4.
;
break
;
default
:
throw
std
::
runtime_error
(
"Order orderRK required too high. Try using a multistep method with fewer steps."
);
}
auto
yPrev
=
initialValue
;
auto
tPrev
=
initialTime
;
//rhsPreviousSteps list is cleared and first value is stored. Need of clearing it comes from test function.
rhsPreviousSteps
.
clear
();
Eigen
::
VectorXd
rhsStart
=
A
*
initialValue
+
g
(
initialTime
);
rhsPreviousSteps
.
push_back
(
rhsStart
);
// k1, k2, k3, k4 define the updates of RK
Eigen
::
VectorXd
k1
(
dimension
),
k2
(
dimension
),
k3
(
dimension
),
k4
(
dimension
);
k2
.
setZero
(),
k3
.
setZero
(),
k4
.
setZero
();
int
initialConditionsNeeded
=
orderRK
;
if
(
stepsAlgo
==
convergenceRate
-
1
)
initialConditionsNeeded
-=
1
;
for
(
int
i
=
0
;
i
<
initialConditionsNeeded
;
i
++
){
k1
=
A
*
yPrev
+
g
(
tPrev
);
//k2, k3, k4 are computed only if a higher order RK method is needed.
if
(
orderRK
>
1
)
k2
=
A
*
(
yPrev
+
0.5
*
stepSize
*
k1
)
+
g
(
tPrev
+
0.5
*
stepSize
);
// With this choice, the order 2 method corresponds to Euler's modified method.
if
(
orderRK
>
2
)
k3
=
A
*
(
yPrev
+
stepSize
*
(
-
1
*
k1
+
2
*
k2
))
+
g
(
tPrev
+
stepSize
);
// This choice for k3 allows us to "recycle" k1, k2, obtaining a 3rd order RK.
if
(
orderRK
>
3
)
{
k3
=
A
*
(
yPrev
+
0.5
*
stepSize
*
k2
)
+
g
(
tPrev
+
0.5
*
stepSize
);
k4
=
A
*
(
yPrev
+
stepSize
*
k3
)
+
g
(
tPrev
+
stepSize
);
}
//computation of a missing initial condition.
Eigen
::
VectorXd
yNext
=
yPrev
+
stepSize
*
(
aCoeff
[
0
]
*
k1
+
aCoeff
[
1
]
*
k2
+
aCoeff
[
2
]
*
k3
+
aCoeff
[
3
]
*
k4
);
//rhs function evaluated and stored in rhsPreviousSteps.
Eigen
::
VectorXd
rhsNext
=
A
*
yNext
+
g
(
tPrev
+
stepSize
);
rhsPreviousSteps
.
push_back
(
rhsNext
);
//The computed missing initial condition is stored in the list yInitialConditions.
yInitialConditions
.
push_back
(
yNext
);
yPrev
=
yNext
;
tPrev
+=
stepSize
;
}
}
void
MultistepAbstractSolver
::
solve
(
std
::
ostream
&
stream
){
yInitialConditions
.
clear
();
yInitialConditions
.
push_back
(
initialValue
);
// The missing initial values are computed, with a suitable one step algorithm.
if
(
stepsAlgo
==
convergenceRate
-
1
)
// For implicit method AdamsMoulton, a higher order RK method is needed to compute the missing initial values.
computeMissingInitialValues
(
convergenceRate
-
1
);
else
// For AdamsBashforth, BDF, stepsAlgo==convergenceRate therefore a lower RK is needed w.r.t. AdamsMoulton.
computeMissingInitialValues
(
stepsAlgo
-
1
);
//The initial conditions computed with computeMissingInitialValues are streamed to the output stream chosen by the user.
int
count
=
0
;
auto
it
=
yInitialConditions
.
begin
();
for
(
it
=
yInitialConditions
.
begin
();
it
!=
yInitialConditions
.
end
();
it
++
){
stream
<<
initialTime
+
stepSize
*
count
<<
" "
<<
(
*
it
).
transpose
()
<<
"
\n
"
;
count
++
;
}
// t is the time at which y has to be computed at each step; y is initialized with the value of the last missing initial
// condition computed; its value is progressively changed by the algorithm's iterations.
double
t
=
initialTime
+
stepSize
*
(
stepsAlgo
-
1
);
Eigen
::
VectorXd
y
=
yInitialConditions
.
back
();
// nSteps-stepsAlgo steps are needed because missing initial conditions have already been computed.
for
(
int
i
=
0
;
i
<=
nSteps
-
stepsAlgo
;
i
++
)
{
step
(
y
,
t
);
stream
<<
initialTime
+
stepSize
*
(
i
+
stepsAlgo
)
<<
" "
<<
y
.
transpose
()
<<
"
\n
"
;
t
+=
stepSize
;
}
}
//void MultistepAbstractSolver::step(Eigen::VectorXd &y, double t) {
// throw std::runtime_error("function step not implemented in MultistepAbstractSolver: it's a purely virtual method, implemented in the daughter classes.");
//}
Event Timeline
Log In to Comment