293 #include <boost/property_tree/ptree.hpp> 
  297 #include <Eigen/Core> 
  298 #include <Eigen/Sparse> 
  299 #include <Eigen/SparseCholesky> 
  331   FlowEquation(Eigen::VectorXd 
const& sourceTerm) : 
muq::Modeling::
ModPiece({int(sourceTerm.size())},
 
  332                                                                             {int(sourceTerm.size()+1)}) 
 
  334     numCells = sourceTerm.size();
 
  335     numNodes = sourceTerm.size()+1;
 
  337     xs = Eigen::VectorXd::LinSpaced(numNodes,0,1);
 
  340     rhs = BuildRhs(sourceTerm);
 
  356     auto& cond = inputs.at(0).get();
 
  359     auto K = BuildStiffness(cond);
 
  362     Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
 
  366     outputs.at(0) = solver.solve(rhs);
 
  400                             Eigen::VectorXd 
const& sens)
 override 
  403     auto& cond = inputs.at(0).get();
 
  406     auto A = BuildStiffness(cond);
 
  409     Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
 
  413     Eigen::VectorXd sol = solver.solve(rhs);
 
  416     Eigen::VectorXd adjRhs = BuildAdjointRHS(sens);
 
  417     Eigen::VectorXd adjSol = solver.solve(adjRhs);
 
  420     gradient = (1.0/dx)*(sol.tail(numCells)-sol.head(numCells)).
array() * (adjSol.tail(numCells) - adjSol.head(numCells)).
array();
 
  454                                  Eigen::VectorXd 
const& vec)
 override 
  457     auto& cond = inputs.at(0).get();
 
  460     auto A = BuildStiffness(cond);
 
  463     Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
 
  467     Eigen::VectorXd sol = solver.solve(rhs);
 
  470     Eigen::VectorXd incrRhs = Eigen::VectorXd::Zero(numNodes);
 
  472     Eigen::VectorXd dh_dx = (sol.tail(numCells)-sol.head(numCells))/dx; 
 
  474     incrRhs.head(numCells) += ( vec.array()*dh_dx.array() ).matrix();
 
  475     incrRhs.tail(numCells) -= ( vec.array()*dh_dx.array() ).matrix();
 
  523                                  Eigen::VectorXd 
const& sens,
 
  524                                  Eigen::VectorXd 
const& vec)
 override 
  527     auto& cond = inputs.at(0).get();
 
  530     auto K = BuildStiffness(cond);
 
  533     Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
 
  537     Eigen::VectorXd sol = solver.solve(rhs);
 
  540     if((inWrt1==0)&&(inWrt2==0)){
 
  543       Eigen::VectorXd adjRhs = BuildAdjointRHS(sens);
 
  544       Eigen::VectorXd adjSol = solver.solve(adjRhs);
 
  547       Eigen::VectorXd incrForRhs = BuildIncrementalRhs(sol, vec);
 
  548       Eigen::VectorXd incrForSol = solver.solve(incrForRhs);
 
  551       Eigen::VectorXd incrAdjRhs = BuildIncrementalRhs(adjSol, vec);
 
  552       Eigen::VectorXd incrAdjSol = solver.solve(incrAdjRhs);
 
  555       auto solDeriv = (sol.tail(numCells)-sol.head(numCells))/dx;
 
  556       auto adjDeriv = (adjSol.tail(numCells)-adjSol.head(numCells))/dx;
 
  557       auto incrForDeriv = (incrForSol.tail(numCells) - incrForSol.head(numCells))/dx;
 
  558       auto incrAdjDeriv = (incrAdjSol.tail(numCells) - incrAdjSol.head(numCells))/dx;
 
  560       hessAction = -(incrAdjDeriv.array() * solDeriv.array() + incrForDeriv.array() * adjDeriv.array());
 
  563     }
