void QRDecomposition<T>::backSub(const VectorT& b, VectorT& x) const { if(x.n == 0) x.resize(QR.n); Assert(QR.m == b.n); Assert(QR.n == x.n); /* compute rhs = Q^T b */ VectorT rhs; QtMul(b,rhs); if(QR.m == QR.n) { /* Solve R x = rhs, storing x in-place */ UBackSubstitute(QR,rhs,x); //UBackSubstitute(QR,x,x); } else if(QR.m > QR.n) { //solve the top part of R x = rhs MatrixT R1; R1.setRef(QR,0,0,1,1,QR.n,QR.n); VectorT rhs1; rhs1.setRef(rhs,0,1,QR.n); UBackSubstitute(R1,rhs1,x); } else { cerr<<"What do we do with m < n?"<<endl; MatrixPrinter mprint(QR); mprint.mode = MatrixPrinter::AsciiShade; cerr<<mprint<<endl; //solve the left part of R x = rhs MatrixT R1; R1.setRef(QR,0,0,1,1,QR.m,QR.m); VectorT x1; x1.setRef(x,0,1,QR.m); UBackSubstitute(R1,rhs,x1); getchar(); } }
void operator()(LinPdeSysT const & pde_system, SegmentT const & segment, StorageType & storage, MatrixT & system_matrix, VectorT & load_vector) { typedef viennamath::equation equ_type; typedef viennamath::expr expr_type; typedef typename expr_type::interface_type interface_type; typedef typename expr_type::numeric_type numeric_type; typedef typename viennagrid::result_of::cell_tag<SegmentT>::type CellTag; std::size_t map_index = viennafvm::create_mapping(pde_system, segment, storage); system_matrix.clear(); system_matrix.resize(map_index, map_index, false); load_vector.clear(); load_vector.resize(map_index); for (std::size_t pde_index = 0; pde_index < pde_system.size(); ++pde_index) { #ifdef VIENNAFVM_DEBUG std::cout << std::endl; std::cout << "//" << std::endl; std::cout << "// Equation " << pde_index << std::endl; std::cout << "//" << std::endl; #endif assemble(pde_system, pde_index, segment, storage, system_matrix, load_vector); } // for pde_index } // functor
void RowEchelon<T>::backSub(VectorT& x) const { Assert(EB.n == 1); Assert(EB.m == R.m); x.resize(R.n); VectorT b; EB.getColRef(0,b); Assert((int)firstEntry.size() == R.m+1); x.setZero(); int m=R.m,n=R.n; for(int i=m-1;i>=0;i--) { VectorT ri; R.getRowRef(i,ri); //solve to set R*x = b[i] //calculate alpha = dot between rest of x[>ji] and R[i] int ji=firstEntry[i]; if(ji == n) continue; int ji2=firstEntry[i+1]; //(i+1==m?n:firstEntry[i+1]); T alpha; if(ji2 == n) alpha = Zero; else { VectorT rji2; rji2.setRef(ri,ji2,1,R.n-ji2); VectorT xji2; xji2.setRef(x,ji2,1,R.n-ji2); alpha = xji2.dot(rji2); } x[ji] = (b[i]-alpha)/ri[ji]; } }
void SparseVectorTemplate<T>::get(VectorT& v) const { v.resize(this->n); int k=0; for(const_iterator i=this->begin();i!=this->end();i++) { while(k < i->first) { v(k)=0; k++; } v(k) = i->second; k=i->first+1; } while(k < (int)this->n) { v(k)=0; k++; } }
void DiagonalMatrixTemplate<T>::mulPseudoInverse(const VectorT& a, VectorT& b) const { if(BaseT::n != a.n) FatalError(MatrixError_ArgIncompatibleDimensions); if(b.n == 0) b.resize(this->n); else if(b.n != this->n) FatalError(MatrixError_DestIncompatibleDimensions); ItT v=this->begin(); VectorIterator<T> va=a.begin(),vb=b.begin(); for(int i=0; i<this->n; i++, v++,va++,vb++) *vb = *va * PseudoInv(*v); }
void SparseVectorCompressed<T>::get(VectorT& v) const { v.resize(n); int i=0; for(int k=0;k<num_entries;k++) { for(;i<indices[k];i++) v[i]=Zero; v[i]=vals[k]; } for(;i<this->n;i++) v[i]=Zero; }
void LDLDecomposition<T>::DBackSub(const VectorT& b, VectorT& x) const { x.resize(b.n); Assert(b.n==x.n); for(int i=0;i<x.n;i++) { if(!FuzzyZero(LDL(i,i),zeroTolerance)) x(i) = b(i)/LDL(i,i); else { if(!FuzzyZero(b(i),zeroTolerance)) cerr<<"LDLDecomposition::DBackSub(): Warning, zero on the diagonal"<<endl; x(i) = 0; } } }
void SparseMatrixTemplate_RM<T>::mulTranspose(const VectorT& a,VectorT& x) const { if(x.n == 0) x.resize(n); if(x.n != n) { FatalError("Destination vector has incorrect dimensions"); } if(a.n != m) { FatalError("Source vector has incorrect dimensions"); } x.setZero(); for(int i=0;i<m;i++) { for(ConstRowIterator it=rows[i].begin();it!=rows[i].end();it++) x(it->first) += it->second*a(i); } }
void SparseMatrixTemplate_RM<T>::mul(const VectorT& a,VectorT& x) const { if(x.n == 0) x.resize(m); if(x.n != m) { FatalError("Destination vector has incorrect dimensions"); } if(a.n != n) { FatalError("Source vector has incorrect dimensions"); } for(int i=0;i<m;i++) { T sum=0; for(ConstRowIterator it=rows[i].begin();it!=rows[i].end();it++) sum += it->second*a(it->first); x(i) = sum; } }
void MatrixTemplate<T>::maddTranspose(const VectorT& a, VectorT& b) const { if(m != a.n) { RaiseErrorFmt(WHERE_AM_I,MatrixError_ArgIncompatibleDimensions); } if(b.n == 0) { b.resize(n); } else if(b.n != n) { RaiseErrorFmt(WHERE_AM_I,MatrixError_DestIncompatibleDimensions); } gen_array2d_vector_madd_transpose(b.getStart(),b.stride, getStart(),istride,jstride, a.getStart(),a.stride, m, n); }
bool LDLDecomposition<T>::DBackSub(const VectorT& b, VectorT& x) const { bool res=true; x.resize(b.n); Assert(b.n==x.n); for(int i=0;i<x.n;i++) { if(!FuzzyZero(LDL(i,i),zeroTolerance)) x(i) = b(i)/LDL(i,i); else { if(!FuzzyZero(b(i),zeroTolerance)) { if(verbose >= 1) LOG4CXX_ERROR(KrisLibrary::logger(),"LDLDecomposition::DBackSub(): Warning, zero on the diagonal, b("<<i<<")="<<b(i)); res = false; x(i) = Sign(b(i))*Inf; } else x(i) = 0; } } return res; }
void QRDecomposition<T>::leastSquares(const VectorT& b, VectorT& x, VectorT& residual) const { if(x.n == 0) x.resize(QR.n); Assert(QR.m >= QR.n); Assert(QR.m == b.n); Assert(QR.n == x.n); Assert(QR.m == residual.n); MatrixT R; R.setRef(QR,0,0,1,1,QR.n,QR.n); VectorT c; c.setRef(residual,0,1,QR.n); /* compute rhs = Q^T b */ QtMul(b,residual); /* Solve R x = rhs */ UBackSubstitute(R,c,x); /* Compute residual = b - A x = Q (Q^T b - R x) */ c.setZero(); QMul(residual,residual); }
void LDLDecomposition<T>::getD(VectorT& d) const { Assert(LDL.m == LDL.n); d.resize(LDL.n); LDL.getDiagCopy(0,d); }
void LDLDecomposition<T>::LTBackSub(const VectorT& b, VectorT& x) const { Assert(b.n == LDL.n); x.resize(LDL.n); Lt1BackSubstitute(LDL,b,x); }
void operator()(SystemType pde_system, DomainType & domain, MatrixT & system_matrix, VectorT & load_vector ) const { typedef typename viennagrid::result_of::cell_tag<DomainType>::type CellTag; typedef typename viennagrid::result_of::point<DomainType>::type PointType; typedef typename viennagrid::result_of::element<DomainType, CellTag>::type CellType; typedef typename viennagrid::result_of::element_range<DomainType, CellTag>::type CellContainer; typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator; typedef typename SystemType::equation_type EquationType; #ifdef VIENNAFEM_DEBUG std::cout << "Strong form: " << pde_system.pde(0) << std::endl; #endif log_strong_form(pde_system); EquationType weak_form_general = viennafem::make_weak_form(pde_system.pde(0)); #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Using weak form general: " << weak_form_general << std::endl; #endif std::vector<EquationType> temp(1); temp[0] = weak_form_general; log_weak_form(temp, pde_system); EquationType weak_form = viennamath::apply_coordinate_system(viennamath::cartesian< PointType::dim >(), weak_form_general); //EquationType weak_form = viennamath::apply_coordinate_system(viennamath::cartesian<Config::coordinate_system_tag::dim>(), weak_form_general); temp[0] = weak_form; log_coordinated_weak_form(temp, pde_system); #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Using weak form " << weak_form << std::endl; std::cout << "* pde_solver::operator(): Write dt_dx coefficients" << std::endl; #endif typedef typename reference_cell_for_basis<CellTag, viennafem::lagrange_tag<1> >::type ReferenceCell; // // Create accessors for performance in the subsequent dt_dx_handler step // //viennafem::dtdx_assigner<DomainType, StorageType, ReferenceCell>::apply(domain, storage); viennafem::dt_dx_handler<DomainType, StorageType, ReferenceCell> dt_dx_handler(domain, storage); //fill with cell quantities CellContainer cells = viennagrid::elements<CellType>(domain); for (CellIterator cell_iter = cells.begin(); cell_iter != cells.end(); ++cell_iter) { //cell_iter->print_short(); //viennadata::access<example_key, double>()(*cell_iter) = i; //viennafem::dt_dx_handler<ReferenceCell>::apply(storage, *cell_iter); dt_dx_handler(*cell_iter); } #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Create Mapping:" << std::endl; #endif std::size_t map_index = create_mapping(storage, pde_system, domain); #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Assigned degrees of freedom in domain so far: " << map_index << std::endl; #endif // resize global system matrix and load vector if needed: // TODO: This can be a performance bottleneck for large numbers of segments! (lots of resize operations...) if (map_index > system_matrix.size1()) { MatrixT temp = system_matrix; ////std::cout << "Resizing system matrix..." << std::endl; system_matrix.resize(map_index, map_index, false); system_matrix.clear(); system_matrix.resize(map_index, map_index, false); for (typename MatrixT::iterator1 row_it = temp.begin1(); row_it != temp.end1(); ++row_it) { for (typename MatrixT::iterator2 col_it = row_it.begin(); col_it != row_it.end(); ++col_it) system_matrix(col_it.index1(), col_it.index2()) = *col_it; } } if (map_index > load_vector.size()) { VectorT temp = load_vector; #ifdef VIENNAFEM_DEBUG std::cout << "Resizing load vector..." << std::endl; #endif load_vector.resize(map_index, false); load_vector.clear(); load_vector.resize(map_index, false); for (std::size_t i=0; i<temp.size(); ++i) load_vector(i) = temp(i); } #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Transform to reference element" << std::endl; #endif EquationType transformed_weak_form = viennafem::transform_to_reference_cell<CellType>(storage, weak_form, pde_system); temp[0] = transformed_weak_form; log_transformed_weak_form<CellType, StorageType>(temp, pde_system); std::cout << "* pde_solver::operator(): Transformed weak form:" << std::endl; std::cout << transformed_weak_form << std::endl; //std::cout << std::endl; #ifdef VIENNAFEM_DEBUG std::cout << "* pde_solver::operator(): Assemble system" << std::endl; #endif typedef detail::equation_wrapper<MatrixT, VectorT> wrapper_type; wrapper_type wrapper(system_matrix, load_vector); detail::pde_assembler_internal()(storage, transformed_weak_form, pde_system, domain, wrapper); // pde_assembler_internal()(transformed_weak_form, pde_system, domain, system_matrix, load_vector); }
void CholeskyDecomposition<T>::LTBackSub(const VectorT& b, VectorT& x) const { x.resize(L.n); if(!LtBackSubstitute(L,b,x)) FatalError("CholeskyDecomposition: LtBackSubstitute failed!"); }