Commit 38acae70 authored by niklas.baumgarten's avatar niklas.baumgarten
Browse files

refactoring and fitting MC classes to new main structure

parent 3f846de3
...@@ -32,7 +32,9 @@ void MonteCarlo::updateStatistic() { ...@@ -32,7 +32,9 @@ void MonteCarlo::updateStatistic() {
} }
void MonteCarlo::upscaleU() { void MonteCarlo::upscaleU() {
// TransferMatrix transferMatrix(TransferMatrixGraph(graphs[l - plevel],
// graphs[l - plevel - 1]));
// assemble.AssembleTransfer(transferMatrix);
} }
void MonteCarlo::updateUSum() { void MonteCarlo::updateUSum() {
...@@ -45,9 +47,12 @@ void MonteCarlo::updateUAvg() { ...@@ -45,9 +47,12 @@ void MonteCarlo::updateUAvg() {
class MonteCarloElliptic : public MonteCarlo { class MonteCarloElliptic : public MonteCarlo {
public: public:
MonteCarloElliptic(int l, int dM, bool baseLevel, StochasticFields &stochFields, EllipticAssemble &assemble;
EllipticAssemble &assemble, MatrixGraphs &graphs) :
MonteCarlo(l, dM, baseLevel,stochFields, assemble, graphs) {} MonteCarloElliptic(int l, int dM, bool baseLevel, Meshes &meshes,
StochasticFields &stochFields, MatrixGraphs &graphs,
EllipticAssemble &assemble) : assemble(assemble),
MonteCarlo(l, dM, baseLevel, meshes, stochFields, graphs) {}
void method() override { void method() override {
Date Start; Date Start;
...@@ -56,47 +61,38 @@ public: ...@@ -56,47 +61,38 @@ public:
vout(1) << " with " << dM << " samples" << endl; vout(1) << " with " << dM << " samples" << endl;
stochFields.setCurrentLevel(l); stochFields.setCurrentLevel(l);
Vector u_f(u_sum);
Vector u_c(graphs[l - 2]);
// TransferMatrix transferMatrix(TransferMatrixGraph(graphs[l - 2],
// graphs[l - 1]));
// assemble.AssembleTransfer(transferMatrix);
for (int m = M; m < M + dM; m++) { for (int m = M; m < M + dM; m++) {
stochFields.generate(); stochFields.generate();
if (verbose >= 2) { if (verbose >= 2) {
vout(2) << " Generated field:" << endl; vout(2) << " Generated field:" << endl;
pair<double, double> min_max_f, min_max_c; pair<double, double> min_max_f, min_max_c;
min_max_f = stochFields.getMinMaxValues(); min_max_f = stochFields.getMinMaxValues(true);
vout(2) << " min_f=" << min_max_f.first vout(2) << " min_f=" << min_max_f.first
<< " max_f=" << min_max_f.second << endl; << " max_f=" << min_max_f.second << endl;
if (!baseLevel) { if (!baseLevel) {
stochFields.setCurrentLevel(l - 1); min_max_c = stochFields.getMinMaxValues(false);
min_max_c = stochFields.getMinMaxValues();
vout(2) << " min_c=" << min_max_c.first vout(2) << " min_c=" << min_max_c.first
<< " max_c=" << min_max_c.second << endl; << " max_c=" << min_max_c.second << endl;
stochFields.setCurrentLevel(l);
} }
} }
double Qf, Qc; double Qf, Qc;
double costf, costc; double costf, costc;
u_f = 0.0; u_f = 0.0, u_c = 0.0;
u_c = 0.0;
Date Start_solving; Date Start_solving;
vout(2) << " Solving PDE on level " << l; vout(2) << " Solving PDE on level " << l;
solvePDE(Qf, costf, u_f, m, l); solvePDE(Qf, costf, u_f);
vout(2) << " took " << Start_solving - Date() << endl; vout(2) << " took " << Start_solving - Date() << endl;
if (!baseLevel) { if (!baseLevel) {
Date Start_solving_c; Date Start_solving_c;
vout(2) << " Solving PDE on level " << l - 1; vout(2) << " Solving PDE on level " << l - 1;
graphs.SetLevel(l - 2); stochFields.setFineField(false);
solvePDE(Qc, costc, u_c, m, l - 1); solvePDE(Qc, costc, u_c);
graphs.SetLevel(l - 1); stochFields.setFineField(true);
vout(2) << " took " << Start_solving_c - Date() << endl; vout(2) << " took " << Start_solving_c - Date() << endl;
} else { } else {
Qc = 0.0; Qc = 0.0;
...@@ -111,20 +107,26 @@ public: ...@@ -111,20 +107,26 @@ public:
updateSum(sums); updateSum(sums);
updateUSum(); updateUSum();
if (plotting >= 2) assemble.plotSolution(u_f, l); if (plotting >= 2)
if (plotting == 3) assemble.plotSolution(u_c, l); assemble.plotSolution(plot_f, u_f, meshes, l, m);
if (plotting == 3 && !baseLevel) {
stochFields.setFineField(false);
assemble.plotSolution(plot_c, u_c, meshes, l - 1, m, "ip");
stochFields.setFineField(true);
}
} }
updateAvg(); updateAvg();
updateUAvg(); updateUAvg();
updateStatistic(); updateStatistic();
if (plotting >= 1) assemble.plotSolution(u_avg, l); if (plotting >= 1)
// assemble.plotSolution(plot_f, u_avg, meshes, l, -1, "avg");
vout (1) << " End after " << Date() - Start << ": |E(Y)|=" << avg_Y vout (1) << " End after " << Date() - Start << ": |E(Y)|=" << avg_Y
<< " V(Y)=" << var_Y << endl; << " V(Y)=" << var_Y << endl;
} }
void solvePDE(double &Q, double &cost, Vector &u, int m, int l) override { void solvePDE(double &Q, double &cost, Vector &u) override {
// Preconditioner *preconditioner = GetPC(*graphs, assemble, "Multigrid"); // Preconditioner *preconditioner = GetPC(*graphs, assemble, "Multigrid");
// Solver solver(preconditioner, "GMRES"); // Solver solver(preconditioner, "GMRES");
Solver solver(graphs, assemble); Solver solver(graphs, assemble);
...@@ -134,20 +136,21 @@ public: ...@@ -134,20 +136,21 @@ public:
if (functional == "L2") Q = assemble.L2(u); if (functional == "L2") Q = assemble.L2(u);
if (functional == "Energy") Q = assemble.Energy(u); if (functional == "Energy") Q = assemble.Energy(u);
// if (functional == "Max") Q = assemble.Max(u); if (functional == "Outflow") Q = assemble.getInflowOutflow(u).second;
if (functional == "Outflow") Q = assemble.FluxError(u);
} }
}; };
MonteCarlo *getMonteCarlo(int l, int dM, bool baseLevel, StochasticFields &stochFields, MonteCarlo *getMonteCarlo(int l, int dM, bool baseLevel, Meshes &meshes,
EllipticAssemble &assemble, MatrixGraphs &graphs, StochasticFields &stochFields, Assemble *assemble,
string MonteCarlo) { MatrixGraphs &graphs) {
if (MonteCarlo.empty())
ReadConfig(Settings, "MonteCarlo", MonteCarlo); auto ellipticAssemble = dynamic_cast<EllipticAssemble *>(assemble);
if (MonteCarlo == "MonteCarloElliptic") auto transportAssemble = dynamic_cast<EllipticAssemble *>(assemble);
return new MonteCarloElliptic(l, dM, baseLevel, if (ellipticAssemble != nullptr)
stochFields, assemble, graphs); return new MonteCarloElliptic(l, dM, baseLevel, meshes,
else Exit("This MonteCarlo is not implemented") stochFields, graphs, (*ellipticAssemble));
if(transportAssemble != nullptr)
return nullptr;
return nullptr; return nullptr;
} }
......
...@@ -6,23 +6,26 @@ ...@@ -6,23 +6,26 @@
/* /*
* MonteCarlo * MonteCarlo
* *
* l: Level, should be set as the index in the data frames * l: Level, should be set as the index in the maps
* baseLevel: Bool to indicate if on base level -> Only fine grid calculations * baseLevel: Bool to indicate if on base level -> Only fine grid calculations
* dM: Samples to go * dM: Samples to go
* M: Samples so far * M: Samples so far
* functional: Type of functional used * functional: Type of functional used
* sum_cost: Summed cost * sum_cost: Summed cost
* avg_cost: Average cost * avg_cost: Average cost
*
* Qf: Functional on fine level * Qf: Functional on fine level
* Qc: Functional on coarse level * Qc: Functional on coarse level
* Q = Qf * Q = Qf
* Y = Qf - Qc * Y = Qf - Qc
*
* sum_Y, sum_Q: Sum of differences, functionals * sum_Y, sum_Q: Sum of differences, functionals
* avg_Y, avg_Q: Average of differences, functionals * avg_Y, avg_Q: Average of differences, functionals
* sum_Y2, sum_Q2: Sum of squared differences, functionals * sum_Y2, sum_Q2: Sum of squared differences, functionals
* E(Y^2), E(Q^2): Average of squared differences, functionals * E(Y^2), E(Q^2): Average of squared differences, functionals
* var_Y = E(Y^2) - (E(Y))^2, V(Q) = E(Q^2) - (E(Q))^2: *
* Variance of differences, functionals * var_Y = E(Y^2) - (E(Y))^2, V(Q)
* = E(Q^2) - (E(Q))^2
* *
* MCPlotting = 0 for no plots at all * MCPlotting = 0 for no plots at all
* MCPlotting = 1 for average plots * MCPlotting = 1 for average plots
...@@ -35,15 +38,17 @@ class MonteCarlo { ...@@ -35,15 +38,17 @@ class MonteCarlo {
public: public:
int verbose = 0, plotting = 0; int verbose = 0, plotting = 0;
int l = 0; int l = 0, plevel = 0;
bool baseLevel = true; bool baseLevel = true;
string functional = "L2"; string functional = "L2";
Meshes &meshes;
StochasticFields &stochFields; StochasticFields &stochFields;
EllipticAssemble &assemble;
MatrixGraphs &graphs; MatrixGraphs &graphs;
Vector u_sum, u_avg; Vector u_sum, u_avg, u_f, u_c;
Plot plot_c, plot_f;
int M = 0, dM = 0; int M = 0, dM = 0;
...@@ -56,14 +61,20 @@ public: ...@@ -56,14 +61,20 @@ public:
double sum_Q2 = 0.0, avg_Q2 = 0.0, var_Q = 0.0; double sum_Q2 = 0.0, avg_Q2 = 0.0, var_Q = 0.0;
double kurtosis = 0.0; double kurtosis = 0.0;
MonteCarlo(int l, int dM, bool baseLevel, StochasticFields &stochFields, MonteCarlo(int l, int dM, bool baseLevel, Meshes &meshes,
EllipticAssemble &assemble, MatrixGraphs &graphs) : StochasticFields &stochFields, MatrixGraphs &graphs) :
l(l), dM(dM), baseLevel(baseLevel),
stochFields(stochFields), assemble(assemble), l(l), dM(dM), baseLevel(baseLevel), meshes(meshes), plevel(meshes.pLevel()),
graphs(graphs), u_sum(graphs[l - 1]), u_avg(graphs[l - 1]) { stochFields(stochFields), graphs(graphs),
u_sum(graphs[l - plevel]), u_avg(u_sum),
u_f(u_sum), u_c(graphs[l - plevel - 1]),
plot_c(meshes[l - 1], meshes.dim(), 2),
plot_f(meshes[l], meshes.dim(), 2) {
ReadConfig(Settings, "MCVerbose", verbose); ReadConfig(Settings, "MCVerbose", verbose);
ReadConfig(Settings, "MCPlotting", plotting); ReadConfig(Settings, "MCPlotting", plotting);
ReadConfig(Settings, "functional", functional); ReadConfig(Settings, "functional", functional);
} }
virtual ~MonteCarlo() = default;; virtual ~MonteCarlo() = default;;
...@@ -82,12 +93,13 @@ public: ...@@ -82,12 +93,13 @@ public:
virtual void method() = 0; virtual void method() = 0;
virtual void solvePDE(double &Q, double &cost, Vector &u, int m, int l) {}; virtual void solvePDE(double &Q, double &cost, Vector &u) {};
}; };
MonteCarlo *getMonteCarlo(int l, int dM, bool baseLevel, StochasticFields &stochFields, MonteCarlo *
EllipticAssemble &assemble, MatrixGraphs &graphs, getMonteCarlo(int l, int dM, bool baseLevel, Meshes &meshes,
string MonteCarlo = ""); StochasticFields &stochFields, Assemble *assemble,
MatrixGraphs &graphs);
void estimateExponents(const map<int, MonteCarlo *> &df_mc, void estimateExponents(const map<int, MonteCarlo *> &df_mc,
double &alpha, double &beta, double &gamma, double &alpha, double &beta, double &gamma,
......
...@@ -2,16 +2,25 @@ ...@@ -2,16 +2,25 @@
using namespace std; using namespace std;
void MultilevelMonteCarlo::method() {
Date Start;
vout (1) << "Start multilevel Monte Carlo method only for initial values" << endl;
for (auto &mc : map_mc)
mc.second->method();
vout (1) << "End after " << Date() - Start << endl;
}
void MultilevelMonteCarlo::method(const double eps) { void MultilevelMonteCarlo::method(const double eps) {
Date Start; Date Start;
vout (1) << "Start multilevel Monte Carlo method for epsilon=" << eps << endl; vout (1) << "Start multilevel Monte Carlo method for epsilon " << eps << endl;
bool converged = false; bool converged = false;
while (!converged) { while (!converged) {
for (auto &iter : map_mc) for (auto &mc : map_mc)
if (iter.second->dM > 0) { if (mc.second->dM > 0)
iter.second->method(); mc.second->method();
}
estimateExponents(map_mc, alpha, beta, gamma); estimateExponents(map_mc, alpha, beta, gamma);
vout (2) << " Estimated exponents: " << "alpha=" << alpha vout (2) << " Estimated exponents: " << "alpha=" << alpha
...@@ -20,8 +29,8 @@ void MultilevelMonteCarlo::method(const double eps) { ...@@ -20,8 +29,8 @@ void MultilevelMonteCarlo::method(const double eps) {
updateNumSamples(eps); updateNumSamples(eps);
bool check_for_new_level = true; bool check_for_new_level = true;
for (auto &iter : map_mc) { for (auto &mc : map_mc) {
if (iter.second->dM > 0) { if (mc.second->dM > 0) {
check_for_new_level = false; check_for_new_level = false;
break; break;
} }
...@@ -35,10 +44,9 @@ void MultilevelMonteCarlo::method(const double eps) { ...@@ -35,10 +44,9 @@ void MultilevelMonteCarlo::method(const double eps) {
Exit ("Maximum level has been reached.") Exit ("Maximum level has been reached.")
} else { } else {
vout(2) << " Append level " << L << endl; vout(2) << " Append level " << L << endl;
map_mc[L] = getMonteCarlo(L, 0, false, map_mc[L] = getMonteCarlo(L, 0, false, meshes,
stochFields, stochFields,
assemble, graphs, assemble, graphs);
"MonteCarloElliptic");
map_mc[L]->var_Y = map_mc[L - 1]->var_Y / pow(2.0, beta); map_mc[L]->var_Y = map_mc[L - 1]->var_Y / pow(2.0, beta);
map_mc[L]->avg_cost = map_mc[L - 1]->avg_cost * pow(2.0, gamma); map_mc[L]->avg_cost = map_mc[L - 1]->avg_cost * pow(2.0, gamma);
updateNumSamples(eps); updateNumSamples(eps);
...@@ -49,38 +57,117 @@ void MultilevelMonteCarlo::method(const double eps) { ...@@ -49,38 +57,117 @@ void MultilevelMonteCarlo::method(const double eps) {
} }
} }
for (auto &iter : map_mc) { for (auto &mc : map_mc) {
value += iter.second->avg_Y; value += mc.second->avg_Y;
cost += iter.second->sum_cost; cost += mc.second->sum_cost;
levels.push_back(iter.first); levels.push_back(mc.first);
numsamples.push_back(iter.second->M); numsamples.push_back(mc.second->M);
} }
vout (1) << "End after " << Date() - Start << endl; vout (1) << "End after " << Date() - Start << endl;
} }
void MultilevelMonteCarlo::method(const vector<double> &eps) {
Date Start;
vout (1) << "Start multilevel Monte Carlo method for several eps" << endl;
for (auto &e : eps)
method(e);
vout (1) << "End after " << Date() - Start << endl;
}
void MultilevelMonteCarlo::updateNumSamples(const double &eps) { void MultilevelMonteCarlo::updateNumSamples(const double &eps) {
int M_optimal; int M_optimal;
double factor = 0.0; double factor = 0.0;
for (auto &iter : map_mc) for (auto &mc : map_mc)
factor += sqrt(iter.second->var_Y * iter.second->avg_cost); factor += sqrt(mc.second->var_Y * mc.second->avg_cost);
for (auto &iter : map_mc) { for (auto &mc : map_mc) {
M_optimal = (int) (ceil(2 * pow(eps, -2) * factor * M_optimal = (int) (ceil(2 * pow(eps, -2) * factor *
sqrt(iter.second->var_Y / iter.second->avg_cost))); sqrt(mc.second->var_Y / mc.second->avg_cost)));
map_mc[iter.first]->dM = M_optimal - map_mc[iter.first]->M; map_mc[mc.first]->dM = M_optimal - map_mc[mc.first]->M;
} }
vout(2) << " Missing samples:"; vout(2) << " Missing samples:";
for (auto &iter:map_mc) vout(1) << " " << iter.second->dM; for (auto &mc:map_mc) vout(1) << " " << mc.second->dM;
vout(2) << endl; vout(2) << endl;
} }
double MultilevelMonteCarlo::estimateNumericalError() { double MultilevelMonteCarlo::estimateNumericalError() {
double maxErr = 0.0; double maxErr = 0.0;
unsigned long exponent = map_mc.size() - 2; unsigned long exponent = map_mc.size() - 2;
for (auto &iter : map_mc) { for (auto &mc : map_mc) {
if (iter.first == map_mc.begin()->first) continue; if (mc.first == map_mc.begin()->first) continue;
maxErr = max(iter.second->avg_Y / (pow(2.0, alpha) - 1) / (pow(2.0, exponent)), maxErr = max(mc.second->avg_Y / (pow(2.0, alpha) - 1) /
(pow(2.0, exponent)),
maxErr); maxErr);
exponent--; exponent--;
} }
return maxErr; return maxErr;
} }
\ No newline at end of file
void MultilevelMonteCarlo::showMCTable() {
mout << endl
<< " l M E[Qf-Qc] E[Qf] V[Qf-Qc] V[Qf] kurtosis cost"
<< endl
<< "--------------------------------------------------------------------------------"
<< endl;
for (auto &mc : map_mc) {
int l = mc.first;
mout << setw(2) << l << setw(6) << mc.second->M
<< setw(12) << mc.second->avg_Y
<< setw(12) << mc.second->avg_Q << setw(12) << mc.second->var_Y
<< setw(12) << mc.second->var_Q << setw(12) << mc.second->kurtosis
<< setw(12) << mc.second->avg_cost << endl;
}
mout
<< "--------------------------------------------------------------------------------"
<< endl;
}
void MultilevelMonteCarlo::showKurtosisWarning() {
for (auto &mc : map_mc) {
if (mc.second->kurtosis > 100.0) {
mout << endl << "WARNING: kurtosis on level " << setw(2) << mc.first
<< " is " << setw(6) << mc.second->kurtosis << endl
<< "indicates MLMC correction is dominated by a few rare paths!"
<< endl;
}
}
}
void MultilevelMonteCarlo::showExponentResults() {
estimateExponents(map_mc, alpha, beta, gamma, true);
mout << endl << "alpha = " << setw(8) << alpha
<< " (exponent for the weak convergence of the FEM)"
<< endl << " beta = " << setw(8) << beta
<< " (exponent for the decay of the variance)"
<< endl << "gamma = " << setw(8) << gamma
<< " (exponent for the growth of the cost)"
<< endl;
}
void MultilevelMonteCarlo::showResultsMLMCRun(double eps) {
string level_str, sample_str;
mout << endl
<< " eps value MLMC cost l M"
<< endl
<< "--------------------------------------------------------------------------------"
<< endl;
mout << setw(6) << eps << setw(12) << value << setw(12) << cost;
for (unsigned long i = 0 ; i < levels.size(); i++) {
if (i != levels.size() - 1) level_str += to_string(levels[i]) + " ";
else level_str += to_string(levels[i]);
}
mout << setw(14) << level_str;
for (unsigned long i = 0; i < numsamples.size(); i++) {
if (i != numsamples.size() - 1) sample_str += to_string(numsamples[i]) + " ";
else sample_str += to_string(numsamples[i]);
}
mout << setw(36) << sample_str << endl;
}
...@@ -9,30 +9,32 @@ class MultilevelMonteCarlo { ...@@ -9,30 +9,32 @@ class MultilevelMonteCarlo {
public: public:
int verbose = 0, plotting = 0; int verbose = 0, plotting = 0;
int Lmax = 9; int Lmax;
map<int, MonteCarlo *> map_mc; map<int, MonteCarlo *> map_mc;
Meshes &meshes;
StochasticFields &stochFields; StochasticFields &stochFields;
EllipticAssemble &assemble; Assemble *assemble;
MatrixGraphs &graphs; MatrixGraphs &graphs;
vector<int> levels, numsamples; vector<int> levels, numsamples;
double value = 0.0, cost = 0.0; double value = 0.0, cost = 0.0;
double alpha = 0.0, beta = 0.0, gamma = 0.0; double alpha = 0.0, beta = 0.0, gamma = 0.0;
MultilevelMonteCarlo(vector<int> l_init, vector<int> M_init, int Lmax, MultilevelMonteCarlo(vector<int> l_init, vector<int> M_init, Meshes &meshes,
StochasticFields &stochFields, EllipticAssemble &assemble, StochasticFields &stochFields, Assemble *assemble,
MatrixGraphs &graphs) : MatrixGraphs &graphs) :
stochFields(stochFields), assemble(assemble), graphs(graphs) { stochFields(stochFields), assemble(assemble), graphs(graphs),
meshes(meshes), Lmax(meshes.Level()) {
ReadConfig(Settings, "MLMCVerbose", verbose); ReadConfig(Settings, "MLMCVerbose", verbose);
ReadConfig(Settings, "MLMCPlotting", plotting); ReadConfig(Settings, "MLMCPlotting", plotting);
for (unsigned long i = 0; i < l_init.size(); i++) { for (unsigned long i = 0; i < l_init.size(); i++) {
bool baseLevel = i == 0; bool baseLevel = i == 0;
map_mc[l_init[i]] = getMonteCarlo(l_init[i], M_init[i], baseLevel, int l = l_init[i], M = M_init[i];
stochFields, assemble, graphs, map_mc[l] = getMonteCarlo(l, M, baseLevel, meshes,
"MonteCarloElliptic");