else if((inWrt1==0)&&(inWrt2==1)){
 
  565       Eigen::VectorXd temp = solver.solve(vec);
 
  566       auto solDeriv = (sol.tail(numCells) - sol.head(numCells))/dx;
 
  567       auto tempDeriv = (temp.tail(numCells)-temp.head(numCells))/dx;
 
  569       hessAction = -dx * solDeriv.array() * tempDeriv.array();
 
  578   Eigen::VectorXd BuildRhs(Eigen::VectorXd 
const& sourceTerm)
 const 
  580     Eigen::VectorXd rhs = Eigen::VectorXd::Zero(numNodes);
 
  582     rhs.segment(1,numNodes-2) = 0.5*dx*(sourceTerm.tail(numNodes-2) + sourceTerm.head(numNodes-2));
 
  583     rhs(numNodes-1) = 0.5*dx*sourceTerm(numNodes-2);
 
  589   Eigen::VectorXd BuildAdjointRHS(Eigen::VectorXd 
const& sensitivity)
 const 
  591     Eigen::VectorXd rhs = -1.0*sensitivity;
 
  597   Eigen::VectorXd BuildIncrementalRhs(Eigen::VectorXd 
const& sol, Eigen::VectorXd 
const& khat)
 
  600     Eigen::VectorXd solGrad = (sol.tail(numCells)-sol.head(numCells))/dx;
 
  601     Eigen::VectorXd rhs = Eigen::VectorXd::Zero(numNodes);
 
  603     unsigned int leftNode, rightNode;
 
  604     for(
unsigned int cellInd=0; cellInd<numCells; ++cellInd)
 
  607       rightNode = cellInd + 1;
 
  609       rhs(leftNode) -= dx*khat(cellInd)*solGrad(cellInd);
 
  610       rhs(rightNode) += dx*khat(cellInd)*solGrad(cellInd);
 
  618   Eigen::SparseMatrix<double> BuildStiffness(Eigen::VectorXd 
const& condVals)
 const{
 
  620     typedef Eigen::Triplet<double> T;
 
  621     std::vector<T> nzVals;
 
  624     nzVals.push_back( T(0,0,1e10) );
 
  626     unsigned int leftNode, rightNode;
 
  627     for(
unsigned int cellInd=0; cellInd<numCells; ++cellInd)
 
  630       rightNode = cellInd+1;
 
  632       nzVals.push_back( T(leftNode,  rightNode, -condVals(cellInd)/dx) );
 
  633       nzVals.push_back( T(rightNode, leftNode,  -condVals(cellInd)/dx) );
 
  634       nzVals.push_back( T(rightNode, rightNode,  condVals(cellInd)/dx) );
 
  635       nzVals.push_back( T(leftNode,  leftNode,   condVals(cellInd)/dx) );
 
  638     Eigen::SparseMatrix<double> stiffMat(numNodes,numNodes);
 
  639     stiffMat.setFromTriplets(nzVals.begin(), nzVals.end());
 
  650   unsigned int numCells;
 
  651   unsigned int numNodes;
 
  669   unsigned int numCells = 200;
 
  672   Eigen::VectorXd nodeLocs = Eigen::VectorXd::LinSpaced(numCells+1,0,1);
 
  675   Eigen::VectorXd cellLocs = 0.5*(nodeLocs.head(numCells) + nodeLocs.tail(numCells));
 
  678   Eigen::VectorXd recharge = Eigen::VectorXd::Ones(numCells);
 
  681   auto mod = std::make_shared<FlowEquation>(recharge);
 
  692   Eigen::VectorXd cond = (20.0*cellLocs.array()).cos().exp();
 
  694   Eigen::VectorXd h = mod->Evaluate(cond).at(0);
 
  696   std::cout << 
"Solution: \n" << h.transpose() << std::endl << std::endl;
 
  711   auto objective = std::make_shared<Gaussian>(numCells+1)->AsDensity();
 
  723   Eigen::VectorXd objSens = Eigen::VectorXd::Ones(1);
 
  724   Eigen::VectorXd sens = objective->Gradient(0,0,h,objSens);
 
  725   Eigen::VectorXd grad = mod->Gradient(0,0,cond,sens);
 
  727   std::cout << 
"Gradient: \n" << grad.transpose() << std::endl << std::endl;
 
  734   Eigen::VectorXd gradFD = mod->GradientByFD(0,0,std::vector<Eigen::VectorXd>{cond},sens);
 
  735   std::cout << 
"Finite Difference Gradient:\n" << gradFD.transpose() << std::endl << std::endl;
 
  741   Eigen::VectorXd jacDir = RandomGenerator::GetUniform(numCells);
 
  743   Eigen::VectorXd jacAct = mod->ApplyJacobian(0,0, cond, jacDir);
 
  744   std::cout << 
"Jacobian Action: \n" << jacAct.transpose() << std::endl << std::endl;
 
  746   Eigen::VectorXd jacActFD = mod->ApplyJacobianByFD(0,0, std::vector<Eigen::VectorXd>{cond}, jacDir);
 
  747   std::cout << 
"Finite Difference Jacobian Action \n" << jacActFD.transpose() << std::endl << std::endl;
 
  754   Eigen::VectorXd hessDir = RandomGenerator::GetUniform(numCells);
 
  756   Eigen::VectorXd hessAct = mod->ApplyHessian(0,0,0,cond,sens,hessDir);
 
  757   std::cout << 
"Hessian Action: \n" << hessAct.transpose() << std::endl << std::endl;
 
  759   Eigen::VectorXd hessActFD = mod->ApplyHessianByFD(0,0,0,std::vector<Eigen::VectorXd>{cond},sens,hessDir);
 
  760   std::cout << 
"Finite Difference Hessian Action \n" << hessActFD.transpose() << std::endl << std::endl;
 
  773   graph.
AddNode(objective, 
"Objective");
 
  774   graph.
AddEdge(
"Model",0,
"Objective",0);
 
  785   hessAct = fullMod->ApplyHessian(0,0,0,cond,objSens,hessDir);
 
  786   hessActFD = fullMod->ApplyHessianByFD(0,0,0,std::vector<Eigen::VectorXd>{cond},objSens,hessDir);
 
  788   std::cout << 
"Hessian Action: \n" << hessAct.transpose() << std::endl << std::endl;
 
  789   std::cout << 
"Finite Difference Hessian Action \n" << hessActFD.transpose() << std::endl << std::endl;
 
  808   unsigned int outWrt = 0; 
 
  809   unsigned int inWrt1 = 0; 
 
  810   unsigned int inWrt2 = 0;
 
  812   double scaling = -1.0;
 
  813   std::vector<Eigen::VectorXd> inputs(1);
 
  815   auto hessOp = std::make_shared<HessianOperator>(fullMod, inputs, outWrt, inWrt1, inWrt2, objSens, scaling);
 
  822   boost::property_tree::ptree opts;
 
  823   opts.put(
"NumEigs", numCells); 
 
  824   opts.put(
"Verbosity", 3); 
 
  841   std::cout << 
"Eigenvalues:\n" << vals.transpose() << std::endl << std::endl;
 
Eigen::VectorXd const  & eigenvalues() const
 
Eigen::MatrixXd const  & eigenvectors() const
 
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)
 
Two-pass stochastic algorithm for computing generalized eigenvalues from matrix products.
 
virtual StochasticEigenSolver & compute(std::shared_ptr< LinearOperator > const &A, std::shared_ptr< LinearOperator > B=nullptr, std::shared_ptr< LinearOperator > Binv=nullptr)
 
A graph of connected muq::Modeling::WorkPiece's.
 
void AddNode(std::shared_ptr< WorkPiece > input, std::string const &name)
Add a new node to the graph.
 
void AddEdge(std::string const &nameFrom, unsigned int const outputDim, std::string const &nameTo, unsigned int const inputDim)
Add a new edge to the graph.
 
std::shared_ptr< ModGraphPiece > CreateModPiece(std::string const &node, std::vector< std::string > const &inNames=std::vector< std::string >()) const
Create a muq::Modeling::ModPiece whose output matches a given node.
 
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
 
@ array
array (ordered collection of values)