std::vector<float> sparseVecMult(const SparseMatrix &matrix, std::vector<float> vec, CL::TinyCL &tiny){ if (vec.size() != matrix.dim){ std::cout << "Vector size doesn't match matrix dimensions" << std::endl; return std::vector<float>(); } cl::Program program = tiny.loadProgram("../res/sparseMatVec.cl"); cl::Kernel kernel = tiny.loadKernel(program, "sparseMatVec"); int nVals = matrix.elements.size(); int *rows = new int[nVals]; int *cols = new int[nVals]; float *vals = new float[nVals]; matrix.getRaw(rows, cols, vals); cl::Buffer rowBuf = tiny.buffer(CL::MEM::READ_ONLY, nVals * sizeof(float), rows); cl::Buffer colBuf = tiny.buffer(CL::MEM::READ_ONLY, nVals * sizeof(float), cols); cl::Buffer valBuf = tiny.buffer(CL::MEM::READ_ONLY, nVals * sizeof(float), vals); cl::Buffer vecBuf = tiny.buffer(CL::MEM::READ_ONLY, vec.size() * sizeof(float), &vec[0]); cl::Buffer resBuf = tiny.buffer(CL::MEM::WRITE_ONLY, vec.size() * sizeof(float)); kernel.setArg(0, sizeof(int), &nVals); kernel.setArg(1, rowBuf); kernel.setArg(2, colBuf); kernel.setArg(3, valBuf); kernel.setArg(4, vecBuf); kernel.setArg(5, resBuf); tiny.runKernel(kernel, cl::NullRange, matrix.dim); std::vector<float> result; result.resize(matrix.dim); tiny.readData(resBuf, matrix.dim * sizeof(float), &result[0], NULL, true); delete[] rows; delete[] cols; delete[] vals; return result; }
void Fill( SparseMatrix<T>& A, T alpha ) { EL_DEBUG_CSE const Int m = A.Height(); const Int n = A.Width(); A.Resize( m, n ); Zero( A ); if( alpha != T(0) ) { A.Reserve( m*n ); for( Int i=0; i<m; ++i ) for( Int j=0; j<n; ++j ) A.QueueUpdate( i, j, alpha ); A.ProcessQueues(); } }
void MatrixMarket( const SparseMatrix<T>& A, string basename="matrix" ) { EL_DEBUG_CSE string filename = basename + "." + FileExtension(MATRIX_MARKET); ofstream file( filename.c_str(), std::ios::binary ); if( !file.is_open() ) RuntimeError("Could not open ",filename); // Write the header // ================ { ostringstream os; os << "%%MatrixMarket matrix coordinate "; if( IsComplex<T>::value ) os << "complex "; else os << "real "; os << "general\n"; file << os.str(); } // Write the size line // =================== const Int m = A.Height(); const Int n = A.Width(); const Int numNonzeros = A.NumEntries(); file << BuildString(m," ",n," ",numNonzeros,"\n"); // Write the entries // ================= for( Int e=0; e<numNonzeros; ++e ) { const Int i = A.Row(e); const Int j = A.Col(e); const T value = A.Value(e); if( IsComplex<T>::value ) { file << BuildString(i," ",j," ",RealPart(value)," ",ImagPart(value),"\n"); } else { file << BuildString(i," ",j," ",RealPart(value),"\n"); } } }
double functionOfW(vector<double>& w, vector<int>& Y, SparseMatrix<double,Eigen::RowMajor>& X) { size_t i; double sum=0.0; double sum2 = 0.0; for (i=0; i<w.size(); i++) { sum+=w.at(i)*w.at(i); } sum = sum*0.5; //cout<<"sum = "<<sum<<endl; int j; for (j=0; j<X.outerSize(); j++) { double dot = 0; for (SparseMatrix<double,Eigen::RowMajor>::InnerIterator it(X,j); it; ++it) { dot+=w.at(it.col())*it.value(); } double temp = exp(-(Y.at(j)*dot)); sum2+= log(1+temp); //cout<<"sum2 = "<<sum2<<endl; } return sum+sum2; }
void MatrixUtils::bloc_to_sparse_copyDownTopLeftRight(const SparseBlocMatrix<ContiguousBloc<Element, Index> >& A, SparseMatrix<Element>& B) { uint32 curr_row_B = B.rowdim() - 1; for(uint32 i=0; i<A.rowBlocDim (); ++i) //for each row of blocs in A, starting at the last row in B { if(A[i].empty ()) { curr_row_B -= A.bloc_height(); continue; } if(A.isFilledWithEmptyBlocs()) check_equal_or_raise_exception(A.FirstBlocsColumIndexes[i], 0); for(uint32 j=0;j<A[i].size (); ++j) //for each bloc in the row { if(A[i][j].empty ()) { continue; } uint32 bloc_idx = A.FirstBlocsColumIndexes[i] + (A.bloc_width() * j); for(uint16 k=0; k<A.bloc_height () && k <= curr_row_B; ++k) //for each row in the bloc { for (uint32 l = 0; l < A[i][j].get_row_size(k); ++l) { B[curr_row_B-k].push_back( typename SparseMatrix<Element>::Row::value_type( bloc_idx + A[i][j].pos_in_row(k, l), A[i][j].value_in_row(k, l))); } } } curr_row_B -= A.bloc_height(); } }
void makeBoundaryMatrix (SparseMatrix<double>& boundaryMatrix, const int M, const int N, const double h, const double * viscosityData) { #ifdef DEBUG cout << "<Creating " << 3 * M * N - M - N << "x" << 2 * M + 2 * N << " BoundaryMatrix>" << endl; #endif vector<Triplet<double> > tripletList; makeBCLaplacianXBlock (tripletList, 0, 0, M, N, h, viscosityData); makeBCLaplacianYBlock (tripletList, M * (N - 1), 2 * M, M, N, h, viscosityData); makeBCDivXBlock (tripletList, 2 * M * N - M - N, 0, M, N, h); makeBCDivYBlock (tripletList, 2 * M * N - M - N, 2 * M, M, N, h); boundaryMatrix.setFromTriplets (tripletList.begin(), tripletList.end()); #ifdef DEBUG cout << endl; #endif }
void COctaveInterface::get_real_sparsematrix(SGSparseVector<float64_t>*& matrix, int32_t& num_feat, int32_t& num_vec) { const octave_value mat_feat=get_arg_increment(); if (!mat_feat.is_sparse_type() || !(mat_feat.is_double_type())) SG_ERROR("Expected Sparse Double Matrix as argument %d\n", m_rhs_counter); SparseMatrix sm = mat_feat.sparse_matrix_value (); num_vec=sm.cols(); num_feat=sm.rows(); int64_t nnz=sm.nelem(); matrix=new SGSparseVector<float64_t>[num_vec]; int64_t offset=0; for (int32_t i=0; i<num_vec; i++) { int32_t len=sm.cidx(i+1)-sm.cidx(i); matrix[i].vec_index=i; matrix[i].num_feat_entries=len; if (len>0) { matrix[i].features=new SGSparseVectorEntry<float64_t>[len]; for (int32_t j=0; j<len; j++) { matrix[i].features[j].entry=sm.data(offset); matrix[i].features[j].feat_index=sm.ridx(offset); offset++; } } else matrix[i].features=NULL; } ASSERT(offset=nnz); }
void makeStokesMatrix (SparseMatrix<double>& stokesMatrix, const int M, const int N, const double h, const double * viscosityData) { #ifdef DEBUG cout << "<Creating " << 3 * M * N - M - N << "x" << 3 * M * N - M - N << " stokesMatrix>" << endl; #endif vector<Triplet<double> > tripletList; makeLaplacianXBlock (tripletList, 0, 0, M, N, h, viscosityData); makeLaplacianYBlock (tripletList, M * (N - 1), M * (N - 1), M, N, h, viscosityData); makeGradXBlock (tripletList, 0, 2 * M * N - M - N, M, N, h); makeGradYBlock (tripletList, M * (N - 1), 2 * M * N - M - N, M, N, h); makeDivXBlock (tripletList, 2 * M * N - M - N, 0, M, N, h); makeDivYBlock (tripletList, 2 * M * N - M - N, M * (N - 1), M, N, h); stokesMatrix.setFromTriplets (tripletList.begin(), tripletList.end()); #ifdef DEBUG cout << endl; #endif }
void Assembly::addCachedJacobian(SparseMatrix<Number> & jacobian) { mooseAssert(_cached_jacobian_rows.size() == _cached_jacobian_cols.size(), "Error: Cached data sizes MUST be the same!"); for(unsigned int i=0; i<_cached_jacobian_rows.size(); i++) jacobian.add(_cached_jacobian_rows[i], _cached_jacobian_cols[i], _cached_jacobian_values[i]); if (_max_cached_jacobians < _cached_jacobian_values.size()) _max_cached_jacobians = _cached_jacobian_values.size(); // Try to be more efficient from now on // The 2 is just a fudge factor to keep us from having to grow the vector during assembly _cached_jacobian_values.clear(); _cached_jacobian_values.reserve(_max_cached_jacobians*2); _cached_jacobian_rows.clear(); _cached_jacobian_rows.reserve(_max_cached_jacobians*2); _cached_jacobian_cols.clear(); _cached_jacobian_cols.reserve(_max_cached_jacobians*2); }
std::pair<unsigned int, Real> EigenSparseLinearSolver<T>::adjoint_solve (SparseMatrix<T> &matrix_in, NumericVector<T> &solution_in, NumericVector<T> &rhs_in, const double tol, const unsigned int m_its) { START_LOG("adjoint_solve()", "EigenSparseLinearSolver"); libmesh_experimental(); EigenSparseMatrix<T> mat_trans(this->comm()); matrix_in.get_transpose(mat_trans); std::pair<unsigned int, Real> retval = this->solve (mat_trans, solution_in, rhs_in, tol, m_its); STOP_LOG("adjoint_solve()", "EigenSparseLinearSolver"); return retval; }
void SymmetricRuizEquil ( SparseMatrix<F>& A, Matrix<Base<F>>& d, Int maxIter, bool progress ) { DEBUG_CSE typedef Base<F> Real; const Int n = A.Height(); Ones( d, n, 1 ); Matrix<Real> scales; const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns (and rows) // ------------------------------ ColumnMaxNorms( A, scales ); EntrywiseMap( scales, function<Real(Real)>(DampScaling<Real>) ); EntrywiseMap( scales, function<Real(Real)>(SquareRootScaling<Real>) ); DiagonalScale( LEFT, NORMAL, scales, d ); SymmetricDiagonalSolve( scales, A ); } SetIndent( indent ); }
void JordanCholesky( SparseMatrix<T>& A, Int n ) { DEBUG_ONLY(CSE cse("JordanCholesky")) Zeros( A, n, n ); A.Reserve( 3*n ); for( Int e=0; e<n; ++e ) { if( e == 0 ) A.QueueUpdate( e, e, T(1) ); else A.QueueUpdate( e, e, T(5) ); if( e > 0 ) A.QueueUpdate( e, e-1, T(2) ); if( e < n-1 ) A.QueueUpdate( e, e+1, T(2) ); } A.ProcessQueues(); }
SparseMatrix<double,0,int> Qinv2(SparseMatrix<double,0,int>& L) { int n = L.rows(); SparseMatrix<double,0,int> Sigma; Sigma.resize(n,n); Sigma.reserve(L.nonZeros()*50); int j; double Lii, val; for (int i=n-1; i>=0; i--) { for(SparseMatrix<double>::ReverseInnerIterator ij(L,i);ij;--ij) { j=ij.row(); val = 0; SparseMatrix<double>::InnerIterator iL(L,i); SparseMatrix<double>::InnerIterator iS(Sigma,j); for(; iL; ++iL) { if(iL.row() == iL.col()){ Lii = iL.value(); } else { for(;iS.row() < iL.row(); ++iS){} if(iS.row() == iL.row()) val += iL.value()*iS.value(); } } if(i==j){ Sigma.insert(i,j) = 1/(Lii*Lii) - val/Lii; } else { Sigma.insert(i,j) = -val/Lii; Sigma.insert(j,i) = -val/Lii; } } } return Sigma; }
void add_state_unit(const int node_dim, const int node_idx) { t_managing_ = clock(); n_nodes_++; nodes_.push_back(node(node_idx, node_dim, x_incr_.size(), n_nodes_-1)); // Resize accumulated permutations augment_permutation(acc_node_permutation_, n_nodes_); // Resize state x_incr_.conservativeResize(x_incr_.size() + node_dim); // Resize problem A_.conservativeResize(A_.rows(), A_.cols() + node_dim); R_.conservativeResize(R_.cols() + node_dim, R_.cols() + node_dim); //A_nodes_.conservativeResize(n_measurements, n_nodes); // not necessary time_managing_ += ((double) clock() - t_managing_) / CLOCKS_PER_SEC; }
// Solve the symmetric system: At·A·x = At·b bool nv::LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon/*1e-5f*/) { nvDebugCheck(A.width() == x.dimension()); nvDebugCheck(A.height() == b.dimension()); nvDebugCheck(A.height() >= A.width()); // @@ If height == width we could solve it directly... const uint D = A.width(); SparseMatrix At(A.height(), A.width()); transpose(A, At); FullVector Atb(D); //mult(Transposed, A, b, Atb); mult(At, b, Atb); SparseMatrix AtA(D); //mult(Transposed, A, NoTransposed, A, AtA); mult(At, A, AtA); return SymmetricSolver(AtA, Atb, x, epsilon); }
void GetMappedDiagonal ( const SparseMatrix<T>& A, Matrix<S>& d, function<S(const T&)> func, Int offset ) { EL_DEBUG_CSE const Int m = A.Height(); const Int n = A.Width(); const T* valBuf = A.LockedValueBuffer(); const Int* colBuf = A.LockedTargetBuffer(); const Int iStart = Max(-offset,0); const Int jStart = Max( offset,0); const Int diagLength = El::DiagonalLength(m,n,offset); d.Resize( diagLength, 1 ); Zero( d ); S* dBuf = d.Buffer(); for( Int k=0; k<diagLength; ++k ) { const Int i = iStart + k; const Int j = jStart + k; const Int thisOff = A.RowOffset(i); const Int nextOff = A.RowOffset(i+1); auto it = std::lower_bound( colBuf+thisOff, colBuf+nextOff, j ); if( *it == j ) { const Int e = it-colBuf; dBuf[Min(i,j)] = func(valBuf[e]); } else dBuf[Min(i,j)] = func(0); } }
/*! @param spm Matrix A in Sparse form*/ void SparseMatrix::extractdiagonal(SparseMatrix & spm){ for(int i = 0; i < spm.get_row_size(); i++){ float temp = 1.0/spm.getValue(i,i); update_matrix(temp,i,i); } }
void Simulation::staticSolveNewtonsForces(MatrixXd& TV, MatrixXi& TT, MatrixXd& B, VectorXd& fixed_forces, int ignorePastIndex){ cout<<"----------------Static Solve Newtons, Fix Forces-------------"<<endl; //Newtons method static solve for minimum Strain E SparseMatrix<double> forceGradient; forceGradient.resize(3*TV.rows(), 3*TV.rows()); SparseMatrix<double> forceGradientStaticBlock; forceGradientStaticBlock.resize(3*ignorePastIndex, 3*ignorePastIndex); VectorXd f, x; f.resize(3*TV.rows()); f.setZero(); x.resize(3*TV.rows()); x.setZero(); setTVtoX(x, TV); cout<<x<<endl; int NEWTON_MAX = 100, k=0; for(k=0; k<NEWTON_MAX; k++){ xToTV(x, TV); calculateForceGradient(TV, forceGradient); calculateElasticForces(f, TV); for(unsigned int i=0; i<fixed_forces.rows(); i++){ if(abs(fixed_forces(i))>0.000001){ if(i>3*ignorePastIndex){ cout<<"Problem Check simulation.cpp file"<<endl; cout<<ignorePastIndex<<endl; cout<<i<<" - "<<fixed_forces(i)<<endl; exit(0); } f(i) = fixed_forces(i); } } //Block forceGrad and f to exclude the fixed verts forceGradientStaticBlock = forceGradient.block(0,0, 3*(ignorePastIndex), 3*ignorePastIndex); VectorXd fblock = f.head(ignorePastIndex*3); //Sparse QR // SparseQR<SparseMatrix<double>, COLAMDOrdering<int>> sqr; // sqr.compute(forceGradientStaticBlock); // VectorXd deltaX = -1*sqr.solve(fblock); // Conj Grad ConjugateGradient<SparseMatrix<double>> cg; cg.compute(forceGradientStaticBlock); if(cg.info() == Eigen::NumericalIssue){ cout<<"ConjugateGradient numerical issue"<<endl; exit(0); } VectorXd deltaX = -1*cg.solve(fblock); // // Sparse Cholesky LL^T // SimplicialLLT<SparseMatrix<double>> llt; // llt.compute(forceGradientStaticBlock); // if(llt.info() == Eigen::NumericalIssue){ // cout<<"Possibly using a non- pos def matrix in the LLT method"<<endl; // exit(0); // } // VectorXd deltaX = -1*llt.solve(fblock); x.segment(0,3*(ignorePastIndex))+=deltaX; cout<<" Newton Iter "<<k<<endl; if(x != x){ cout<<"NAN"<<endl; exit(0); } cout<<"fblock square norm"<<endl; cout<<fblock.squaredNorm()/fblock.size()<<endl; double strainE = 0; for(int i=0; i< M.tets.size(); i++){ strainE += M.tets[i].undeformedVol*M.tets[i].energyDensity; } cout<<strainE<<endl; if (fblock.squaredNorm()/fblock.size() < 0.00001){ break; } } if(k== NEWTON_MAX){ cout<<"ERROR Static Solve: Newton max reached"<<endl; cout<<k<<endl; exit(0); } double strainE = 0; for(int i=0; i< M.tets.size(); i++){ strainE += M.tets[i].undeformedVol*M.tets[i].energyDensity; } cout<<"strain E"<<strainE<<endl; cout<<"x[0] "<<x(0)<<endl; cout<<"x[1] "<<x(1)<<endl; exit(0); cout<<"-------------------"<<endl; }
void SparseMatrix::copy(SparseMatrix & spm){ // cout << spm.get_row_size(); I.set_size(spm.get_row_size() + 1); J.set_size(spm.get_non_zero_enteries()); Elements.set_size(spm.get_non_zero_enteries()); number_of_rows = spm.get_row_size(); // cout << number_of_rows; number_of_non_zero = spm.get_non_zero_enteries(); size_of_array = spm.get_size(); for (int i = 0; i < spm.get_row_size() + 1;i++){ // cout << "row"; I[i] = spm.get_I(i); } for (int i = 0; i < spm.get_non_zero_enteries();i++){ // cout << "volumn"; J[i] = spm.get_J(i); } for (int i = 0; i < spm.get_non_zero_enteries(); i++){ // cout << spm.get_non_zero_Elements(i); Elements[i] = spm.get_non_zero_Elements(i); // cout << Elements[i]; } }
SparseILUPreconditioner::SparseILUPreconditioner(const SparseMatrix& A, Integer lfil) : L_(A.size1(),A.size2()), U_(A.size1(),A.size2()) { QL_REQUIRE(A.size1() == A.size2(), "sparse ILU preconditioner works only with square matrices"); for (SparseMatrix::size_type i=0; i < L_.size1(); ++i) L_(i,i) = 1.0; const Integer n = A.size1(); std::set<Integer> lBandSet, uBandSet; compressed_matrix<Integer> levs(n,n); Integer lfilp = lfil + 1; for (Integer ii=0; ii<n; ++ii) { Array w(n); for(Integer k=0; k<n; ++k) { w[k] = A(ii,k); } std::vector<Integer> levii(n, 0); for (Integer i=0; i<n; ++i) { if( w[i] > QL_EPSILON || w[i] < -1.0*QL_EPSILON) levii[i] = 1; } Integer jj = -1; while (jj < ii) { for (Integer k=jj+1; k<n; ++k) { if(levii[k]) { jj = k; break; } } if (jj >= ii) { break; } Integer jlev = levii[jj]; if (jlev <= lfilp) { std::vector<Integer> nonZeros; std::vector<Real> nonZeroEntries; nonZeros.reserve(uBandSet.size()+1); nonZeroEntries.reserve(uBandSet.size()+1); const Real entry = U_(jj,jj); if(entry > QL_EPSILON || entry < -1.0*QL_EPSILON) { nonZeros.push_back(jj); nonZeroEntries.push_back(entry); } std::set<Integer>::const_iterator iter=uBandSet.begin(); std::set<Integer>::const_iterator end =uBandSet.end(); for (; iter != end; ++iter) { const Real entry = U_(jj,jj+*iter); if(entry > QL_EPSILON || entry < -1.0*QL_EPSILON) { nonZeros.push_back(jj+*iter); nonZeroEntries.push_back(entry); } } Real fact = w[jj]; if(!nonZeroEntries.empty()) { fact /= nonZeroEntries[0]; } for (Size k=0; k<nonZeros.size(); ++k) { const Integer j = nonZeros[k] ; const Integer temp = levs(jj,j) + jlev ; if (levii[j] == 0) { if (temp <= lfilp) { w[j] = - fact*nonZeroEntries[k]; levii[j] = temp; } } else { w[j] -= fact*nonZeroEntries[k]; levii[j] = std::min(levii[j],temp); } } w[jj] = fact; } } std::vector<Integer> wNonZeros; std::vector<Real> wNonZeroEntries; wNonZeros.reserve(w.size()); wNonZeroEntries.reserve(w.size()); for (Size i=0; i<w.size(); ++i) { const Real entry = w[i]; if(entry > QL_EPSILON || entry < -1.0*QL_EPSILON) { wNonZeros.push_back(i); wNonZeroEntries.push_back(entry); } } std::vector<Integer> leviiNonZeroEntries; leviiNonZeroEntries.reserve(levii.size()); for (Size i=0; i<levii.size(); ++i) { const Integer entry = levii[i]; if(entry > QL_EPSILON || entry < -1.0*QL_EPSILON) { leviiNonZeroEntries.push_back(entry); } } for (Size k=0; k<wNonZeros.size(); ++k) { Integer j = wNonZeros[k]; if (j < ii) { L_(ii,j) = wNonZeroEntries[k]; lBandSet.insert(ii-j); } else { U_(ii,j) = wNonZeroEntries[k]; levs(ii,j) = leviiNonZeroEntries[k]; if(j-ii > 0) { uBandSet.insert(j-ii); } } } } lBands_.resize(lBandSet.size()); uBands_.resize(uBandSet.size()); std::copy(lBandSet.begin(), lBandSet.end(), lBands_.begin()); std::copy(uBandSet.begin(), uBandSet.end(), uBands_.begin()); }
void levelGen<T>::generateRP(const FixedSparseMatrix<T> &A, FixedSparseMatrix<T> &R, FixedSparseMatrix<T> &P, int ni, int nj, int nk) { //matlab code(2D): //m = ceil(M/2); //n = ceil(N/2); //R = sparse(zeros(m*n, M*N)); //coef = [1 3 3 1; 3 9 9 3; 3 9 9 3; 1 3 3 1]/16.0; //for i=0:m-1 // for j=0:n-1 // index = i*n + j +1; // for ii=0:1 // for jj=0:1 // iii = i*2+ii; // jjj = j*2+jj; // if iii<M && jjj<N && iii>=0 && jjj>=0 // index2 = iii*N + jjj +1; // if A(index2,index2)~=0 // R(index, index2) = 0.25; // %R(index, index2) = coef(ii+2,jj+2)/4; // else // R(index, index2) = 0.0; // end // end // end // end // end //end //P = 4*R'; int nni = ceil((float)ni/2.0); int nnj = ceil((float)nj/2.0); int nnk = ceil((float)nk/2.0); SparseMatrix<T> r; SparseMatrix<T> p; p.resize(ni*nj*nk); p.zero(); r.resize(nni*nnj*nnk); r.zero(); for(int k=0;k<nnk;k++)for(int j=0;j<nnj;j++)for (int i=0;i<nni;i++) { unsigned int index = (k*nnj +j)*nni + i; for(int kk=0;kk<=1;kk++)for(int jj=0;jj<=1;jj++)for(int ii=0;ii<=1;ii++) { int iii = i*2 + ii; int jjj = j*2 + jj; int kkk = k*2 + kk; if(iii<ni && jjj<nj && kkk<nk) { unsigned int index2 = (kkk*nj + jjj)*ni + iii; r.set_element(index, index2, (T)0.125); p.set_element(index2,index, 1.0); } } } R.construct_from_matrix(r); P.construct_from_matrix(p); r.clear(); p.clear(); //transposeMat(R,P,(T)8.0); }
void AssembleMatrixResNS(MultiLevelProblem &ml_prob){ adept::Stack & adeptStack = FemusInit::_adeptStack; clock_t AssemblyTime=0; clock_t start_time, end_time; //pointers and references NonLinearImplicitSystem& my_nnlin_impl_sys = ml_prob.get_system<NonLinearImplicitSystem>("Navier-Stokes"); const unsigned level = my_nnlin_impl_sys.GetLevelToAssemble(); const unsigned gridn = my_nnlin_impl_sys.GetLevelMax(); bool assemble_matrix = my_nnlin_impl_sys.GetAssembleMatrix(); MultiLevelSolution* ml_sol = ml_prob._ml_sol; Solution* mysolution = ml_sol->GetSolutionLevel(level); LinearEquationSolver* myLinEqSolver = my_nnlin_impl_sys._LinSolver[level]; Mesh *mymsh = ml_prob._ml_msh->GetLevel(level); elem *myel = mymsh->el; SparseMatrix *myKK = myLinEqSolver->_KK; NumericVector *myRES = myLinEqSolver->_RES; const unsigned dim = mymsh->GetDimension(); const unsigned nabla_dim = 3*(dim-1); const unsigned max_size = static_cast< unsigned > (ceil(pow(3,dim))); // local objects vector<adept::adouble> SolVAR(dim+1); vector<vector<adept::adouble> > GradSolVAR(dim+1); vector<vector<adept::adouble> > NablaSolVAR(dim+1); for(int i=0;i<dim+1;i++){ GradSolVAR[i].resize(dim); NablaSolVAR[i].resize(nabla_dim); } vector <double > phi; vector <adept::adouble> gradphi; vector <adept::adouble> nablaphi; adept::adouble Weight; phi.reserve(max_size); gradphi.reserve(max_size*dim); nablaphi.reserve(max_size*nabla_dim); vector <double > phi1; vector <adept::adouble> gradphi1; vector <adept::adouble> nablaphi1; adept::adouble Weight1; phi1.reserve(max_size); gradphi1.reserve(max_size*dim); nablaphi1.reserve(max_size*nabla_dim); vector <vector < adept::adouble> > vx(dim); vector <vector < adept::adouble> > vx_face(dim); for(int i=0;i<dim;i++){ vx[i].reserve(max_size); vx_face[i].resize(9); } vector< vector< adept::adouble > > Soli(dim+1); vector< vector< int > > dofsVAR(dim+1); for(int i=0;i<dim+1;i++){ Soli[i].reserve(max_size); dofsVAR[i].reserve(max_size); } vector< vector< double > > Rhs(dim+1); vector< vector< adept::adouble > > aRhs(dim+1); for(int i=0;i<dim+1;i++){ aRhs[i].reserve(max_size); Rhs[i].reserve(max_size); } vector < int > dofsAll; dofsAll.reserve(max_size*(dim+1)); vector < double > KKloc; KKloc.reserve(dim*max_size*(dim+1)*dim*max_size*(dim+1)); vector < double > Jac; Jac.reserve(dim*max_size*(dim+1)*dim*max_size*(dim+1)); // ------------------------------------------------------------------------ // Physical parameters double rhof = ml_prob.parameters.get<Fluid>("Fluid").get_density(); double IRe = ml_prob.parameters.get<Fluid>("Fluid").get_IReynolds_number(); double betans = 1.; // gravity double _gravity[3]={0.,0.,0.}; double DRe = 1+(counter*counter)*5; //double DRe=150; IRe =( DRe*(counter+1) < 10000 )? 1./(DRe*(counter+1)):1./10000.; cout<<"iteration="<<counter<<" Reynolds Number = "<<1./IRe<<endl; counter++; // ----------------------------------------------------------------- // space discretization parameters unsigned SolType2 = ml_sol->GetSolutionType(ml_sol->GetIndex("U")); unsigned SolType1 = ml_sol->GetSolutionType(ml_sol->GetIndex("P")); unsigned SolTypeVx = 2; // mesh and procs unsigned nel = mymsh->GetNumberOfElements(); unsigned igrid = mymsh->GetLevel(); unsigned iproc = mymsh->processor_id(); //---------------------------------------------------------------------------------- //variable-name handling const char varname[4][3] = {"U","V","W","P"}; vector <unsigned> indexVAR(dim+1); vector <unsigned> indVAR(dim+1); vector <unsigned> SolType(dim+1); for(unsigned ivar=0; ivar<dim; ivar++) { indVAR[ivar]=ml_sol->GetIndex(&varname[ivar][0]); SolType[ivar]=ml_sol->GetSolutionType(&varname[ivar][0]); indexVAR[ivar]=my_nnlin_impl_sys.GetSolPdeIndex(&varname[ivar][0]); } indVAR[dim]=ml_sol->GetIndex(&varname[3][0]); SolType[dim]=ml_sol->GetSolutionType(&varname[3][0]); indexVAR[dim]=my_nnlin_impl_sys.GetSolPdeIndex(&varname[3][0]); unsigned indLmbd=ml_sol->GetIndex("lmbd"); //---------------------------------------------------------------------------------- start_time=clock(); myKK->zero(); // *** element loop *** for(int iel=mymsh->IS_Mts2Gmt_elem_offset[iproc]; iel < mymsh->IS_Mts2Gmt_elem_offset[iproc+1]; iel++) { unsigned kel = mymsh->IS_Mts2Gmt_elem[iel]; short unsigned kelt = myel->GetElementType(kel); unsigned nve2 = myel->GetElementDofNumber(kel,SolType2); unsigned nve1 = myel->GetElementDofNumber(kel,SolType1); unsigned nveVx = myel->GetElementDofNumber(kel,SolTypeVx); // ******************************************************************************************************* //cout<<SolType1<<" "<<SolType2<<" "<<SolTypeVx<<" "<<nve1<<" "<<nve2<<" "<<nveVx<<endl; //Rhs for(int i=0; i<dim; i++) { dofsVAR[i].resize(nve2); Soli[indexVAR[i]].resize(nve2); aRhs[indexVAR[i]].resize(nve2); Rhs[indexVAR[i]].resize(nve2); } dofsVAR[dim].resize(nve1); Soli[indexVAR[dim]].resize(nve1); aRhs[indexVAR[dim]].resize(nve1); Rhs[indexVAR[dim]].resize(nve1); dofsAll.resize(0); KKloc.resize((dim*nve2+nve1)*(dim*nve2+nve1)); Jac.resize((dim*nve2+nve1)*(dim*nve2+nve1)); // ---------------------------------------------------------------------------------------- // coordinates for(int i=0;i<dim;i++){ vx[i].resize(nveVx); } for (unsigned i=0;i<nveVx;i++) { unsigned inode=myel->GetMeshDof(kel,i,SolTypeVx); unsigned inode_Metis=mymsh->GetMetisDof(inode,SolTypeVx); for(int j=0; j<dim; j++) { //coordinates vx[j][i]= (*mymsh->_coordinate->_Sol[j])(inode_Metis); } } // Velocity for (unsigned i=0;i<nve2;i++) { unsigned inode=myel->GetMeshDof(kel,i,SolType2); unsigned inode_Metis=mymsh->GetMetisDof(inode,SolType2); for(int j=0; j<dim; j++) { // velocity dofs Soli[indexVAR[j]][i] = (*mysolution->_Sol[indVAR[j]])(inode_Metis); dofsVAR[j][i] = myLinEqSolver->GetKKDof(indVAR[j],indexVAR[j],inode); aRhs[indexVAR[j]][i] = 0.; } } // Pressure dofs for (unsigned i=0;i<nve1;i++) { unsigned inode=myel->GetMeshDof(kel,i,SolType1); unsigned inode_Metis =mymsh->GetMetisDof(inode,SolType1); Soli[indexVAR[dim]][i] = (*mysolution->_Sol[indVAR[dim]])(inode_Metis); dofsVAR[dim][i]=myLinEqSolver->GetKKDof(indVAR[dim],indexVAR[dim],inode); aRhs[indexVAR[dim]][i] = 0.; } // build dof composition for(int idim=0;idim<dim;idim++){ dofsAll.insert( dofsAll.end(), dofsVAR[idim].begin(), dofsVAR[idim].end() ); } dofsAll.insert( dofsAll.end(), dofsVAR[dim].begin(), dofsVAR[dim].end() ); if (igrid==gridn || !myel->GetRefinedElementIndex(kel) ) { adeptStack.new_recording(); // *** Gauss point loop *** adept::adouble hk; for (unsigned ig=0;ig < mymsh->_finiteElement[kelt][SolType2]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives in the moving frame*** mymsh->_finiteElement[kelt][SolType2]->Jacobian(vx,ig,Weight,phi,gradphi,nablaphi); mymsh->_finiteElement[kelt][SolType1]->Jacobian(vx,ig,Weight1,phi1,gradphi1,nablaphi1); for(int i=0;i<nve1;i++){ for(int j=0;j<nabla_dim;j++){ //cout<<nablaphi[i*nabla_dim+j]<<" "; } //cout<<endl; } //cout<<endl; if(ig==0){ double referenceElementArea[6]={8, 1./6., 1., 4., 1., 2.}; double GaussWeight = mymsh->_finiteElement[kelt][SolType2]->GetGaussWeight(ig); double area=referenceElementArea[kelt]*Weight.value()/GaussWeight; hk = pow(area,1./dim); //cout<<hk<<" "; } // velocity: solution, gradient and laplace for(int i=0; i<dim; i++){ SolVAR[i]=0.; for(int j=0; j<dim; j++) { GradSolVAR[i][j]=0.; } for(int j=0; j<nabla_dim; j++) { NablaSolVAR[i][j]=0.; } for (unsigned inode=0; inode<nve2; inode++) { adept::adouble soli = Soli[indexVAR[i]][inode]; SolVAR[i]+=phi[inode]*soli; for(int j=0; j<dim; j++) { GradSolVAR[i][j]+=gradphi[inode*dim+j]*soli; } for(int j=0; j<nabla_dim; j++) { NablaSolVAR[i][j]+=nablaphi[inode*nabla_dim+j]*soli; } } } // pressure, solution and gradient SolVAR[dim]=0.; for(int j=0; j<dim; j++) { GradSolVAR[dim][j]=0.; } for (unsigned inode=0; inode<nve1; inode++) { adept::adouble soli = Soli[indexVAR[dim]][inode]; SolVAR[dim]+=phi1[inode]*soli; for(int j=0; j<dim; j++) { GradSolVAR[dim][j]+=gradphi1[inode*dim+j]*soli; } } bool Tezduyare=0; bool FrancaAndFrey=!Tezduyare; if( Tezduyare ){ //BEGIN TAU_SUPG, TAU_PSPG EVALUATION // ******** T.E. Tezduyar, S. Mittal, S.E. Ray and R. Shih ***************************** // Computer Methods in Applied Mechanics and Engineering 95 (1992) 221-242 North-Holland // ************************************************************************************* // velocity vector < adept::adouble > u(dim); for(int ivar=0; ivar<dim; ivar++){ u[ivar]=SolVAR[ivar]; } // speed adept::adouble uL2Norm=0.; for(int ivar=0;ivar<dim;ivar++){ uL2Norm += u[ivar]*u[ivar]; } uL2Norm=sqrt(uL2Norm); adept::adouble tauSupg=0.; adept::adouble tauPspg=0.; if( uL2Norm/(2.*IRe) > 1.0e-10){ // velocity direction s = u/|u| vector < adept::adouble > s(dim); for(int ivar=0;ivar<dim;ivar++) s[ivar]=u[ivar]/uL2Norm; // element lenght h(s) = 2. ( \sum_i |s . gradphi_i | )^(-1) adept::adouble h=0.; for (unsigned i=0; i<nve2; i++) { adept::adouble sDotGradphi=0.; for(int ivar=0; ivar<dim; ivar++) sDotGradphi += s[ivar]*gradphi[i*dim+ivar]; //Start WARNING!!! do not change the following if into h += fabs(sDotGradphi). //Adept does not like it, and convergence is bad if( sDotGradphi.value() < 0.) h -= sDotGradphi; else h += sDotGradphi; //End WARNING } h = 2./h; //tauSupg adept::adouble Reu = 1./3.*(uL2Norm*h)/(2.*IRe); adept::adouble zReu = (Reu.value() < 1.)? Reu : 1.; tauSupg = h / (2.*uL2Norm)*zReu; uL2Norm=0.01; h = 2.*hk/sqrt(acos(-1.)); Reu = 1./3.*(uL2Norm*h)/(2.*IRe); zReu = (Reu.value() < 1.)? Reu : 1.; tauPspg = h / (2.*uL2Norm)*zReu; } //END TAU_SUPG, TAU_PSPG EVALUATION //BEGIN FLUID ASSEMBLY { vector < adept::adouble > Res(dim,0.); for(unsigned ivar=0; ivar<dim; ivar++) { Res[ivar] += 0. - GradSolVAR[dim][ivar]; for(unsigned jvar=0; jvar<dim; jvar++) { unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = dim; // xy else if (2 == ivar + jvar ) kvar = dim+2; // xz else if (3 == ivar + jvar ) kvar = dim+1; // yz Res[ivar] += - SolVAR[jvar]*GradSolVAR[ivar][jvar] + IRe * ( NablaSolVAR[ivar][jvar] + NablaSolVAR[jvar][kvar] ); } } adept::adouble div_vel=0.; for(int ivar=0; ivar<dim; ivar++) { div_vel +=GradSolVAR[ivar][ivar]; } //BEGIN redidual momentum block for (unsigned i=0; i<nve2; i++){ for(unsigned ivar=0; ivar<dim; ivar++) { adept::adouble Advection = 0.; adept::adouble Laplacian = 0.; adept::adouble phiSupg=0.; for(unsigned jvar=0; jvar<dim; jvar++) { unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = dim; // xy else if (2 == ivar + jvar ) kvar = dim+2; // xz else if (3 == ivar + jvar ) kvar = dim+1; // yz Advection += SolVAR[jvar]*GradSolVAR[ivar][jvar]*phi[i]; Laplacian += IRe*gradphi[i*dim+jvar]*(GradSolVAR[ivar][jvar]+GradSolVAR[jvar][ivar]); phiSupg += ( SolVAR[jvar]*gradphi[i*dim+jvar] ) * tauSupg; } aRhs[indexVAR[ivar]][i]+= ( - Advection - Laplacian + SolVAR[dim] * gradphi[i*dim+ivar] + Res[ivar] * phiSupg ) * Weight; } } //END redidual momentum block //BEGIN continuity block for (unsigned i=0; i<nve1; i++) { adept::adouble MinusGradPhi1DotRes = 0.; for(int ivar=0;ivar<dim;ivar++){ MinusGradPhi1DotRes += -gradphi1[i*dim+ivar] * Res[ivar] * tauPspg; } aRhs[indexVAR[dim]][i] += ( - (-div_vel) * phi1[i] + MinusGradPhi1DotRes ) * Weight; } //END continuity block } //END FLUID ASSEMBLY } else if(FrancaAndFrey){ //BEGIN TAU_SUPG EVALUATION // ********************************* Tau_Supg FRANCA and FREY ************************** // Computer Methods in Applied Mechanics and Engineering 99 (1992) 209-233 North-Holland // ************************************************************************************* // velocity // double Ck[6][3]={{1.,1.,1.},{1.,1.,1.},{1.,1.,1.},{0.5, 11./270., 11./270.},{0.,1./42.,1./42.},{1.,1.,1.}}; vector < adept::adouble > a(dim); for(int ivar=0; ivar<dim; ivar++){ a[ivar]=SolVAR[ivar]; } // speed adept::adouble aL2Norm=0.; for(int ivar=0;ivar<dim;ivar++){ aL2Norm += a[ivar]*a[ivar]; } aL2Norm=sqrt(aL2Norm); adept::adouble deltaSupg=0.; double sqrtlambdak = (*mysolution->_Sol[indLmbd])(iel); adept::adouble tauSupg=1. / ( sqrtlambdak*sqrtlambdak *4.*IRe); adept::adouble Rek = aL2Norm / ( 4.*sqrtlambdak*IRe); /*adept::adouble mk=std::min(1./3., 2.*Ck[kelt][SolType2]); adept::adouble Rek = mk * aL2Norm * hk / ( 4.*IRe); adept::adouble tauSupg = (mk*hk*hk/2.) / ( 4.*IRe); */ if( Rek > 1.0e-15){ adept::adouble xiRek = ( Rek >= 1. ) ? 1.:Rek; tauSupg = xiRek/(aL2Norm*sqrtlambdak); deltaSupg = (xiRek*aL2Norm)/sqrtlambdak; // tauSupg = hk / (2.*aL2Norm)*xiRek; // double lambda=1.; // deltaSupg = lambda*aL2Norm*hk*xiRek; } //END TAU_SUPG EVALUATION ============ //BEGIN FLUID ASSEMBLY ============ { vector < adept::adouble > Res(dim,0.); for(unsigned ivar=0; ivar<dim; ivar++) { Res[ivar] += 0. - GradSolVAR[dim][ivar]; for(unsigned jvar=0; jvar<dim; jvar++) { unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = dim; // xy else if (2 == ivar + jvar ) kvar = dim+2; // xz else if (3 == ivar + jvar ) kvar = dim+1; // yz Res[ivar] += - SolVAR[jvar]*GradSolVAR[ivar][jvar] + IRe * ( NablaSolVAR[ivar][jvar] + NablaSolVAR[jvar][kvar] ); } } adept::adouble div_vel=0.; for(int ivar=0; ivar<dim; ivar++) { div_vel +=GradSolVAR[ivar][ivar]; } //BEGIN redidual momentum block for (unsigned i=0; i<nve2; i++){ for(unsigned ivar=0; ivar<dim; ivar++) { adept::adouble Advection = 0.; adept::adouble Laplacian = 0.; adept::adouble phiSupg=0.; for(unsigned jvar=0; jvar<dim; jvar++) { unsigned kvar; if(ivar == jvar) kvar = jvar; else if (1 == ivar + jvar ) kvar = dim; // xy else if (2 == ivar + jvar ) kvar = dim+2; // xz else if (3 == ivar + jvar ) kvar = dim+1; // yz Advection += SolVAR[jvar]*GradSolVAR[ivar][jvar]*phi[i]; Laplacian += IRe*gradphi[i*dim+jvar]*(GradSolVAR[ivar][jvar]+GradSolVAR[jvar][ivar]); phiSupg += ( SolVAR[jvar]*gradphi[i*dim+jvar] ) * tauSupg; aRhs[indexVAR[ivar]][i] += Res[ivar] * (-IRe * nablaphi[i*nabla_dim+jvar])* tauSupg * Weight; aRhs[indexVAR[jvar]][i] += Res[ivar] * (-IRe * nablaphi[i*nabla_dim+kvar])* tauSupg * Weight; } aRhs[indexVAR[ivar]][i]+= ( - Advection - Laplacian + ( SolVAR[dim] - deltaSupg * div_vel) * gradphi[i*dim+ivar] + Res[ivar] * phiSupg ) * Weight; } } //END redidual momentum block //BEGIN continuity block for (unsigned i=0; i<nve1; i++) { adept::adouble MinusGradPhi1DotRes = 0.; for(int ivar=0;ivar<dim;ivar++){ MinusGradPhi1DotRes += -gradphi1[i*dim+ivar] * Res[ivar] * tauSupg; } aRhs[indexVAR[dim]][i] += ( - (-div_vel) * phi1[i] + MinusGradPhi1DotRes ) * Weight; } //END continuity block =========================== } //END FLUID ASSEMBLY ============ } } } //BEGIN local to global assembly //copy adouble aRhs into double Rhs for (unsigned i=0;i<dim;i++) { for(int j=0; j<nve2; j++) { Rhs[indexVAR[i]][j] = aRhs[indexVAR[i]][j].value(); } } for (unsigned j=0;j<nve1;j++) { Rhs[indexVAR[dim]][j] = aRhs[indexVAR[dim]][j].value(); } for(int i=0; i<dim+1; i++) { myRES->add_vector_blocked(Rhs[indexVAR[i]],dofsVAR[i]); } //Store equations for(int i=0; i<dim; i++) { adeptStack.dependent(&aRhs[indexVAR[i]][0], nve2); adeptStack.independent(&Soli[indexVAR[i]][0], nve2); } adeptStack.dependent(&aRhs[indexVAR[dim]][0], nve1); adeptStack.independent(&Soli[indexVAR[dim]][0], nve1); adeptStack.jacobian(&Jac[0]); unsigned nveAll=(dim*nve2+nve1); for (int inode=0;inode<nveAll;inode++){ for (int jnode=0;jnode<nveAll;jnode++){ KKloc[inode*nveAll+jnode]=-Jac[jnode*nveAll+inode]; } } myKK->add_matrix_blocked(KKloc,dofsAll,dofsAll); adeptStack.clear_independents(); adeptStack.clear_dependents(); //END local to global assembly } //end list of elements loop myKK->close(); myRES->close(); // ************************************* end_time=clock(); AssemblyTime+=(end_time-start_time); // ***************** END ASSEMBLY RESIDUAL + MATRIX ******************* }
void AssembleBoussinesqAppoximation_AD(MultiLevelProblem& ml_prob) { // ml_prob is the global object from/to where get/set all the data // level is the level of the PDE system to be assembled // levelMax is the Maximum level of the MultiLevelProblem // assembleMatrix is a flag that tells if only the residual or also the matrix should be assembled // call the adept stack object adept::Stack& s = FemusInit::_adeptStack; // extract pointers to the several objects that we are going to use NonLinearImplicitSystem* mlPdeSys = &ml_prob.get_system<NonLinearImplicitSystem> ("NS"); // pointer to the linear implicit system named "Poisson" const unsigned level = mlPdeSys->GetLevelToAssemble(); const unsigned levelMax = mlPdeSys->GetLevelMax(); const bool assembleMatrix = mlPdeSys->GetAssembleMatrix(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned dim2 = (3 * (dim - 1) + !(dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) // reserve memory for the local standar vectors const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 //solution variable vector < unsigned > solVIndex(dim); solVIndex[0] = mlSol->GetIndex("U"); // get the position of "U" in the ml_sol object solVIndex[1] = mlSol->GetIndex("V"); // get the position of "V" in the ml_sol object if (dim == 3) solVIndex[2] = mlSol->GetIndex("W"); // get the position of "V" in the ml_sol object unsigned solVType = mlSol->GetSolutionType(solVIndex[0]); // get the finite element type for "u" unsigned solPIndex; solPIndex = mlSol->GetIndex("P"); // get the position of "P" in the ml_sol object unsigned solPType = mlSol->GetSolutionType(solPIndex); // get the finite element type for "u" vector < unsigned > solVPdeIndex(dim); solVPdeIndex[0] = mlPdeSys->GetSolPdeIndex("U"); // get the position of "U" in the pdeSys object solVPdeIndex[1] = mlPdeSys->GetSolPdeIndex("V"); // get the position of "V" in the pdeSys object if (dim == 3) solVPdeIndex[2] = mlPdeSys->GetSolPdeIndex("W"); unsigned solPPdeIndex; solPPdeIndex = mlPdeSys->GetSolPdeIndex("P"); // get the position of "P" in the pdeSys object vector < vector < adept::adouble > > solV(dim); // local solution vector < adept::adouble > solP; // local solution vector< vector < adept::adouble > > aResV(dim); // local redidual vector vector< adept::adouble > aResP; // local redidual vector vector < vector < double > > coordX(dim); // local coordinates unsigned coordXType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) for (unsigned k = 0; k < dim; k++) { solV[k].reserve(maxSize); aResV[k].reserve(maxSize); coordX[k].reserve(maxSize); } solP.reserve(maxSize); aResP.reserve(maxSize); vector <double> phiV; // local test function vector <double> phiV_x; // local test function first order partial derivatives vector <double> phiV_xx; // local test function second order partial derivatives phiV.reserve(maxSize); phiV_x.reserve(maxSize * dim); phiV_xx.reserve(maxSize * dim2); double* phiP; double weight; // gauss point weight vector< int > KKDof; // local to global pdeSys dofs KKDof.reserve((dim + 1) *maxSize); vector< double > Res; // local redidual vector Res.reserve((dim + 1) *maxSize); vector < double > Jac; Jac.reserve((dim + 1) *maxSize * (dim + 1) *maxSize); if (assembleMatrix) KK->zero(); // Set to zero all the entries of the Global Matrix // element loop: each process loops only on the elements that owns for (int iel = msh->IS_Mts2Gmt_elem_offset[iproc]; iel < msh->IS_Mts2Gmt_elem_offset[iproc + 1]; iel++) { unsigned kel = msh->IS_Mts2Gmt_elem[iel]; // mapping between paralell dof and mesh dof short unsigned kelGeom = el->GetElementType(kel); // element geometry type unsigned nDofsV = el->GetElementDofNumber(kel, solVType); // number of solution element dofs unsigned nDofsP = el->GetElementDofNumber(kel, solPType); // number of solution element dofs unsigned nDofsX = el->GetElementDofNumber(kel, coordXType); // number of coordinate element dofs unsigned nDofsVP = dim * nDofsV + nDofsP; // resize local arrays KKDof.resize(nDofsVP); for (unsigned k = 0; k < dim; k++) { solV[k].resize(nDofsV); coordX[k].resize(nDofsX); } solP.resize(nDofsP); for (unsigned k = 0; k < dim; k++) { aResV[k].resize(nDofsV); //resize std::fill(aResV[k].begin(), aResV[k].end(), 0); //set aRes to zero } aResP.resize(nDofsP); //resize std::fill(aResP.begin(), aResP.end(), 0); //set aRes to zero // local storage of global mapping and solution for (unsigned i = 0; i < nDofsV; i++) { unsigned iNode = el->GetMeshDof(kel, i, solVType); // local to global solution node unsigned solVDof = msh->GetMetisDof(iNode, solVType); // global to global mapping between solution node and solution dof for (unsigned k = 0; k < dim; k++) { solV[k][i] = (*sol->_Sol[solVIndex[k]])(solVDof); // global extraction and local storage for the solution KKDof[i + k * nDofsV] = pdeSys->GetKKDof(solVIndex[k], solVPdeIndex[k], iNode); // global to global mapping between solution node and pdeSys dof } } for (unsigned i = 0; i < nDofsP; i++) { unsigned iNode = el->GetMeshDof(kel, i, solPType); // local to global solution node unsigned solPDof = msh->GetMetisDof(iNode, solPType); // global to global mapping between solution node and solution dof solP[i] = (*sol->_Sol[solPIndex])(solPDof); // global extraction and local storage for the solution KKDof[i + dim * nDofsV] = pdeSys->GetKKDof(solPIndex, solPPdeIndex, iNode); // global to global mapping between solution node and pdeSys dof } // local storage of coordinates for (unsigned i = 0; i < nDofsX; i++) { unsigned iNode = el->GetMeshDof(kel, i, coordXType); // local to global coordinates node unsigned coordXDof = msh->GetMetisDof(iNode, coordXType); // global to global mapping between coordinates node and coordinate dof for (unsigned k = 0; k < dim; k++) { coordX[k][i] = (*msh->_coordinate->_Sol[k])(coordXDof); // global extraction and local storage for the element coordinates } } if (level == levelMax || !el->GetRefinedElementIndex(kel)) { // do not care about this if now (it is used for the AMR) // start a new recording of all the operations involving adept::adouble variables s.new_recording(); // *** Gauss point loop *** for (unsigned ig = 0; ig < msh->_finiteElement[kelGeom][solVType]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** msh->_finiteElement[kelGeom][solVType]->Jacobian(coordX, ig, weight, phiV, phiV_x, phiV_xx); phiP = msh->_finiteElement[kelGeom][solPType]->GetPhi(ig); vector < adept::adouble > solV_gss(dim, 0); vector < vector < adept::adouble > > gradSolV_gss(dim); for (unsigned k = 0; k < dim; k++) { gradSolV_gss[k].resize(dim); std::fill(gradSolV_gss[k].begin(), gradSolV_gss[k].end(), 0); } for (unsigned i = 0; i < nDofsV; i++) { for (unsigned k = 0; k < dim; k++) { solV_gss[k] += phiV[i] * solV[k][i]; } for (unsigned j = 0; j < dim; j++) { for (unsigned k = 0; k < dim; k++) { gradSolV_gss[k][j] += phiV_x[i * dim + j] * solV[k][i]; } } } adept::adouble solP_gss = 0; for (unsigned i = 0; i < nDofsP; i++) { solP_gss += phiP[i] * solP[i]; } double nu = 1.; // *** phiV_i loop *** for (unsigned i = 0; i < nDofsV; i++) { vector < adept::adouble > NSV(dim, 0.); for (unsigned j = 0; j < dim; j++) { for (unsigned k = 0; k < dim; k++) { NSV[k] += nu * phiV_x[i * dim + j] * (gradSolV_gss[k][j] + gradSolV_gss[j][k]); NSV[k] += phiV[i] * (solV_gss[j] * gradSolV_gss[k][j]); } } for (unsigned k = 0; k < dim; k++) { NSV[k] += -solP_gss * phiV_x[i * dim + k]; } for (unsigned k = 0; k < dim; k++) { aResV[k][i] += - NSV[k] * weight; } } // end phiV_i loop // *** phiP_i loop *** for (unsigned i = 0; i < nDofsP; i++) { for (int k = 0; k < dim; k++) { aResP[i] += - (gradSolV_gss[k][k]) * phiP[i] * weight; } } // end phiP_i loop } // end gauss point loop } // endif single element not refined or fine grid loop //-------------------------------------------------------------------------------------------------------- // Add the local Matrix/Vector into the global Matrix/Vector //copy the value of the adept::adoube aRes in double Res and store them in RES Res.resize(nDofsVP); //resize for (int i = 0; i < nDofsV; i++) { for (unsigned k = 0; k < dim; k++) { Res[ i + k * nDofsV ] = -aResV[k][i].value(); } } for (int i = 0; i < nDofsP; i++) { Res[ i + dim * nDofsV ] = -aResP[i].value(); } RES->add_vector_blocked(Res, KKDof); //Extarct and store the Jacobian if (assembleMatrix) { Jac.resize(nDofsVP * nDofsVP); // define the dependent variables for (unsigned k = 0; k < dim; k++) { s.dependent(&aResV[k][0], nDofsV); } s.dependent(&aResP[0], nDofsP); // define the independent variables for (unsigned k = 0; k < dim; k++) { s.independent(&solV[k][0], nDofsV); } s.independent(&solP[0], nDofsP); // get the and store jacobian matrix (row-major) s.jacobian(&Jac[0] , true); KK->add_matrix_blocked(Jac, KKDof, KKDof); s.clear_independents(); s.clear_dependents(); } } //end element loop for each process RES->close(); if (assembleMatrix) KK->close(); // ***************** END ASSEMBLY ******************* }
void AssemblePoisson_AD (MultiLevelProblem& ml_prob) { // ml_prob is the global object from/to where get/set all the data // level is the level of the PDE system to be assembled // levelMax is the Maximum level of the MultiLevelProblem // assembleMatrix is a flag that tells if only the residual or also the matrix should be assembled // call the adept stack object adept::Stack& s = FemusInit::_adeptStack; // extract pointers to the several objects that we are going to use NonLinearImplicitSystem* mlPdeSys = &ml_prob.get_system<NonLinearImplicitSystem> ("Poisson"); // pointer to the linear implicit system named "Poisson" const unsigned level = mlPdeSys->GetLevelToAssemble(); Mesh* msh = ml_prob._ml_msh->GetLevel (level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel (level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned dim2 = (3 * (dim - 1) + ! (dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) // reserve memory for the local standar vectors const unsigned maxSize = static_cast< unsigned > (ceil (pow (3, dim))); // conservative: based on line3, quad9, hex27 //solution variable unsigned solUIndex; solUIndex = mlSol->GetIndex ("U"); // get the position of "U" in the ml_sol object = 0 unsigned solUType = mlSol->GetSolutionType (solUIndex); // get the finite element type for "T" unsigned solUPdeIndex; solUPdeIndex = mlPdeSys->GetSolPdeIndex ("U"); // get the position of "U" in the pdeSys object = 0 vector < adept::adouble > solU; // local solution vector< adept::adouble > aResU; // local redidual vector unsigned solVIndex; solVIndex = mlSol->GetIndex ("V"); unsigned solVType = mlSol->GetSolutionType (solVIndex); unsigned solVPdeIndex; solVPdeIndex = mlPdeSys->GetSolPdeIndex ("V"); vector < adept::adouble > solV; // local solution vector< adept::adouble > aResV; // local redidual vector vector < vector < double > > crdX (dim); // local coordinates unsigned crdXType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) solU.reserve (maxSize); aResU.reserve (maxSize); solV.reserve (maxSize); aResV.reserve (maxSize); for (unsigned k = 0; k < dim; k++) { crdX[k].reserve (maxSize); } vector <double> phi; // local test function vector <double> phi_x; // local test function first order partial derivatives vector <double> phi_xx; // local test function second order partial derivatives phi.reserve (maxSize); phi_x.reserve (maxSize * dim); phi_xx.reserve (maxSize * dim2); vector <double> phiV; // local test function vector <double> phiV_x; // local test function first order partial derivatives vector <double> phiV_xx; // local test function second order partial derivatives phiV.reserve (maxSize); phiV_x.reserve (maxSize * dim); phiV_xx.reserve (maxSize * dim2); double weight; // gauss point weight vector< int > sysDof; // local to global pdeSys dofs sysDof.reserve (2 * maxSize); vector< double > Res; // local residual vector Res.reserve (2 * maxSize); vector < double > Jac; Jac.reserve (4 * maxSize * maxSize); KK->zero(); // Set to zero all the entries of the Global Matrix // element loop: each process loops only on the elements that owns for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { short unsigned ielGeom = msh->GetElementType (iel); // element geometry type unsigned nDofsU = msh->GetElementDofNumber (iel, solUType); // number of solution element dofs unsigned nDofsV = msh->GetElementDofNumber (iel, solVType); unsigned nDofsX = msh->GetElementDofNumber (iel, crdXType); // number of solution element dofs // resize local arrays sysDof.resize (nDofsU + nDofsV); solU.resize (nDofsU); solV.resize (nDofsV); for (unsigned k = 0; k < dim; k++) { crdX[k].resize (nDofsX); } aResU.assign (nDofsU, 0); aResV.assign (nDofsV, 0); // local storage of global mapping and solution for (unsigned i = 0; i < nDofsU; i++) { unsigned solUDof = msh->GetSolutionDof (i, iel, solUType); // local to global mapping of the solution U solU[i] = (*sol->_Sol[solUIndex]) (solUDof); // value of the solution U in the dofs sysDof[i] = pdeSys->GetSystemDof (solUIndex, solUPdeIndex, i, iel); // local to global mapping between solution U and system } for (unsigned i = 0; i < nDofsV; i++) { unsigned solVDof = msh->GetSolutionDof (i, iel, solVType); solV[i] = (*sol->_Sol[solVIndex]) (solVDof); sysDof[i + nDofsU] = pdeSys->GetSystemDof (solVIndex, solVPdeIndex, i, iel); } // local storage of coordinates for (unsigned i = 0; i < nDofsX; i++) { unsigned coordXDof = msh->GetSolutionDof (i, iel, crdXType); // local to global mapping of the coordinate X[dim] for (unsigned k = 0; k < dim; k++) { crdX[k][i] = (*msh->_topology->_Sol[k]) (coordXDof); // value of the solution X[dim] } } s.new_recording(); // *** Gauss point loop *** // for (unsigned ig = 0; ig < msh->_finiteElement[ielGeom][solUType]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** msh->_finiteElement[ielGeom][solUType]->Jacobian (crdX, ig, weight, phi, phi_x, phi_xx); msh->_finiteElement[ielGeom][solVType]->Jacobian (crdX, ig, weight, phiV, phiV_x, phiV_xx); adept::adouble solUig = 0; // solution U in the gauss point vector < adept::adouble > gradSolUig (dim, 0.); // gradient of solution U in the gauss point for (unsigned i = 0; i < nDofsU; i++) { solUig += phi[i] * solU[i]; for (unsigned j = 0; j < dim; j++) { gradSolUig[j] += phi_x[i * dim + j] * solU[i]; } } adept::adouble solVig = 0; // solution V in the gauss point vector < adept::adouble > gradSolVig (dim, 0.); // gradient of solution U in the gauss point for (unsigned i = 0; i < nDofsV; i++) { solVig += phiV[i] * solV[i]; for (unsigned j = 0; j < dim; j++) { gradSolVig[j] += phiV_x[i * dim + j] * solV[i]; } } double nu = 1.; // *** phiU_i loop *** for (unsigned i = 0; i < nDofsU; i++) { adept::adouble LaplaceU = 0.; for (unsigned j = 0; j < dim; j++) { LaplaceU -= nu * phi_x[i * dim + j] * gradSolUig[j]; } aResU[i] += (phi[i] - LaplaceU) * weight; } // end phiU_i loop for (unsigned i = 0; i < nDofsV; i++) { adept::adouble LaplaceV = 0.; for (unsigned j = 0; j < dim; j++) { LaplaceV -= nu * phiV_x[i * dim + j] * gradSolVig[j]; } aResV[i] += (phiV[i] * solUig - LaplaceV) * weight; } // end phiV_i loop } // end gauss point loop // } // endif single element not refined or fine grid loop //-------------------------------------------------------------------------------------------------------- // Add the local Matrix/Vector into the global Matrix/Vector //copy the value of the adept::adoube aRes in double Res and store them in RES Res.resize (nDofsU + nDofsV); //resize for (int i = 0; i < nDofsU; i++) { Res[i] = -aResU[i].value(); } for (int i = 0; i < nDofsV; i++) { Res[i + nDofsU] = -aResV[i].value(); } RES->add_vector_blocked (Res, sysDof); //Extarct and store the Jacobian Jac.resize ( (nDofsU + nDofsV) * (nDofsU + nDofsV)); // define the dependent variables s.dependent (&aResU[0], nDofsU); s.dependent (&aResV[0], nDofsV); // define the independent variables s.independent (&solU[0], nDofsU); s.independent (&solV[0], nDofsV); // get the and store jacobian matrix (row-major) s.jacobian (&Jac[0] , true); KK->add_matrix_blocked (Jac, sysDof, sysDof); s.clear_independents(); s.clear_dependents(); } //end element loop for each process RES->close(); KK->close(); // ***************** END ASSEMBLY ******************* }
void AssembleBilaplaceProblem_AD(MultiLevelProblem& ml_prob) { // ml_prob is the global object from/to where get/set all the data // level is the level of the PDE system to be assembled // call the adept stack object adept::Stack& s = FemusInit::_adeptStack; // extract pointers to the several objects that we are going to use NonLinearImplicitSystem* mlPdeSys = &ml_prob.get_system<NonLinearImplicitSystem> ("Poisson"); // pointer to the linear implicit system named "Poisson" const unsigned level = mlPdeSys->GetLevelToAssemble(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) //solution variable unsigned soluIndex; soluIndex = mlSol->GetIndex("u"); // get the position of "u" in the ml_sol object unsigned soluType = mlSol->GetSolutionType(soluIndex); // get the finite element type for "u" unsigned soluPdeIndex; soluPdeIndex = mlPdeSys->GetSolPdeIndex("u"); // get the position of "u" in the pdeSys object vector < adept::adouble > solu; // local solution unsigned solvIndex; solvIndex = mlSol->GetIndex("v"); // get the position of "v" in the ml_sol object unsigned solvType = mlSol->GetSolutionType(solvIndex); // get the finite element type for "v" unsigned solvPdeIndex; solvPdeIndex = mlPdeSys->GetSolPdeIndex("v"); // get the position of "v" in the pdeSys object vector < adept::adouble > solv; // local solution vector < vector < double > > x(dim); // local coordinates unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) vector< int > sysDof; // local to global pdeSys dofs vector <double> phi; // local test function vector <double> phi_x; // local test function first order partial derivatives vector <double> phi_xx; // local test function second order partial derivatives double weight; // gauss point weight vector< double > Res; // local redidual vector vector< adept::adouble > aResu; // local redidual vector vector< adept::adouble > aResv; // local redidual vector // reserve memory for the local standar vectors const unsigned maxSize = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 solu.reserve(maxSize); solv.reserve(maxSize); for (unsigned i = 0; i < dim; i++) x[i].reserve(maxSize); sysDof.reserve(2 * maxSize); phi.reserve(maxSize); phi_x.reserve(maxSize * dim); unsigned dim2 = (3 * (dim - 1) + !(dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) phi_xx.reserve(maxSize * dim2); Res.reserve(2 * maxSize); aResu.reserve(maxSize); aResv.reserve(maxSize); vector < double > Jac; // local Jacobian matrix (ordered by column, adept) Jac.reserve(4 * maxSize * maxSize); KK->zero(); // Set to zero all the entries of the Global Matrix // element loop: each process loops only on the elements that owns for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { short unsigned ielGeom = msh->GetElementType(iel); unsigned nDofs = msh->GetElementDofNumber(iel, soluType); // number of solution element dofs unsigned nDofs2 = msh->GetElementDofNumber(iel, xType); // number of coordinate element dofs // resize local arrays sysDof.resize(2 * nDofs); solu.resize(nDofs); solv.resize(nDofs); for (int i = 0; i < dim; i++) { x[i].resize(nDofs2); } aResu.assign(nDofs, 0.); //resize aResv.assign(nDofs, 0.); //resize // local storage of global mapping and solution for (unsigned i = 0; i < nDofs; i++) { unsigned solDof = msh->GetSolutionDof(i, iel, soluType); // global to global mapping between solution node and solution dof solu[i] = (*sol->_Sol[soluIndex])(solDof); // global extraction and local storage for the solution solv[i] = (*sol->_Sol[solvIndex])(solDof); // global extraction and local storage for the solution sysDof[i] = pdeSys->GetSystemDof(soluIndex, soluPdeIndex, i, iel); // global to global mapping between solution node and pdeSys dof sysDof[nDofs + i] = pdeSys->GetSystemDof(solvIndex, solvPdeIndex, i, iel); // global to global mapping between solution node and pdeSys dof } // local storage of coordinates for (unsigned i = 0; i < nDofs2; i++) { unsigned xDof = msh->GetSolutionDof(i, iel, xType); // global to global mapping between coordinates node and coordinate dof for (unsigned jdim = 0; jdim < dim; jdim++) { x[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof); // global extraction and local storage for the element coordinates } } // start a new recording of all the operations involving adept::adouble variables s.new_recording(); // *** Gauss point loop *** for (unsigned ig = 0; ig < msh->_finiteElement[ielGeom][soluType]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** msh->_finiteElement[ielGeom][soluType]->Jacobian(x, ig, weight, phi, phi_x, phi_xx); // evaluate the solution, the solution derivatives and the coordinates in the gauss point adept::adouble soluGauss = 0; vector < adept::adouble > soluGauss_x(dim, 0.); adept::adouble solvGauss = 0; vector < adept::adouble > solvGauss_x(dim, 0.); vector < double > xGauss(dim, 0.); for (unsigned i = 0; i < nDofs; i++) { soluGauss += phi[i] * solu[i]; solvGauss += phi[i] * solv[i]; for (unsigned jdim = 0; jdim < dim; jdim++) { soluGauss_x[jdim] += phi_x[i * dim + jdim] * solu[i]; solvGauss_x[jdim] += phi_x[i * dim + jdim] * solv[i]; xGauss[jdim] += x[jdim][i] * phi[i]; } } // *** phi_i loop *** for (unsigned i = 0; i < nDofs; i++) { adept::adouble Laplace_u = 0.; adept::adouble Laplace_v = 0.; for (unsigned jdim = 0; jdim < dim; jdim++) { Laplace_u += - phi_x[i * dim + jdim] * soluGauss_x[jdim]; Laplace_v += - phi_x[i * dim + jdim] * solvGauss_x[jdim]; } double exactSolValue = GetExactSolutionValue(xGauss); double pi = acos(-1.); aResv[i] += (solvGauss * phi[i] - Laplace_u) * weight; aResu[i] += (4.*pi * pi * pi * pi * exactSolValue * phi[i] - Laplace_v) * weight; } // end phi_i loop } // end gauss point loop // Add the local Matrix/Vector into the global Matrix/Vector //copy the value of the adept::adoube aRes in double Res and store Res.resize(2 * nDofs); for (int i = 0; i < nDofs; i++) { Res[i] = -aResu[i].value(); Res[nDofs + i] = -aResv[i].value(); } RES->add_vector_blocked(Res, sysDof); Jac.resize( 4 * nDofs * nDofs ); // define the dependent variables s.dependent(&aResu[0], nDofs); s.dependent(&aResv[0], nDofs); // define the independent variables s.independent(&solu[0], nDofs); s.independent(&solv[0], nDofs); // get the jacobian matrix (ordered by column) s.jacobian(&Jac[0], true); KK->add_matrix_blocked(Jac, sysDof, sysDof); s.clear_independents(); s.clear_dependents(); } //end element loop for each process RES->close(); KK->close(); // ***************** END ASSEMBLY ******************* }
//------------------------------------------------------------------------------------------------------------ void AssembleMatrixResT(MultiLevelProblem &ml_prob){ //pointers and references LinearImplicitSystem& mylin_impl_sys = ml_prob.get_system<LinearImplicitSystem>("Temperature"); const unsigned level = mylin_impl_sys.GetLevelToAssemble(); const unsigned gridn = mylin_impl_sys.GetLevelMax(); bool assemble_matrix = mylin_impl_sys.GetAssembleMatrix(); Solution* mysolution = ml_prob._ml_sol->GetSolutionLevel(level); LinearEquationSolver* mylsyspde = mylin_impl_sys._LinSolver[level]; Mesh* mymsh = ml_prob._ml_msh->GetLevel(level); elem* myel = mymsh->el; SparseMatrix* myKK = mylsyspde->_KK; NumericVector* myRES = mylsyspde->_RES; MultiLevelSolution* ml_sol = ml_prob._ml_sol; //data const unsigned dim = mymsh->GetDimension(); unsigned nel = mymsh->GetNumberOfElements(); unsigned igrid = mymsh->GetLevel(); unsigned iproc = mymsh->processor_id(); double IPe = 1./(ml_prob.parameters.get<Fluid>("Fluid").get_Peclet_number()); //solution variable unsigned SolIndex; unsigned SolPdeIndex; SolIndex=ml_sol->GetIndex("T"); SolPdeIndex=mylin_impl_sys.GetSolPdeIndex("T"); //solution order unsigned order_ind = ml_sol->GetSolutionType(SolIndex); //coordinates vector< vector < double> > coordinates(dim); //const char coordinate_name[3][2] = {"X","Y","Z"}; //vector < unsigned > coordinate_Index(dim); // for(unsigned ivar=0; ivar<dim; ivar++) { // coordinate_Index[ivar]=ivar;//ml_prob.GetIndex(coordinate_name[ivar]); // } // declare vector< int > metis_node; vector< int > KK_dof; vector <double> phi; vector <double> gradphi; vector <double> nablaphi; double weight; vector< double > F; vector< double > B; // reserve const unsigned max_size = static_cast< unsigned > (ceil(pow(3,dim))); metis_node.reserve(max_size); KK_dof.reserve(max_size); for(int i=0;i<dim;i++) coordinates[i].reserve(max_size); phi.reserve(max_size); gradphi.reserve(max_size*dim); nablaphi.reserve(max_size*(3*(dim-1)) ); F.reserve(max_size); B.reserve(max_size*max_size); // Set to zeto all the entries of the Global Matrix if(assemble_matrix) myKK->zero(); // *** element loop *** for (int iel=mymsh->IS_Mts2Gmt_elem_offset[iproc]; iel < mymsh->IS_Mts2Gmt_elem_offset[iproc+1]; iel++) { unsigned kel = mymsh->IS_Mts2Gmt_elem[iel]; short unsigned kelt=myel->GetElementType(kel); unsigned nve=myel->GetElementDofNumber(kel,order_ind); // resize metis_node.resize(nve); KK_dof.resize(nve); phi.resize(nve); gradphi.resize(nve*dim); nablaphi.resize( nve*(3*(dim-1)) ); for(int i=0;i<dim;i++){ coordinates[i].resize(nve); } // set to zero all the entries of the FE matrices F.resize(nve); memset(&F[0],0,nve*sizeof(double)); if(assemble_matrix){ B.resize(nve*nve); memset(&B[0],0,nve*nve*sizeof(double)); } // get local to global mappings for( unsigned i=0;i<nve;i++){ unsigned inode=myel->GetElementVertexIndex(kel,i)-1u; unsigned inode_metis=mymsh->GetMetisDof(inode,2); metis_node[i]=inode_metis; for(unsigned ivar=0; ivar<dim; ivar++) { coordinates[ivar][i]=(*mymsh->_coordinate->_Sol[ivar])(inode_metis); } KK_dof[i]=mylsyspde->GetKKDof(SolIndex,SolPdeIndex,inode); } if(igrid==gridn || !myel->GetRefinedElementIndex(kel)) { // *** Gauss poit loop *** for(unsigned ig=0;ig < ml_prob._ml_msh->_finiteElement[kelt][order_ind]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives *** ml_prob._ml_msh->_finiteElement[kelt][order_ind]->Jacobian(coordinates,ig,weight,phi,gradphi,nablaphi); //Temperature and velocity current solution double SolT=0; vector < double > gradSolT(dim,0.); for(unsigned ivar=0; ivar<dim; ivar++){ gradSolT[ivar]=0; } vector < double > SolU(dim,0.); vector < unsigned > SolIndexU(dim); SolIndexU[0]=ml_sol->GetIndex("U"); SolIndexU[1]=ml_sol->GetIndex("V"); if(dim==3) SolIndexU[2]=ml_sol->GetIndex("W"); unsigned SolType=ml_sol->GetSolutionType("T"); for(unsigned i=0; i<nve; i++) { double soli = (*mysolution->_Sol[SolIndex])(metis_node[i]); SolT+=phi[i]*soli; for(unsigned ivar2=0; ivar2<dim; ivar2++) gradSolT[ivar2] += gradphi[i*dim+ivar2]*soli; for(int j=0;j<dim;j++) { SolU[j]+=phi[i]*(*mysolution->_Sol[SolIndexU[j]])(metis_node[i]); } } // *** phi_i loop *** for(unsigned i=0; i<nve; i++){ //BEGIN RESIDUALS A block =========================== double Adv_rhs=0; double Lap_rhs=0; for(unsigned ivar=0; ivar<dim; ivar++) { Lap_rhs += gradphi[i*dim+ivar]*gradSolT[ivar]; Adv_rhs += SolU[ivar]*gradSolT[ivar]; } F[i]+= (-IPe*Lap_rhs-Adv_rhs*phi[i])*weight; //END RESIDUALS A block =========================== if(assemble_matrix){ // *** phi_j loop *** for(unsigned j=0; j<nve; j++) { double Lap=0; double Adv1=0; for(unsigned ivar=0; ivar<dim; ivar++) { // Laplacian Lap += gradphi[i*dim+ivar]*gradphi[j*dim+ivar]*weight; // advection term I Adv1 += SolU[ivar]*gradphi[j*dim+ivar]*phi[i]*weight; } B[i*nve+j] += IPe*Lap + Adv1; } // end phij loop } // end phii loop } // endif assemble_matrix } // end gauss point loop } // endif single element not refined or fine grid loop //-------------------------------------------------------------------------------------------------------- //Sum the local matrices/vectors into the global Matrix/vector myRES->add_vector_blocked(F,KK_dof); if(assemble_matrix) myKK->add_matrix_blocked(B,KK_dof,KK_dof); } //end list of elements loop for each subdomain myRES->close(); if(assemble_matrix) myKK->close(); // ***************** END ASSEMBLY ******************* }
void AssembleMatrixResNS(MultiLevelProblem &ml_prob){ //pointers NonLinearImplicitSystem& my_nnlin_impl_sys = ml_prob.get_system<NonLinearImplicitSystem>("Navier-Stokes"); const unsigned level = my_nnlin_impl_sys.GetLevelToAssemble(); const unsigned gridn = my_nnlin_impl_sys.GetLevelMax(); bool assemble_matrix = my_nnlin_impl_sys.GetAssembleMatrix(); Solution* mysolution = ml_prob._ml_sol->GetSolutionLevel(level); LinearEquationSolver* mylsyspde = my_nnlin_impl_sys._LinSolver[level]; const char* pdename = my_nnlin_impl_sys.name().c_str(); MultiLevelSolution* ml_sol=ml_prob._ml_sol; Mesh* mymsh = ml_prob._ml_msh->GetLevel(level); elem* myel = mymsh->el; SparseMatrix* myKK = mylsyspde->_KK; NumericVector* myRES = mylsyspde->_RES; //data const unsigned dim = mymsh->GetDimension(); unsigned nel= mymsh->GetNumberOfElements(); unsigned igrid= mymsh->GetLevel(); unsigned iproc = mymsh->processor_id(); double ILambda= 0; double IRe = ml_prob.parameters.get<Fluid>("Fluid").get_IReynolds_number(); bool penalty = true; //mylsyspde->GetStabilization(); const bool symm_mat = false;//mylsyspde->GetMatrixProperties(); const bool NavierStokes = true; unsigned nwtn_alg = 2; bool newton = (nwtn_alg==0) ? 0:1; // solution and coordinate variables const char Solname[4][2] = {"U","V","W","P"}; vector < unsigned > SolPdeIndex(dim+1); vector < unsigned > SolIndex(dim+1); //const char coordinate_name[3][2] = {"X","Y","Z"}; //vector < unsigned > coordinate_Index(dim); vector< vector < double> > coordinates(dim); for(unsigned ivar=0; ivar<dim; ivar++) { SolPdeIndex[ivar]=my_nnlin_impl_sys.GetSolPdeIndex(&Solname[ivar][0]); SolIndex[ivar]=ml_sol->GetIndex(&Solname[ivar][0]); //coordinate_Index[ivar]=ivar;//ml_prob.GetIndex(&coordinate_name[ivar][0]); } SolPdeIndex[dim]=my_nnlin_impl_sys.GetSolPdeIndex(&Solname[3][0]); SolIndex[dim]=ml_sol->GetIndex(&Solname[3][0]); //solution order unsigned order_ind2 = ml_sol->GetSolutionType(SolIndex[0]); unsigned order_ind1 = ml_sol->GetSolutionType(SolIndex[dim]); // declare vector < int > metis_node2; vector < int > node1; vector< vector< int > > KK_dof(dim+1); vector <double> phi2; vector <double> gradphi2; vector <double> nablaphi2; const double *phi1; double Weight2; double normal[3]; vector< vector< double > > F(dim+1); vector< vector< vector< double > > > B(dim+1); // reserve const unsigned max_size = static_cast< unsigned > (ceil(pow(3,dim))); metis_node2.reserve(max_size); node1.reserve( static_cast< unsigned > (ceil(pow(2,dim)))); for(int i=0;i<dim;i++) { coordinates[i].reserve(max_size); } phi2.reserve(max_size); gradphi2.reserve(max_size*dim); nablaphi2.reserve(max_size*(3*(dim-1)) ); for(int i=0;i<dim;i++) { KK_dof[i].reserve(max_size); } for(int i=0;i<dim+1;i++) F[i].reserve(max_size); if(assemble_matrix){ for(int i=0;i<dim+1;i++){ B[i].resize(dim+1); for(int j=0;j<dim+1;j++){ B[i][j].reserve(max_size*max_size); } } } vector < double > SolVAR(dim+1); vector < vector < double > > gradSolVAR(dim); for(int i=0;i<dim;i++) { gradSolVAR[i].resize(dim); } // Set to zeto all the entries of the matrix if(assemble_matrix) myKK->zero(); // *** element loop *** for (int iel=mymsh->IS_Mts2Gmt_elem_offset[iproc]; iel < mymsh->IS_Mts2Gmt_elem_offset[iproc+1]; iel++) { unsigned kel = mymsh->IS_Mts2Gmt_elem[iel]; short unsigned kelt=myel->GetElementType(kel); unsigned nve2=myel->GetElementDofNumber(kel,order_ind2); unsigned nve1=myel->GetElementDofNumber(kel,order_ind1); //set to zero all the entries of the FE matrices metis_node2.resize(nve2); node1.resize(nve1); phi2.resize(nve2); gradphi2.resize(nve2*dim); nablaphi2.resize(nve2*(3*(dim-1)) ); for(int ivar=0; ivar<dim; ivar++) { coordinates[ivar].resize(nve2); KK_dof[ivar].resize(nve2); F[SolPdeIndex[ivar]].resize(nve2); memset(&F[SolPdeIndex[ivar]][0],0,nve2*sizeof(double)); if(assemble_matrix){ B[SolPdeIndex[ivar]][SolPdeIndex[ivar]].resize(nve2*nve2); B[SolPdeIndex[ivar]][SolPdeIndex[dim]].resize(nve2*nve1); B[SolPdeIndex[dim]][SolPdeIndex[ivar]].resize(nve1*nve2); memset(&B[SolPdeIndex[ivar]][SolPdeIndex[ivar]][0],0,nve2*nve2*sizeof(double)); memset(&B[SolPdeIndex[ivar]][SolPdeIndex[dim]][0],0,nve2*nve1*sizeof(double)); memset(&B[SolPdeIndex[dim]][SolPdeIndex[ivar]][0],0,nve1*nve2*sizeof(double)); } } KK_dof[dim].resize(nve1); F[SolPdeIndex[dim]].resize(nve1); memset(&F[SolPdeIndex[dim]][0],0,nve1*sizeof(double)); if(assemble_matrix*nwtn_alg==2){ for(int ivar=0; ivar<dim; ivar++) { for(int ivar2=1; ivar2<dim; ivar2++) { B[SolPdeIndex[ivar]][SolPdeIndex[(ivar+ivar2)%dim]].resize(nve2*nve2); memset(&B[SolPdeIndex[ivar]][SolPdeIndex[(ivar+ivar2)%dim]][0],0,nve2*nve2*sizeof(double)); } } } if(assemble_matrix*penalty){ B[SolPdeIndex[dim]][SolPdeIndex[dim]].resize(nve1*nve1,0.); memset(&B[SolPdeIndex[dim]][SolPdeIndex[dim]][0],0,nve1*nve1*sizeof(double)); } for( unsigned i=0;i<nve2;i++){ unsigned inode=myel->GetElementVertexIndex(kel,i)-1u; unsigned inode_metis=mymsh->GetMetisDof(inode,2); metis_node2[i]=inode_metis; for(unsigned ivar=0; ivar<dim; ivar++) { coordinates[ivar][i]=(*mymsh->_coordinate->_Sol[ivar])(inode_metis); KK_dof[ivar][i]=mylsyspde->GetKKDof(SolIndex[ivar],SolPdeIndex[ivar],inode); } } for(unsigned i=0;i<nve1;i++) { unsigned inode=(order_ind1<3)?(myel->GetElementVertexIndex(kel,i)-1u):(kel+i*nel); node1[i]=inode; KK_dof[dim][i]=mylsyspde->GetKKDof(SolIndex[dim],SolPdeIndex[dim],inode); } if(igrid==gridn || !myel->GetRefinedElementIndex(kel)) { // *** Gauss poit loop *** for(unsigned ig=0;ig < ml_prob._ml_msh->_finiteElement[kelt][order_ind2]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives *** ml_prob._ml_msh->_finiteElement[kelt][order_ind2]->Jacobian(coordinates,ig,Weight2,phi2,gradphi2,nablaphi2); phi1=ml_prob._ml_msh->_finiteElement[kelt][order_ind1]->GetPhi(ig); //velocity variable for(unsigned ivar=0; ivar<dim; ivar++) { SolVAR[ivar]=0; for(unsigned ivar2=0; ivar2<dim; ivar2++){ gradSolVAR[ivar][ivar2]=0; } unsigned SolIndex=ml_sol->GetIndex(&Solname[ivar][0]); unsigned SolType=ml_sol->GetSolutionType(&Solname[ivar][0]); for(unsigned i=0; i<nve2; i++) { double soli = (*mysolution->_Sol[SolIndex])(metis_node2[i]); SolVAR[ivar]+=phi2[i]*soli; for(unsigned ivar2=0; ivar2<dim; ivar2++){ gradSolVAR[ivar][ivar2] += gradphi2[i*dim+ivar2]*soli; } } } //pressure variable SolVAR[dim]=0; unsigned SolIndex=ml_sol->GetIndex(&Solname[3][0]); unsigned SolType=ml_sol->GetSolutionType(&Solname[3][0]); for(unsigned i=0; i<nve1; i++){ unsigned sol_dof = mymsh->GetMetisDof(node1[i],SolType); double soli = (*mysolution->_Sol[SolIndex])(sol_dof); SolVAR[dim]+=phi1[i]*soli; } // *** phi_i loop *** for(unsigned i=0; i<nve2; i++){ //BEGIN RESIDUALS A block =========================== for(unsigned ivar=0; ivar<dim; ivar++) { double Adv_rhs=0; double Lap_rhs=0; for(unsigned ivar2=0; ivar2<dim; ivar2++) { Lap_rhs += gradphi2[i*dim+ivar2]*gradSolVAR[ivar][ivar2]; Adv_rhs += SolVAR[ivar2]*gradSolVAR[ivar][ivar2]; } F[SolPdeIndex[ivar]][i]+= (-IRe*Lap_rhs-NavierStokes*Adv_rhs*phi2[i]+SolVAR[dim]*gradphi2[i*dim+ivar])*Weight2; } //END RESIDUALS A block =========================== if(assemble_matrix){ // *** phi_j loop *** for(unsigned j=0; j<nve2; j++) { double Lap=0; double Adv1=0; double Adv2 = phi2[i]*phi2[j]*Weight2; for(unsigned ivar=0; ivar<dim; ivar++) { // Laplacian Lap += gradphi2[i*dim+ivar]*gradphi2[j*dim+ivar]*Weight2; // advection term I Adv1 += SolVAR[ivar]*gradphi2[j*dim+ivar]*phi2[i]*Weight2; } for(unsigned ivar=0; ivar<dim; ivar++) { B[SolPdeIndex[ivar]][SolPdeIndex[ivar]][i*nve2+j] += IRe*Lap+ NavierStokes*newton*Adv1; if(nwtn_alg==2){ // Advection term II B[SolPdeIndex[ivar]][SolPdeIndex[ivar]][i*nve2+j] += Adv2*gradSolVAR[ivar][ivar]; for(unsigned ivar2=1; ivar2<dim; ivar2++) { B[SolPdeIndex[ivar]][SolPdeIndex[(ivar+ivar2)%dim]][i*nve2+j] += Adv2*gradSolVAR[ivar][(ivar+ivar2)%dim]; } } } } //end phij loop // *** phi1_j loop *** for(unsigned j=0; j<nve1; j++){ for(unsigned ivar=0; ivar<dim; ivar++) { B[SolPdeIndex[ivar]][SolPdeIndex[dim]][i*nve1+j] -= gradphi2[i*dim+ivar]*phi1[j]*Weight2; } } //end phi1_j loop } // endif assemble_matrix } //end phii loop // *** phi1_i loop *** for(unsigned i=0; i<nve1; i++){ //BEGIN RESIDUALS B block =========================== double div = 0; for(unsigned ivar=0; ivar<dim; ivar++) { div += gradSolVAR[ivar][ivar]; } F[SolPdeIndex[dim]][i]+= (phi1[i]*div +penalty*ILambda*phi1[i]*SolVAR[dim])*Weight2; //END RESIDUALS B block =========================== if(assemble_matrix){ // *** phi_j loop *** for(unsigned j=0; j<nve2; j++) { for(unsigned ivar=0; ivar<dim; ivar++) { B[SolPdeIndex[dim]][SolPdeIndex[ivar]][i*nve2+j]-= phi1[i]*gradphi2[j*dim+ivar]*Weight2; } } //end phij loop } // endif assemble_matrix } //end phi1_i loop if(assemble_matrix * penalty){ //block nve1 nve1 // *** phi_i loop *** for(unsigned i=0; i<nve1; i++){ // *** phi_j loop *** for(unsigned j=0; j<nve1; j++){ B[SolPdeIndex[dim]][SolPdeIndex[dim]][i*nve1+j]-= ILambda*phi1[i]*phi1[j]*Weight2; } } } //end if penalty } // end gauss point loop //-------------------------------------------------------------------------------------------------------- // Boundary Integral --> to be addded //number of faces for each type of element // if (igrid==gridn || !myel->GetRefinedElementIndex(kel) ) { // // unsigned nfaces = myel->GetElementFaceNumber(kel); // // // loop on faces // for(unsigned jface=0;jface<nfaces;jface++){ // // // look for boundary faces // if(myel->GetFaceElementIndex(kel,jface)<0){ // for(unsigned ivar=0; ivar<dim; ivar++) { // ml_prob.ComputeBdIntegral(pdename, &Solname[ivar][0], kel, jface, level, ivar); // } // } // } // } //-------------------------------------------------------------------------------------------------------- } // endif single element not refined or fine grid loop //-------------------------------------------------------------------------------------------------------- //Sum the local matrices/vectors into the Global Matrix/Vector for(unsigned ivar=0; ivar<dim; ivar++) { myRES->add_vector_blocked(F[SolPdeIndex[ivar]],KK_dof[ivar]); if(assemble_matrix){ myKK->add_matrix_blocked(B[SolPdeIndex[ivar]][SolPdeIndex[ivar]],KK_dof[ivar],KK_dof[ivar]); myKK->add_matrix_blocked(B[SolPdeIndex[ivar]][SolPdeIndex[dim]],KK_dof[ivar],KK_dof[dim]); myKK->add_matrix_blocked(B[SolPdeIndex[dim]][SolPdeIndex[ivar]],KK_dof[dim],KK_dof[ivar]); if(nwtn_alg==2){ for(unsigned ivar2=1; ivar2<dim; ivar2++) { myKK->add_matrix_blocked(B[SolPdeIndex[ivar]][SolPdeIndex[(ivar+ivar2)%dim]],KK_dof[ivar],KK_dof[(ivar+ivar2)%dim]); } } } } //Penalty if(assemble_matrix*penalty) myKK->add_matrix_blocked(B[SolPdeIndex[dim]][SolPdeIndex[dim]],KK_dof[dim],KK_dof[dim]); myRES->add_vector_blocked(F[SolPdeIndex[dim]],KK_dof[dim]); //-------------------------------------------------------------------------------------------------------- } //end list of elements loop for each subdomain if(assemble_matrix) myKK->close(); myRES->close(); // ***************** END ASSEMBLY ******************* }
int lanczos (int flag, SparseMatrix const &mat, int max_nstep, double &gsEnergy, vector<MatType> &z) { /* * In each step of the Lanczos algorithm the values of a[] * and b[] are computed. * then a tridiagonal matrix T[j] is formed from the matrix * T[j-1] as * * | a[0] b[0] | * | b[0] a[1] b[1] | * T(j) = | b[1] . . | * | . . a[j-2] b[j-2] | * | . . b[j-2] a[j-1] | */ // Set flag = 1 for the ground state // Set flag = 0 for the maximum eigenvalue int i, j; long int seed; double s, enew, eold, atmp, btmp, ctmp, eps = 0.001; vector<double> a,b,c; vector<MatType> x,y; MatType tmp,tmp2; vector<double> nullVector; if (nullVector.size()>0) { std::cerr<<"nullVector has size greater than zero\n"; exit(1); } seed= rand(); for (i = 0; i < max_nstep; i++) { a.push_back(0.0); b.push_back(0.0); c.push_back(0.0); } srand48 (seed); s = 0.0; z.clear(); for (i = 0; i < mat.getSize(); i++) { tmp2 = MatType(0,0); z.push_back(tmp2); tmp2 = MatType(0,0); x.push_back(tmp2); tmp2 = MatType(drand48 () - 0.5, drand48 () - 0.5); y.push_back(tmp2); s += real (y[i] * conj (y[i])); } s = 1.0 / sqrt (s); for (i = 0; i < mat.getSize(); i++) y[i] *= s; if (max_nstep > mat.getSize()) max_nstep = mat.getSize(); eold = 100.; //cout<<"iter\t< 0 | H | 0 >\n"; for (j = 0; j < max_nstep; j++) { mat.sparse_mult (x, y); atmp = 0.0; for (i = 0; i < mat.getSize(); i++) atmp += real (y[i] * conj (x[i])); btmp = 0.0; for (i = 0; i < mat.getSize(); i++) { x[i] -= atmp * y[i]; btmp += real (x[i] * conj (x[i])); } a[j] = atmp; b[j] = (btmp = sqrt (btmp)); enew = ground (flag,j+1, a, b,nullVector); // cout<<j<<":\t"<<enew<<" "<<nullVector.size()<<endl; if (fabs ((enew - eold)/enew) < eps) break; eold = enew; for (i = 0; i < mat.getSize(); i++) { tmp = y[i]; y[i] = x[i] / btmp; x[i] = -btmp * tmp; } } if (j < max_nstep) max_nstep = j + 1; gsEnergy = ground (flag,max_nstep, a, b, c); srand48 (seed); for (i = 0; i < mat.getSize(); i++) { x[i] = MatType(0,0); y[i] = s * MatType((drand48 () - 0.5), (drand48 () - 0.5)) ; z[i] = MatType(0,0); } for (j = 0; j < max_nstep; j++) { mat.sparse_mult (x, y); atmp = a[j]; btmp = b[j]; ctmp = c[j]; for (i = 0; i < mat.getSize(); i++) { z[i] += ctmp * y[i]; x[i] -= atmp * y[i]; tmp = y[i]; y[i] = x[i] / btmp; x[i] = -btmp * tmp; } } return 0; }
IGL_INLINE bool igl::bbw( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::PlainObjectBase<DerivedEle> & Ele, const Eigen::PlainObjectBase<Derivedb> & b, const Eigen::PlainObjectBase<Derivedbc> & bc, igl::BBWData & data, Eigen::PlainObjectBase<DerivedW> & W ) { using namespace igl; using namespace std; using namespace Eigen; // number of domain vertices int n = V.rows(); // number of handles int m = bc.cols(); SparseMatrix<typename DerivedW::Scalar> L; cotmatrix(V,Ele,L); MassMatrixType mmtype = MASSMATRIX_VORONOI; if(Ele.cols() == 4) { mmtype = MASSMATRIX_BARYCENTRIC; } SparseMatrix<typename DerivedW::Scalar> M; SparseMatrix<typename DerivedW::Scalar> Mi; massmatrix(V,Ele,mmtype,M); invert_diag(M,Mi); // Biharmonic operator SparseMatrix<typename DerivedW::Scalar> Q = L.transpose() * Mi * L; W.derived().resize(n,m); if(data.partition_unity) { // Not yet implemented assert(false); }else { // No linear terms VectorXd c = VectorXd::Zero(n); // No linear constraints SparseMatrix<typename DerivedW::Scalar> A(0,n),Aeq(0,n),Aieq(0,n); VectorXd uc(0,1),Beq(0,1),Bieq(0,1),lc(0,1); // Upper and lower box constraints (Constant bounds) VectorXd ux = VectorXd::Ones(n); VectorXd lx = VectorXd::Zero(n); active_set_params eff_params = data.active_set_params; switch(data.qp_solver) { case QP_SOLVER_IGL_ACTIVE_SET: { //if(data.verbosity >= 1) //{ cout<<"BBW: max_iter: "<<eff_params.max_iter<<endl; //} if(data.verbosity >= 1) { cout<<"BBW: Computing initial weights for "<<m<<" handle"<< (m!=1?"s":"")<<"."<<endl; } min_quad_with_fixed_data<typename DerivedW::Scalar > mqwf; min_quad_with_fixed_precompute(Q,b,Aeq,true,mqwf); min_quad_with_fixed_solve(mqwf,c,bc,Beq,W); // decrement eff_params.max_iter--; bool error = false; // Loop over handles #pragma omp parallel for for(int i = 0;i<m;i++) { // Quicker exit for openmp if(error) { continue; } if(data.verbosity >= 1) { #pragma omp critical cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<< "."<<endl; } VectorXd bci = bc.col(i); VectorXd Wi; // use initial guess Wi = W.col(i); SolverStatus ret = active_set( Q,c,b,bci,Aeq,Beq,Aieq,Bieq,lx,ux,eff_params,Wi); switch(ret) { case SOLVER_STATUS_CONVERGED: break; case SOLVER_STATUS_MAX_ITER: cerr<<"active_set: max iter without convergence."<<endl; break; case SOLVER_STATUS_ERROR: default: cerr<<"active_set error."<<endl; error = true; } W.col(i) = Wi; } if(error) { return false; } break; } case QP_SOLVER_MOSEK: { #ifdef IGL_NO_MOSEK assert(false && "Use another QPSolver. Recompile without IGL_NO_MOSEK defined."); cerr<<"Use another QPSolver. Recompile without IGL_NO_MOSEK defined."<<endl; return false; #else // Loop over handles for(int i = 0;i<m;i++) { if(data.verbosity >= 1) { cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<< "."<<endl; } VectorXd bci = bc.col(i); VectorXd Wi; // impose boundary conditions via bounds slice_into(bci,b,ux); slice_into(bci,b,lx); bool r = mosek_quadprog(Q,c,0,A,lc,uc,lx,ux,data.mosek_data,Wi); if(!r) { return false; } W.col(i) = Wi; } #endif break; } default: { assert(false && "Unknown qp_solver"); return false; } } #ifndef NDEBUG const double min_rowsum = W.rowwise().sum().array().abs().minCoeff(); if(min_rowsum < 0.1) { cerr<<"bbw.cpp: Warning, minimum row sum is very low. Consider more " "active set iterations or enforcing partition of unity."<<endl; } #endif } return true; }
int SparseFromFile(SparseMatrix &mat, char *filename) { int i, j, k; double eps = 1.e-15; MatType Aij; int tmp; ifstream fin(filename); if (!fin || fin.bad()) { cerr<<"new_sparse: can't open file "<<filename<<endl; return -1; } fin>>tmp; mat.setSize(tmp); mat.initRow(mat.getSize()+1); k = 0; for (i = 0; i < mat.getSize(); i++) { mat.setRow(i,k); for (j = 0; j < mat.getSize(); j++) { fin>>Aij; if (abs (Aij) > eps) k++; } } mat.setRow(mat.getSize(),k); /* # of non-zero elements */ mat.initCol(k); mat.initValues(k); fin.close(); fin.open(filename); if (!fin || fin.bad()) { cerr<<"new_sparse: can't open file "<<filename<<endl; return -1; } fin>>tmp; mat.setSize(tmp); k = 0; for (i = 0; i < mat.getSize(); i++) for (j = 0; j < mat.getSize(); j++) { fin>>Aij; if (abs (Aij) > eps) { mat.setCol(k,j); mat.setValues(k,Aij); k++; } } fin.close(); return mat.getSize(); }