MUQ  0.4.3
FenicsPiece.h
Go to the documentation of this file.
1 #ifndef FENICSPIECE_H
2 #define FENICSPIECE_H
3 
6 
7 #include <pybind11/pybind11.h>
8 #include <pybind11/eigen.h>
9 #include <pybind11/functional.h>
10 #include <pybind11/stl.h>
11 
12 #include <dolfin/la/GenericVector.h>
13 
14 #include <dolfin/fem/LinearVariationalProblem.h>
15 #include <dolfin/fem/LinearVariationalSolver.h>
16 #include <dolfin/fem/Form.h>
17 
18 #include <dolfin/function/Function.h>
19 #include <dolfin/la/EigenVector.h>
20 
21 #include <string>
22 
23 #include <iostream>
24 #include <fstream>
25 
26 #include <cxxabi.h>
27 
28 std::string demangle_typename(const char* name) {
29 
30  int status = -4; // some arbitrary value to eliminate the compiler warning
31 
32  // enable c++11 by passing the flag -std=c++11 to g++
33  std::unique_ptr<char, void(*)(void*)> res {
34  abi::__cxa_demangle(name, NULL, NULL, &status),
35  std::free
36  };
37 
38  return (status==0) ? res.get() : name ;
39 }
40 
41 
42 namespace muq{
43  namespace Modeling{
44 
45  class FenicsPiece : public WorkPiece
46  {
47 
48  public:
49  FenicsPiece(pybind11::object const& problemIn,
50  pybind11::object const& outputFieldIn,
51  std::vector<pybind11::object> const& inputs) : WorkPiece(inputs.size(), 1){
52 
53  ExtractInputs(inputs);
54 
55  // First, make sure the input object is actually an instance of LinearVariationalProblem
56  CheckProblemType(problemIn, "LinearVariationalProblem");
57  CheckProblemType(outputFieldIn, "Function");
58 
59  problem = SwigExtract(problemIn);
60  outputField = SwigExtract(outputFieldIn);
61  };
62 
63 
64  void EvaluateFunc(std::vector<pybind11::object> const& inputs)
65  {
66  // Set all of the expressions
67  for(auto& expr : inputExprs)
68  {
69  CheckProblemType(inputs.at(expr.first),"list");
70 
71  auto xList = pybind11::list(inputs.at(expr.first));
72  for(unsigned i=0; i<expr.second.second.size(); ++i)
73  expr.second.first.attr(expr.second.second.at(i).c_str()) = xList[i];
74  }
75 
76  // Set all the functions
77  for(auto& f : inputFuncs)
78  {
79  CheckProblemType(inputs.at(f.first),"Function");
80  *f.second = *SwigExtract(inputs.at(f.first)).Cast<std::shared_ptr<dolfin::Function>>();
81  }
82  // Update each of the expressions
83 // exprs.at(0).attr("bc_val") = leftVal;
84 // exprs.at(1).attr("bc_val") = rightVal;
85 
86  //*inputField = *SwigExtract(f).Cast<std::shared_ptr<dolfin::Function>>();
87  dolfin::LinearVariationalSolver solver(problem);
88  solver.solve();
89  }
90 
91  virtual void EvaluateImpl(ref_vector<boost::any> const& inputs) override
92  {
93  // Loop over the function inputs
94  for(auto it = inputFuncs.begin(); it!= inputFuncs.end(); ++it)
95  {
96  // This is a reference to the vector defining the Dolfin function that we want to update
97  Eigen::VectorXd& inVec = *std::dynamic_pointer_cast<dolfin::EigenVector>(it->second->vector())->vec();
98 
99  // This is a reference to the vector containing the new values that we want to insert
100  Eigen::Ref<Eigen::Matrix<double, -1, -1, 1, -1, -1>, 0, Eigen::OuterStride<-1>> vec = boost::any_cast<Eigen::Ref<Eigen::Matrix<double, -1, -1, 1, -1, -1>, 0, Eigen::OuterStride<-1>> >(inputs.at(it->first).get());
101 
102  // Set the new values and update the function
103  inVec = vec;
104  it->second->update();
105  }
106 
107 
108  // Loop over the expression inputs
109  for(auto it = inputExprs.begin(); it!=inputExprs.end(); ++it)
110  {
111 
112  unsigned inputInd = it->first;
113 
114  std::pair<pybind11::object, std::vector<std::string>> &exprDef = it->second;
115 
116  // This is a reference to the vector containing the new values that we want to insert
117  if(inputs.at(inputInd).get().type() == typeid(double)){
118  double val = boost::any_cast<double>(inputs.at(inputInd).get());
119 
120  assert(exprDef.second.size()==1);
121 
122  exprDef.first.attr(exprDef.second.at(0).c_str()) = pybind11::cast(val);
123 
124  }else{
125  Eigen::Ref<Eigen::Matrix<double, -1, -1, 1, -1, -1>, 0, Eigen::OuterStride<-1>> vec = boost::any_cast<Eigen::Ref<Eigen::Matrix<double, -1, -1, 1, -1, -1>, 0, Eigen::OuterStride<-1>> >(inputs.at(inputInd).get());
126  assert(exprDef.second.size()==vec.rows());
127  for(int k=0; k<exprDef.second.size(); ++k){
128  exprDef.first.attr(exprDef.second.at(k).c_str()) = pybind11::cast(vec(k,0));
129  }
130  }
131 
132  }
133 
134 
135  // Solve the system!
136  dolfin::LinearVariationalSolver solver(problem);
137  solver.solve();
138 
139  std::shared_ptr<dolfin::EigenVector> vec = std::dynamic_pointer_cast<dolfin::EigenVector>(outputField->vector());
140  assert(vec);
141 
142  outputs.resize(1);
143  outputs.at(0) = Eigen::VectorXd(*vec->vec());
144  }
145 
146  boost::any EvaluateVec(Eigen::Ref<const Eigen::VectorXd> const& x, std::vector<double> vals)
147  {
148  //Eigen::VectorXd& inVec = std::dynamic_pointer_cast<dolfin::EigenVector>(inputField->vector())->vec();
149  //assert(inVec);
150 
151  // Update the value of the input field
152  //inVec = x;
153  //inputField->update();
154 
155  // Update each of the expressions
156  //exprs.at(0).attr("bc_val") = leftVal;
157  //exprs.at(1).attr("bc_val") = rightVal;
158 
159  dolfin::LinearVariationalSolver solver(problem);
160  solver.solve();
161 
162  std::shared_ptr<dolfin::EigenVector> vec = std::dynamic_pointer_cast<dolfin::EigenVector>(outputField->vector());
163  assert(vec);
164 
165  return *vec->vec();
166  };
167 
168  private:
169 
170  static void CheckProblemType(pybind11::object const& obj, std::string const& requiredType)
171  {
172  std::string typeName = pybind11::handle(obj).ptr()->ob_type->tp_name;
173 
174  if(typeName.compare(requiredType))
175  {
176  throw std::invalid_argument("FenicsPiece constructor was given an instance of \"" + typeName + "\" but requires an instance of \"" + requiredType + "\"");
177  }
178  }
179 
180  void ExtractInputs(std::vector<pybind11::object> const& inputs){
181 
182 
183  for(unsigned i=0; i<inputs.size(); ++ i){
184 
185 
186  // If the input is a list or tuple, then it should define an expression
187  if(pybind11::isinstance<pybind11::list>(inputs.at(i))){
188 
189  pybind11::list input(inputs[i]);
190 
191  pybind11::object expr = input[0];
192  CheckProblemType(expr, "CompiledExpression");
193 
194  CheckProblemType(input[1],"list");
195  pybind11::list part2(input[1]);
196 
197  if(pybind11::isinstance<pybind11::list>(part2) || pybind11::isinstance<pybind11::tuple>(part2)){
198 
199  std::vector<std::string> names;
200  for(auto& name : part2){
201  names.push_back(name.cast<std::string>());
202  }
203  inputExprs[i] = std::make_pair(expr, names);
204 
205  }
206 
207  }else{
208  CheckProblemType(inputs.at(i),"Function");
209  inputFuncs[i] = SwigExtract(inputs.at(i));
210  }
211  }
212  }
213 
214  std::map<unsigned, std::pair<pybind11::object, std::vector<std::string>>> inputExprs;
215  std::map<unsigned, std::shared_ptr<dolfin::Function>> inputFuncs;
216 
217  std::shared_ptr<dolfin::Function> outputField;
218  std::shared_ptr<dolfin::LinearVariationalProblem> problem;
219  };
220 
221  }// namespace Modeling
222 }// namespace muq
223 
224 
225 #endif
std::string demangle_typename(const char *name)
Definition: FenicsPiece.h:28
std::map< unsigned, std::shared_ptr< dolfin::Function > > inputFuncs
Definition: FenicsPiece.h:215
std::shared_ptr< dolfin::Function > outputField
Definition: FenicsPiece.h:217
virtual void EvaluateImpl(ref_vector< boost::any > const &inputs) override
User-implemented function that determines the behavior of this muq::Modeling::WorkPiece.
Definition: FenicsPiece.h:91
static void CheckProblemType(pybind11::object const &obj, std::string const &requiredType)
Definition: FenicsPiece.h:170
std::map< unsigned, std::pair< pybind11::object, std::vector< std::string > > > inputExprs
Definition: FenicsPiece.h:214
boost::any EvaluateVec(Eigen::Ref< const Eigen::VectorXd > const &x, std::vector< double > vals)
Definition: FenicsPiece.h:146
std::shared_ptr< dolfin::LinearVariationalProblem > problem
Definition: FenicsPiece.h:218
void ExtractInputs(std::vector< pybind11::object > const &inputs)
Definition: FenicsPiece.h:180
void EvaluateFunc(std::vector< pybind11::object > const &inputs)
Definition: FenicsPiece.h:64
FenicsPiece(pybind11::object const &problemIn, pybind11::object const &outputFieldIn, std::vector< pybind11::object > const &inputs)
Definition: FenicsPiece.h:49
Class to extract a c++ class that was exposed to python with Swig. @detials This class is used to unw...
Definition: SwigExtract.h:36
Base class for MUQ's modelling envronment.
Definition: WorkPiece.h:40
std::vector< boost::any > outputs
The outputs.
Definition: WorkPiece.h:546
std::string name
A unique name for this WorkPiece. Defaults to <ClassName>_<id>
Definition: WorkPiece.h:583
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
Definition: WorkPiece.h:37