1 #ifndef FLOWEQUATION_H_
2 #define FLOWEQUATION_H_
14 #include <boost/property_tree/ptree.hpp>
19 #include <Eigen/Sparse>
20 #include <Eigen/SparseCholesky>
52 FlowEquation(Eigen::VectorXd
const& sourceTerm) :
muq::Modeling::
ModPiece({int(sourceTerm.size())},
53 {int(sourceTerm.size()+1)})
55 numCells = sourceTerm.size();
56 numNodes = sourceTerm.size()+1;
58 xs = Eigen::VectorXd::LinSpaced(numNodes,0,1);
61 rhs = BuildRhs(sourceTerm);
77 auto& cond = inputs.at(0).get();
80 auto K = BuildStiffness(cond);
83 Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
87 outputs.at(0) = solver.solve(rhs);
121 Eigen::VectorXd
const& sens)
override
124 auto& cond = inputs.at(0).get();
127 auto A = BuildStiffness(cond);
130 Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
134 Eigen::VectorXd sol = solver.solve(rhs);
137 Eigen::VectorXd adjRhs = BuildAdjointRHS(sens);
138 Eigen::VectorXd adjSol = solver.solve(adjRhs);
141 gradient = (1.0/dx)*(sol.tail(numCells)-sol.head(numCells)).
array() * (adjSol.tail(numCells) - adjSol.head(numCells)).
array();
175 Eigen::VectorXd
const& vec)
override
178 auto& cond = inputs.at(0).get();
181 auto A = BuildStiffness(cond);
184 Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
188 Eigen::VectorXd sol = solver.solve(rhs);
191 Eigen::VectorXd incrRhs = Eigen::VectorXd::Zero(numNodes);
193 Eigen::VectorXd dh_dx = (sol.tail(numCells)-sol.head(numCells))/dx;
195 incrRhs.head(numCells) += ( vec.array()*dh_dx.array() ).matrix();
196 incrRhs.tail(numCells) -= ( vec.array()*dh_dx.array() ).matrix();
244 Eigen::VectorXd
const& sens,
245 Eigen::VectorXd
const& vec)
override
248 auto& cond = inputs.at(0).get();
251 auto K = BuildStiffness(cond);
254 Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
258 Eigen::VectorXd sol = solver.solve(rhs);
261 if((inWrt1==0)&&(inWrt2==0)){
264 Eigen::VectorXd adjRhs = BuildAdjointRHS(sens);
265 Eigen::VectorXd adjSol = solver.solve(adjRhs);
268 Eigen::VectorXd incrForRhs = BuildIncrementalRhs(sol, vec);
269 Eigen::VectorXd incrForSol = solver.solve(incrForRhs);
272 Eigen::VectorXd incrAdjRhs = BuildIncrementalRhs(adjSol, vec);
273 Eigen::VectorXd incrAdjSol = solver.solve(incrAdjRhs);
276 auto solDeriv = (sol.tail(numCells)-sol.head(numCells))/dx;
277 auto adjDeriv = (adjSol.tail(numCells)-adjSol.head(numCells))/dx;
278 auto incrForDeriv = (incrForSol.tail(numCells) - incrForSol.head(numCells))/dx;
279 auto incrAdjDeriv = (incrAdjSol.tail(numCells) - incrAdjSol.head(numCells))/dx;
281 hessAction = -(incrAdjDeriv.array() * solDeriv.array() + incrForDeriv.array() * adjDeriv.array());
284 }
else if((inWrt1==0)&&(inWrt2==1)){
286 Eigen::VectorXd temp = solver.solve(vec);
287 auto solDeriv = (sol.tail(numCells) - sol.head(numCells))/dx;
288 auto tempDeriv = (temp.tail(numCells)-temp.head(numCells))/dx;
290 hessAction = -dx * solDeriv.array() * tempDeriv.array();
299 Eigen::VectorXd BuildRhs(Eigen::VectorXd
const& sourceTerm)
const
301 Eigen::VectorXd rhs = Eigen::VectorXd::Zero(numNodes);
303 rhs.segment(1,numNodes-2) = 0.5*dx*(sourceTerm.tail(numNodes-2) + sourceTerm.head(numNodes-2));
304 rhs(numNodes-1) = 0.5*dx*sourceTerm(numNodes-2);
310 Eigen::VectorXd BuildAdjointRHS(Eigen::VectorXd
const& sensitivity)
const
312 Eigen::VectorXd rhs = -1.0*sensitivity;
318 Eigen::VectorXd BuildIncrementalRhs(Eigen::VectorXd
const& sol, Eigen::VectorXd
const& khat)
321 Eigen::VectorXd solGrad = (sol.tail(numCells)-sol.head(numCells))/dx;
322 Eigen::VectorXd rhs = Eigen::VectorXd::Zero(numNodes);
324 unsigned int leftNode, rightNode;
325 for(
unsigned int cellInd=0; cellInd<numCells; ++cellInd)
328 rightNode = cellInd + 1;
330 rhs(leftNode) -= dx*khat(cellInd)*solGrad(cellInd);
331 rhs(rightNode) += dx*khat(cellInd)*solGrad(cellInd);
339 Eigen::SparseMatrix<double> BuildStiffness(Eigen::VectorXd
const& condVals)
const{
341 typedef Eigen::Triplet<double> T;
342 std::vector<T> nzVals;
345 nzVals.push_back( T(0,0,1e10) );
347 unsigned int leftNode, rightNode;
348 for(
unsigned int cellInd=0; cellInd<numCells; ++cellInd)
351 rightNode = cellInd+1;
353 nzVals.push_back( T(leftNode, rightNode, -condVals(cellInd)/dx) );
354 nzVals.push_back( T(rightNode, leftNode, -condVals(cellInd)/dx) );
355 nzVals.push_back( T(rightNode, rightNode, condVals(cellInd)/dx) );
356 nzVals.push_back( T(leftNode, leftNode, condVals(cellInd)/dx) );
359 Eigen::SparseMatrix<double> stiffMat(numNodes,numNodes);
360 stiffMat.setFromTriplets(nzVals.begin(), nzVals.end());
371 unsigned int numCells;
372 unsigned int numNodes;
Provides an abstract interface for defining vector-valued model components.
virtual void GradientImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
virtual void ApplyJacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &vec)
std::vector< Eigen::VectorXd > outputs
ModPiece(std::vector< int > const &inputSizes, std::vector< int > const &outputSizes)
virtual void EvaluateImpl(ref_vector< boost::any > const &inputs) override
User-implemented function that determines the behavior of this muq::Modeling::WorkPiece.
Eigen::VectorXd hessAction
Eigen::VectorXd jacobianAction
virtual void ApplyHessianImpl(unsigned int const outWrt, unsigned int const inWrt1, unsigned int const inWrt2, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sens, Eigen::VectorXd const &vec)
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
@ array
array (ordered collection of values)