使用ViennaCL bicgstab求解器异常:结果向量全为零值
问题:ViennaCL BiCGSTAB求解器返回全零向量且无报错
在科研项目中,我使用ViennaCL的BiCGSTAB求解器结合CUDA与Eigen库模拟一维热传导。求解器所用矩阵为单位矩阵加常数倍二阶导数矩阵,先以Eigen稀疏矩阵格式构建,再复制到ViennaCL矩阵中。测试时输入全为20的初始温度分布,理论上因无热交换应返回全20的向量,但求解器却返回全零向量,程序无任何报错仍正常运行。
相关代码
typedef Eigen::SparseMatrix<double> SpMat; //create a defining code for sparse mat typedef Eigen::Triplet<double> Tri; typedef viennacl::compressed_matrix<double> SpMatVienna; typedef viennacl::vector<double> vectorVienna; mat = SpMat(1000,1000); mat.setFromTriplets(tripleList.begin(),tripleList.end()); SpMatVienna viennacl_sparsematrix = SpMatVienna(1000,1000); vectorVienna temperatureAtPoints = vectorVienna(1000); viennacl::copy(mat, viennacl_sparsematrix); temperatureAtPoints = viennacl::linalg::solve(viennacl_sparsematrix, temperatureAtPoints, viennacl::linalg::bicgstab_tag());
排查与解决方法
输入向量未初始化:代码中仅声明了大小为1000的
temperatureAtPoints向量,但未设置初始值为20。ViennaCL默认会将向量初始化为全零,实际求解的是A*x=0,而矩阵A可逆,解自然是全零。需先给向量赋值全20:// 方法1:通过Eigen向量复制 Eigen::VectorXd temp_cpu(1000); temp_cpu.setConstant(20.0); viennacl::copy(temp_cpu, temperatureAtPoints); // 方法2:直接填充ViennaCL向量 viennacl::fill(temperatureAtPoints, 20.0);验证矩阵复制正确性:确保Eigen稀疏矩阵到ViennaCL矩阵的复制没有丢失数据,可对比关键位置的元素:
double eigen_val = mat.coeff(0,0); double viennacl_val = viennacl_sparsematrix(0,0); std::cout << "Eigen(0,0): " << eigen_val << ", ViennaCL(0,0): " << viennacl_val << std::endl;显式设置求解器参数:可指定BiCGSTAB的收敛精度和最大迭代次数,同时检查求解是否收敛:
viennacl::linalg::bicgstab_tag tag(1e-8, 1000); // 精度阈值、最大迭代次数 temperatureAtPoints = viennacl::linalg::solve(viennacl_sparsematrix, temperatureAtPoints, tag); if (!tag.success()) { std::cout << "求解未收敛,迭代次数:" << tag.iters() << std::endl; }
内容的提问来源于stack exchange,提问作者user29172641
相关产品推荐
相关产品推荐

