//************************************ // Method: SolvePFC // FullName: PFCal::PFC::SolvePFC // Access: public // Returns: PF_RESULT // Qualifier: 潮流计算模板函数,构造各种方法求解线性方程组 //************************************ PFVoid PFC::Solve(){ PFDouble opml(0.0); Eigen::SparseLU<PFCore::PFSMatrixXD, PFCore::PFCOLAMDOrdering> solver; PFCIter = 0; //0. 初始化计算矩阵及向量大小 this->_InitPFCalMatrix(); do { //1. 求解功率失配量 cout << "QG DISPATCH..." << endl; _MakeDPQVector(); //2. 如果达到收敛条件,退出 cout << "MAXDISPATCH\t" << PFCIter << "\t" << dPFCPQ.cwiseAbs().maxCoeff() << endl; if (dPFCPQ.cwiseAbs().maxCoeff() < PFCEpsm){ this->PFCResult = PF_RESULT_CONVERG; return; } //3. 计算雅可比阵 _MakeJacoMatrix(); //4. 计算电压偏差 solver.compute(PFCJaco); if (solver.info() != Eigen::Success){ cout << "Solving<stage_1> Failed!" << endl; this->PFCResult = PF_RESULT_DIVERGE_FAILURE; return; } dPFCVA = solver.solve(dPFCPQ); if (solver.info() != Eigen::Success){ cout << "Solving<stage_2> Failed!" << endl; this->PFCResult = PF_RESULT_DIVERGE_FAILURE; return; } //5. 检测是否出现NAN if(dPFCVA.hasNaN()){ this->PFCResult = PF_RESULT_DIVERGE_NAN; return; } //6. 更新状态量 cout << "VOL DISPATCH..." << endl; opml = _CalOptimalMultiplier(); dPFCVA *= opml; _UpdateSysState(); //7. 迭代次数增加 ++PFCIter; } while (PFCIter <= PFCMaxIter); //迭代次数越限 if (PFCIter > PFCMaxIter){ this->PFCResult = PF_RESULT_DIVERGE_OVER_ITER; return; } this->PFCResult = PF_RESULT_DIVERGE; return; }
void ReliefGeneration::CompressHeightField(std::vector<double>& heightField, int resX, int resY) { double bbScale = 2; double alpha = bbScale * 300.0; double threthold = bbScale * 0.05; int vertNum = (resX + 1) * (resY + 1); std::vector<MagicMath::Vector3> DeltaVector(vertNum); for (int xid = 0; xid < resX; xid++) { for (int yid = 0; yid < resY; yid++) { int index = xid * (resY + 1) + yid; MagicMath::Vector3 deltaT(0, 0, 0); deltaT[0] = heightField.at(index + resY + 1) - heightField.at(index); deltaT[1] = heightField.at(index + 1) - heightField.at(index); double deltaMag = deltaT.Normalise(); if (deltaMag > threthold) { deltaMag = 0; } else { deltaMag = log(1 + alpha * deltaMag) / alpha; } DeltaVector.at(index) = deltaT * deltaMag; } } std::vector<double> LaplaceField(vertNum); for (int xid = 1; xid < resX; xid++) { for (int yid = 1; yid < resY; yid++) { int index = xid * (resY + 1) + yid; LaplaceField.at(index) = DeltaVector.at(index)[0] - DeltaVector.at(index - resY - 1)[0] + DeltaVector.at(index)[1] - DeltaVector.at(index - 1)[1]; } } DebugLog << "Relief: Construct Matrix" << std::endl; std::vector< Eigen::Triplet<double> > tripletList; Eigen::VectorXd b(vertNum, 1); for (int xid = 0; xid < resX + 1; xid++) { for (int yid = 0; yid < resY + 1; yid++) { int index = xid * (resY + 1) + yid; if (xid == 0 || xid == resX || yid == 0 || yid == resY) { tripletList.push_back( Eigen::Triplet<double>(index, index, 1) ); b(index) = 0; } else { tripletList.push_back( Eigen::Triplet<double>(index, index, -4.0) ); tripletList.push_back( Eigen::Triplet<double>(index, index + 1, 1.0) ); tripletList.push_back( Eigen::Triplet<double>(index, index - 1, 1.0) ); tripletList.push_back( Eigen::Triplet<double>(index, index + resY + 1, 1.0) ); tripletList.push_back( Eigen::Triplet<double>(index, index - resY - 1, 1.0) ); b(index) = LaplaceField.at(index); } } } DebugLog << "Relief: Solve Matrix" << std::endl; Eigen::SparseMatrix<double, Eigen::ColMajor> matA(vertNum,vertNum); matA.setFromTriplets(tripletList.begin(), tripletList.end()); Eigen::SparseLU<Eigen::SparseMatrix<double, Eigen::ColMajor> > solver; solver.compute(matA); if(solver.info()!= Eigen::Success) { DebugLog << "Relief: SuperLU Failed" << std::endl; } Eigen::VectorXd res = solver.solve(b); //Copy results for (int i = 0; i < vertNum; i++) { heightField.at(i) = res(i); } }
IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>:: minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q, const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f, const Eigen::VectorXi isConstrained, const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown, Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x) { int N = Q.rows(); int nc = xknown.rows(); Eigen::VectorXi known; known.setZero(nc,1); Eigen::VectorXi unknown; unknown.setZero(N-nc,1); int indk = 0, indu = 0; for (int i = 0; i<N; ++i) if (isConstrained[i]) { known[indk] = i; indk++; } else { unknown[indu] = i; indu++; } Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk; igl::slice(Q,unknown, unknown, Quu); igl::slice(Q,unknown, known, Quk); std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList; Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1); igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu); Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu; Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver; solver.compute(-Quu); if(solver.info()!=Eigen::Success) { std::cerr<<"Decomposition failed!"<<std::endl; return; } Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> b = solver.solve(rhs); if(solver.info()!=Eigen::Success) { std::cerr<<"Solving failed!"<<std::endl; return; } indk = 0, indu = 0; x.setZero(N,1); for (int i = 0; i<N; ++i) if (isConstrained[i]) x[i] = xknown[indk++]; else x[i] = b.coeff(indu++,0); }