Commit e3a98079 authored by niklas.baumgarten's avatar niklas.baumgarten
Browse files

Merge branch '34-derive-sprasegridgenerator-from-samplegenerator' into 'feature'

added weight solution - other possible approach could be to add the weight as...

Closes #34

See merge request !47
parents cc29d01d 035273e9
Pipeline #157969 passed with stages
in 11 minutes and 49 seconds
...@@ -7,7 +7,10 @@ ...@@ -7,7 +7,10 @@
Estimator *EstimatorCreator::Create() { Estimator *EstimatorCreator::Create() {
if (_estimatorName == "StochasticCollocation") if (_estimatorName == "StochasticCollocation")
return new StochasticCollocation(); return new StochasticCollocation(
_epsilon, _level, _stochLevel, _onlyFine, _parallel,
_meshesCreator, _pdeSolverCreator
);
if (_estimatorName == "MultilevelMonteCarlo") if (_estimatorName == "MultilevelMonteCarlo")
return new MultilevelEstimator( return new MultilevelEstimator(
......
...@@ -71,6 +71,8 @@ private: ...@@ -71,6 +71,8 @@ private:
int _initSamples; int _initSamples;
int _stochLevel;
double _epsilon; double _epsilon;
Levels _levelVec; Levels _levelVec;
...@@ -120,6 +122,11 @@ public: ...@@ -120,6 +122,11 @@ public:
return *this; return *this;
} }
EstimatorCreator WithStochLevel(int stochLevel) {
_stochLevel = stochLevel;
return *this;
}
EstimatorCreator WithOnlyFine(bool onlyFine) { EstimatorCreator WithOnlyFine(bool onlyFine) {
_onlyFine = onlyFine; _onlyFine = onlyFine;
return *this; return *this;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "MeshesCreator.hpp" #include "MeshesCreator.hpp"
#include <utility>
class MonteCarlo : public Estimator { class MonteCarlo : public Estimator {
protected: protected:
...@@ -34,7 +36,7 @@ public: ...@@ -34,7 +36,7 @@ public:
PDESolverCreator pdeCreator = PDESolverCreator()) : PDESolverCreator pdeCreator = PDESolverCreator()) :
Estimator(epsilon, level, initSamples), onlyFine(onlyFine), parallel(parallel), Estimator(epsilon, level, initSamples), onlyFine(onlyFine), parallel(parallel),
fineId(SampleID(level, 0, false)), coarseId(SampleID(level, 0, true)), fineId(SampleID(level, 0, false)), coarseId(SampleID(level, 0, true)),
meshesCreator(meshesCreator), pdeSolverCreator(pdeCreator) { meshesCreator(std::move(meshesCreator)), pdeSolverCreator(std::move(pdeCreator)) {
config.get("MCVerbose", verbose); config.get("MCVerbose", verbose);
config.get("MCParallel", parallel); config.get("MCParallel", parallel);
......
//
// Created by niklas on 11.05.21.
//
#include "StochasticCollocation.hpp" #include "StochasticCollocation.hpp"
void StochasticCollocation::Method() {
mout.StartBlock("Stochastic Collocation l=" + to_string(level));
vout(1) << "Start with: " << aggregate;
method();
aggregate.UpdateParallel();
vout(1) << "End with: " << aggregate;
mout.EndBlock(verbose == 0);
}
void StochasticCollocation::method() {
std::unique_ptr<Meshes> meshes = meshesCreator.
WithMeshName(pdeSolverCreator.GetMeshName()).
WithCommSplit(aggregate.commSplit).
WithPLevel(level - 1).
WithLevel(level).
CreateUnique();
std::unique_ptr<PDESolver> pdeSolver = pdeSolverCreator.
CreateUnique(*meshes);
SampleSolution fineSolution(pdeSolver->GetDisc(), fineId);
SampleSolution coarseSolution(pdeSolver->GetDisc(), coarseId);
int numGridPoints = pdeSolver->GetProblem()->NumOfSamples();
aggregate.UpdateSampleCounter(numGridPoints);
while (aggregate.ctr.dMcomm != 0) {
updateSampleIds(fineSolution, coarseSolution);
pdeSolver->DrawSample(fineId);
pdeSolver->Run(fineSolution);
aggregate.Update(fineSolution, coarseSolution);
}
}
void StochasticCollocation::updateSampleIds(SampleSolution &fSol, SampleSolution &cSol) {
fineId.number = aggregate.index();
coarseId.number = aggregate.index();
fSol.id = fineId;
cSol.id = coarseId;
}
...@@ -3,20 +3,41 @@ ...@@ -3,20 +3,41 @@
#include "Estimator.hpp" #include "Estimator.hpp"
#include <utility>
class StochasticCollocation : public Estimator { class StochasticCollocation : public Estimator {
private: protected:
int verbose = 1;
bool onlyFine;
bool parallel;
SampleID fineId;
SampleID coarseId;
MeshesCreator meshesCreator;
PDESolverCreator pdeSolverCreator;
void updateSampleIds(SampleSolution &fSol, SampleSolution &cSol);
void method();
public: public:
StochasticCollocation() : Estimator(0.0, 0, 0) {} StochasticCollocation(double epsilon, int level, int stochLevel,
bool onlyFine, bool parallel,
MeshesCreator meshesCreator = MeshesCreator(),
PDESolverCreator pdeCreator = PDESolverCreator()) :
Estimator(epsilon, level, 0),
fineId(SampleID(level, 0, false)), coarseId(SampleID(level, 0, true)),
meshesCreator(std::move(meshesCreator)), pdeSolverCreator(std::move(pdeCreator)) {}
std::string Name() const override { std::string Name() const override { return "StochasticCollocation"; }
return "StochasticCollocation";
}
void Method() override { void Method() override;
// Todo here is some stuff todo
}
}; };
#endif //STOCHASTICCOLLOCATION_HPP #endif //STOCHASTICCOLLOCATION_HPP
...@@ -86,7 +86,10 @@ struct SVar { ...@@ -86,7 +86,10 @@ struct SVar {
Ycomm = Y2comm / (ctr.Mcomm - 1); Ycomm = Y2comm / (ctr.Mcomm - 1);
} }
void UpdateParallel(int commSplit) { void UpdateParallel(double C2, double Q2, double Y2, SampleCounter ctr) {
C = C2 / (ctr.M - 1);
Q = Q2 / (ctr.M - 1);
Y = Y2 / (ctr.M - 1);
} }
friend Logging &operator<<(Logging &s, const SVar &sVar) { friend Logging &operator<<(Logging &s, const SVar &sVar) {
...@@ -136,7 +139,8 @@ struct Kurtosis { ...@@ -136,7 +139,8 @@ struct Kurtosis {
double Ycomm = 0.0; double Ycomm = 0.0;
void Update() {//Averages avgs, Variances vars) { void Update() {
//Averages avgs, Variances vars) {
// Q = (avgs.Q4 - 4.0 * avgs.Q3 * avgs.Q + 6.0 * avgs.Q2 * avgs.Q * avgs.Q - // Q = (avgs.Q4 - 4.0 * avgs.Q3 * avgs.Q + 6.0 * avgs.Q2 * avgs.Q * avgs.Q -
// 3.0 * avgs.Q * avgs.Q * avgs.Q * avgs.Q) / vars.Q / vars.Q; // 3.0 * avgs.Q * avgs.Q * avgs.Q * avgs.Q) / vars.Q / vars.Q;
// Y = (avgs.Y4 - 4.0 * avgs.Y3 * avgs.Y + 6.0 * avgs.Y2 * avgs.Y * avgs.Y - // Y = (avgs.Y4 - 4.0 * avgs.Y3 * avgs.Y + 6.0 * avgs.Y2 * avgs.Y * avgs.Y -
...@@ -194,7 +198,7 @@ public: ...@@ -194,7 +198,7 @@ public:
bool parallel = true; bool parallel = true;
public: public:
WelfordAggregate(int dM) { explicit WelfordAggregate(int dM) {
UpdateSampleCounter(dM); UpdateSampleCounter(dM);
} }
...@@ -233,24 +237,11 @@ public: ...@@ -233,24 +237,11 @@ public:
Q2 = PPM->SumAcrossComm(Q2comm, commSplit); Q2 = PPM->SumAcrossComm(Q2comm, commSplit);
Y2 = PPM->SumAcrossComm(Y2comm, commSplit); Y2 = PPM->SumAcrossComm(Y2comm, commSplit);
// delta = avg_b - avg_a sVar.UpdateParallel(C2, Q2, Y2, ctr);
// M2 = M2_a + M2_b + delta ** 2 * n_a * n_b / n
sVar.C = C2 / (ctr.M - 1);
sVar.Q = Q2 / (ctr.M - 1);
sVar.Y = Y2 / (ctr.M - 1);
// def parallel_variance(n_a, avg_a, M2_a, n_b, avg_b, M2_b):
// n = n_a + n_b
// delta = avg_b - avg_a
// M2 = M2_a + M2_b + delta ** 2 * n_a * n_b / n
// var_ab = M2 / (n - 1)
// return var_ab
} }
int index() { int index() const {
return ctr.M + ctr.Mcomm + ctr.dMcomm * PPM->Proc(0); return ctr.M + ctr.Mcomm + ctr.dMcomm * PPM->Proc(0);
// return M + dMcomm * PPM->Proc(0);
} }
void UpdateSampleCounter(int dM) { void UpdateSampleCounter(int dM) {
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
#define SPARSEGRIDGENERATOR_HPP #define SPARSEGRIDGENERATOR_HPP
#include "TasmanianSparseGrid.hpp" #include "TasmanianSparseGrid.hpp"
#include "SampleGenerator.hpp"
// Todo Use RVector and such //template<typename T>
class SparseGridGenerator : public SampleGenerator<RVector> {
class SparseGridGenerator {
protected: protected:
TasGrid::TasmanianSparseGrid grid; TasGrid::TasmanianSparseGrid grid;
...@@ -18,32 +18,68 @@ protected: ...@@ -18,32 +18,68 @@ protected:
int outputs; int outputs;
double weight = 0.0;
RVector sample {};
std::vector<double> weights{};
std::vector<RVector> samples{};
void fillSampleVector() {
std::vector<double> points = grid.getPoints();
for (auto it_start = points.begin(); it_start != points.end(); it_start += dimension)
samples.emplace_back(std::vector<double>(it_start, it_start + dimension));
}
void drawSample(const SampleID &id) override {
sample = samples[id.number];
weight = weights[id.number];
};
public: public:
SparseGridGenerator(int dimension, int outputs, SparseGridGenerator(const Meshes &meshes, int dimension, int outputs, int level,
TasGrid::TypeDepth depth = TasGrid::type_level, TasGrid::TypeDepth depth = TasGrid::type_level,
TasGrid::TypeOneDRule rule = TasGrid::rule_clenshawcurtis) : TasGrid::TypeOneDRule rule = TasGrid::rule_clenshawcurtis) :
dimension(dimension), outputs(outputs), depth(depth), rule(rule) { SampleGenerator(meshes), dimension(dimension), outputs(outputs),
depth(depth), rule(rule) {
grid.makeGlobalGrid(dimension, outputs, level, depth, rule);
weights = grid.getQuadratureWeights();
fillSampleVector();
} }
void CreateGlobalGrid(int level) { void CreateGlobalGrid(int level) {
grid.makeGlobalGrid(dimension, outputs, level, depth, rule); grid.makeGlobalGrid(dimension, outputs, level, depth, rule);
} }
std::vector<double> GetPoints() { std::vector<RVector> GetSamples() {
return grid.getPoints(); return samples;
} }
std::vector<double> GetWeights() { std::vector<double> GetWeights() {
return grid.getQuadratureWeights(); return weights;
}
double SampleWeight(const SampleID &id) {
return weights[id.number];
} }
int GetNumPoints() { int GetNumPoints() {
return grid.getNumPoints(); return grid.getNumPoints();
} }
double Quadrature(double func (double, double)) { int GetStochDimension() {
return grid.getNumDimensions();
}
RVector EvalSample() const override {
return sample;
}
// todo move to stochastic collocation class
double Quadrature(double func(double, double)) {
double I = 0.0; double I = 0.0;
std::vector<double> points = GetPoints(); std::vector<double> points = grid.getPoints();
std::vector<double> weights = GetWeights(); std::vector<double> weights = GetWeights();
int num_points = GetNumPoints(); int num_points = GetNumPoints();
for (int i = 0; i < num_points; i++) { for (int i = 0; i < num_points; i++) {
...@@ -53,6 +89,8 @@ public: ...@@ -53,6 +89,8 @@ public:
} }
return I; return I;
} }
string Name() const override { return "SparseGridGenerator"; };
}; };
#endif //SPARSEGRIDGENERATOR_HPP #endif //SPARSEGRIDGENERATOR_HPP
...@@ -5,6 +5,7 @@ void EllipticPDESolver::run(SampleSolution &solution) { ...@@ -5,6 +5,7 @@ void EllipticPDESolver::run(SampleSolution &solution) {
newton->operator()(*assemble, solution.U); newton->operator()(*assemble, solution.U);
} }
// Todo maybe multiply weights to Q
void EllipticPDESolver::computeQ(SampleSolution &solution) { void EllipticPDESolver::computeQ(SampleSolution &solution) {
if (quantity == "L2") solution.Q = assemble->L2(solution.U); if (quantity == "L2") solution.Q = assemble->L2(solution.U);
else if (quantity == "H1") solution.Q = assemble->H1(solution.U); else if (quantity == "H1") solution.Q = assemble->H1(solution.U);
......
...@@ -32,6 +32,10 @@ protected: ...@@ -32,6 +32,10 @@ protected:
virtual void plotSolution(SampleSolution &solution) = 0; virtual void plotSolution(SampleSolution &solution) = 0;
void weightSolution(SampleSolution &solution) const {
solution.Q = GetProblem()->SampleWeight(solution.id) * solution.Q;
}
public: public:
PDESolver(const Meshes &meshes, const std::string &quantity, PDESolver(const Meshes &meshes, const std::string &quantity,
const std::string &costMeasure) : const std::string &costMeasure) :
...@@ -56,6 +60,8 @@ public: ...@@ -56,6 +60,8 @@ public:
computeQ(solution); computeQ(solution);
computeCost(solution); computeCost(solution);
plotSolution(solution); plotSolution(solution);
weightSolution(solution);
// Todo other idea: Add weight as class member of solution
vout(2) << "Q=" << solution.Q << " cost=" << solution.Cost << endl; vout(2) << "Q=" << solution.Q << " cost=" << solution.Cost << endl;
mout.EndBlock(verbose <= 1); mout.EndBlock(verbose <= 1);
} }
...@@ -79,7 +85,7 @@ protected: ...@@ -79,7 +85,7 @@ protected:
void run(SampleSolution &solution) override {} void run(SampleSolution &solution) override {}
void computeQ(SampleSolution &solution) override { void computeQ(SampleSolution &solution) override {
if (quantity == "GeneratorValue") solution.Q = assemble->GeneratorValue(); if (quantity == "FunctionEvaluation") solution.Q = assemble->FunctionEvaluation();
else Exit("Quantity of interest not implemented") else Exit("Quantity of interest not implemented")
} }
...@@ -98,12 +104,7 @@ public: ...@@ -98,12 +104,7 @@ public:
const Meshes &meshes, const Meshes &meshes,
const std::string &quantity = "L2", const std::string &quantity = "L2",
const std::string &costMeasure = "size") : const std::string &costMeasure = "size") :
PDESolver(meshes, quantity, costMeasure), assemble(assemble) { PDESolver(meshes, quantity, costMeasure), assemble(assemble) {}
if (verbose > 0) {
PrintInfo();
assemble->PrintInfo();
}
}
IAssemble *GetAssemble() const override { return assemble; } IAssemble *GetAssemble() const override { return assemble; }
......
...@@ -10,7 +10,7 @@ private: ...@@ -10,7 +10,7 @@ private:
std::string _pc; std::string _pc;
std::string _model = "DummyPDESolver"; std::string _model = "DummyPDESolver";
std::string _problem = "StochasticDummyProblem"; std::string _problem = "StochasticDummyProblem";
std::string _quantity = "GeneratorValue"; std::string _quantity = "FunctionEvaluation";
std::string _costMeasure = "size"; std::string _costMeasure = "size";
std::string _linearSolver = "GMRES"; std::string _linearSolver = "GMRES";
......
...@@ -55,8 +55,8 @@ public: ...@@ -55,8 +55,8 @@ public:
return 0.0; return 0.0;
}; };
double GeneratorValue() const { double FunctionEvaluation() const {
return problem->GeneratorValue(); return problem->FunctionEvaluation();
} }
}; };
......
#include "IStochasticProblem.hpp" #include "IStochasticProblem.hpp"
StochasticDummyProblem * StochasticDummyProblem *
CreateStochasticDummyProblem(const std::string &problemName, const Meshes &meshes) { CreateStochasticDummyProblem(const std::string &problemName, const Meshes &meshes) {
if (problemName == "StochasticDummyScalarGeneratorProblem") if (problemName == "ScalarGeneratorProblem")
return new StochasticDummyScalarGeneratorProblem(meshes); return new ScalarGeneratorProblem(meshes);
if (problemName == "StochasticDummyComplexGeneratorProblem") if (problemName == "ComplexGeneratorProblem")
return new StochasticDummyComplexGeneratorProblem(meshes); return new ComplexGeneratorProblem(meshes);
if (problemName == "StochasticDummyVectorFieldGeneratorProblem") if (problemName == "VectorFieldGeneratorProblem")
return new StochasticDummyVectorFieldGeneratorProblem(meshes); return new VectorFieldGeneratorProblem(meshes);
if (problemName == "StochasticDummyTensorGeneratorProblem") if (problemName == "TensorGeneratorProblem")
return new StochasticDummyTensorGeneratorProblem(meshes); return new TensorGeneratorProblem(meshes);
if (problemName == "StochasticDummyRVectorGeneratorProblem") if (problemName == "RVectorGeneratorProblem")
return new StochasticDummyRVectorGeneratorProblem(meshes); return new RVectorGeneratorProblem(meshes);
if (problemName == "StochasticDummyCVectorGeneratorProblem") if (problemName == "CVectorGeneratorProblem")
return new StochasticDummyCVectorGeneratorProblem(meshes); return new CVectorGeneratorProblem(meshes);
if (problemName == "StochasticDummyRMatrixGeneratorProblem") if (problemName == "RMatrixGeneratorProblem")
return new StochasticDummyRMatrixGeneratorProblem(meshes); return new RMatrixGeneratorProblem(meshes);
if (problemName == "StochasticDummyCMatrixGeneratorProblem") if (problemName == "CMatrixGeneratorProblem")
return new StochasticDummyCMatrixGeneratorProblem(meshes); return new CMatrixGeneratorProblem(meshes);
Exit(problemName + " not found") if (problemName == "SparseGrid1DGeneratorProblem")
return new SparseGrid1DGeneratorProblem(meshes);
if (problemName == "SparseGrid2DGeneratorProblem")
return new SparseGrid2DGeneratorProblem(meshes);
Exit(problemName + " not found")
} }
\ No newline at end of file
...@@ -21,6 +21,10 @@ public: ...@@ -21,6 +21,10 @@ public:
virtual void DrawSample(const SampleID &id) = 0; virtual void DrawSample(const SampleID &id) = 0;
virtual double SampleWeight(const SampleID &id) { return 1.0; }
virtual int NumOfSamples() { return 0; };
virtual string Name() const = 0; virtual string Name() const = 0;
}; };
...@@ -29,13 +33,13 @@ public: ...@@ -29,13 +33,13 @@ public:
explicit StochasticDummyProblem(const Meshes &meshes) : explicit StochasticDummyProblem(const Meshes &meshes) :
IStochasticProblem(meshes) {} IStochasticProblem(meshes) {}
virtual double GeneratorValue() = 0; virtual double FunctionEvaluation() = 0;
}; };
class StochasticDummyScalarGeneratorProblem : public StochasticDummyProblem { class ScalarGeneratorProblem : public StochasticDummyProblem {
NormalDistributionReal scalarGenerator; NormalDistributionReal scalarGenerator;
public: public:
explicit StochasticDummyScalarGeneratorProblem(const Meshes &meshes) : explicit ScalarGeneratorProblem(const Meshes &meshes) :
StochasticDummyProblem(meshes), StochasticDummyProblem(meshes),
scalarGenerator(NormalDistributionReal(meshes)) {} scalarGenerator(NormalDistributionReal(meshes)) {}
...@@ -43,19 +47,19 @@ public: ...@@ -43,19 +47,19 @@ public:
scalarGenerator.DrawSample(id); scalarGenerator.DrawSample(id);
} }
double GeneratorValue() override { double FunctionEvaluation() override {
return this->scalarGenerator.EvalSample();