void solve_adjoint_sensitivity(std::vector<std::vector<Real> > &P, const std::vector<std::vector<Real> > &U) { // Get Diagonal and Off-Diagonal Entries of PDE Jacobian std::vector<Real> d(nx_,4.0*dx_/6.0 + dt_*2.0/dx_); d[0] = dx_/3.0 + dt_/dx_; d[nx_-1] = dx_/3.0 + dt_/dx_; std::vector<Real> o(nx_-1,dx_/6.0 - dt_/dx_); // Perform LDL factorization Teuchos::LAPACK<int,Real> lp; int info; int ldb = nx_; int nhrs = 1; lp.PTTRF(nx_,&d[0],&o[0],&info); // Initialize State Storage P.clear(); P.resize(nt_); // Time Step Using Implicit Euler std::vector<Real> b(nx_,0.0); for ( uint t = nt_; t > 0; t-- ) { // Get Right Hand Side if ( t == nt_ ) { apply_mass(b,U[t-1]); } else { apply_mass(b,P[t]); } // Solve Tridiagonal System Using LAPACK's SPD Tridiagonal Solver lp.PTTRS(nx_,nhrs,&d[0],&o[0],&b[0],ldb,&info); // Update State Storage (P[t-1]).assign(b.begin(),b.end()); } }
void solve_state(std::vector<std::vector<Real> > &U, const std::vector<Real> &z) { // Get Diagonal and Off-Diagonal Entries of PDE Jacobian std::vector<Real> d(nx_,4.0*dx_/6.0 + dt_*2.0/dx_); d[0] = dx_/3.0 + dt_/dx_; d[nx_-1] = dx_/3.0 + dt_/dx_; std::vector<Real> o(nx_-1,dx_/6.0 - dt_/dx_); // Perform LDL factorization Teuchos::LAPACK<int,Real> lp; int info; int ldb = nx_; int nhrs = 1; lp.PTTRF(nx_,&d[0],&o[0],&info); // Initialize State Storage U.clear(); U.resize(nt_+1); (U[0]).assign(u0_.begin(),u0_.end()); // Time Step Using Implicit Euler std::vector<Real> b(nx_,0.0); for ( uint t = 0; t < nt_; t++ ) { // Get Right Hand Side apply_mass(b,U[t]); b[nx_-1] += dt_*z[t]; // Solve Tridiagonal System Using LAPACK's SPD Tridiagonal Solver lp.PTTRS(nx_,nhrs,&d[0],&o[0],&b[0],ldb,&info); // Update State Storage (U[t+1]).assign(b.begin(),b.end()); } }