Example #1
0
//=============================================================================
int main(int argc, char** argv)
{
  srand(time(NULL));
  
  const int size(100);
  CPPL::dsymatrix A(size);
  
  for(int i=0; i<size; i++){
    for(int j=0; j<=i; j++){
      A(i,j) =(double(rand())/double(RAND_MAX))*2.0 -1.0;
    }
    A(i,i)+=10.;
  }
  A.write("A.dsymatrix");
  
  CPPL::dcovector x(size);
  for(int i=0; i<size; i++){
    x(i) =(double(rand())/double(RAND_MAX))*1. -0.5;
  }
  x.write("answer.dcovector");//solution
  std::cerr << "answer=\n" << t(x) << std::endl;
  
  CPPL::dcovector y(size);
  y=A*x;
  y.write("y.dcovector");
  
  double eps(fabs(damax(y))*1e-6);
  //std::cerr << "eps=" << eps << std::endl;
  if( minres(A, y, eps) ){
    std::cerr << "failed." << std::endl;
    exit(1);
  }
  y.write("solution.dcovector");
  std::cout << "solution=\n" << t(y) << std::endl;
  
  return 0;
}
Example #2
0
void ISOP2P1::solveStokes()
{
	buildStokesSys();
	std::cout << "Stokes system builded." << std::endl;
	int n_dof_v = fem_space_v.n_dof();
	int n_dof_p = fem_space_p.n_dof();
	int n_total_dof = 2 * n_dof_v + n_dof_p;

	/// 构建系数矩阵和右端项.
	/// 这个存放整体的数值解. 没有分割成 u_h[0], u_h[1] 和 p_h.
	Vector<double> x(n_total_dof);
	/// 将数值解合并一个向量便于边界处理.
	for (int i = 0; i < n_dof_v; ++i)
	{
		x(i) = v_h[0](i);
		x(n_dof_v + i) = v_h[1](i);
	}

	for (int i = 0; i < n_dof_p; ++i)
		x(2 * n_dof_v + i) = p_h(i);

	rhs.reinit(n_total_dof);

	/// 边界条件一起处理了. 修改了matrix, rhs和x.
	boundaryValueStokes(x, t);
	std::cout << "Stokes boundary applied." << std::endl;

// 	/// 矩阵求解.
// 	dealii::SolverControl solver_control (400000, l_tol * rhs.l2_norm(), 1);
// 	/// 不完全LU分解.
// 	dealii::SparseILU<double> preconditioner;
// 	preconditioner.initialize(matrix);

// 	/// 求解Stokes方程, MinRes要比GMRES求解器要快很多,
// 	/// 当矩阵规模稍微大点的时候,GMRES会出现不收敛的情况.
// 	SolverMinRes<Vector<double> > minres (solver_control);
// 	SolverGMRES<Vector<double> >::AdditionalData para(1000, false, true);
// 	/// 不用para算不动, 但是均匀网格下可以不用para,算其它的例子也不用para,是不是跟计算区域有关系?
// 	SolverGMRES<Vector<double> > gmres(solver_control, para);

//         // /// 移动网格和时间发展中,这个预处理失效.
// 	//  StokesPreconditioner preconditioner;
// 	 // /// 预处理矩阵.
// 	 // SparseMatrix<double> matrix_vxvx(sp_vxvx);
// 	 // SparseMatrix<double> matrix_vyvy(sp_vyvy);
// 	 // /// 这里从 Stokes 取是因为加了边界条件.
// 	 // for (int i = 0; i < sp_vxvx.n_nonzero_elements(); ++i)
// 	 // 	matrix_vxvx.global_entry(i) = matrix.global_entry(index_vxvx[i]);
// 	 // for (int i = 0; i < sp_vyvy.n_nonzero_elements(); ++i)
// 	 // 	matrix_vyvy.global_entry(i) = matrix.global_entry(index_vyvy[i]);

// 	 // preconditioner.initialize(mat_v_stiff, mat_v_stiff, mat_p_mass);


// 	clock_t t_cost = clock();
//         minres.solve (matrix, x, rhs, PreconditionIdentity());
// //	gmres.solve(matrix, x, rhs, preconditioner);
// 	t_cost = clock() - t_cost;

// 	std::cout << "time cost: " << (((float)t_cost) / CLOCKS_PER_SEC) << std::endl;

// 	/// 将整体数值解分割成速度和压力.
// 	for (int i = 0; i < n_dof_v; ++i)
// 	{
// 		v_h[0](i) = x(i);
// 		v_h[1](i) = x(i + n_dof_v);
// 	}
// 	for (int i = 0; i < n_dof_p; ++i)
// 		p_h(i) =  x(i + 2 * n_dof_v);
//        /// 计算误差, t为时间参数.
// 	computeError(t);
// 	/// debug, 计算惨量的L2 norm。
// 	Vector<double> res(n_total_dof);
// 	matrix.vmult(res, x);
// 	res *= -1;
// 	res += rhs;
// 	std::cout << "res_l2norm =" << res.l2_norm() << std::endl;

	/// 矩阵求解.
	SparseMatrix<double> mat_BTx(sp_pvx);
	SparseMatrix<double> mat_BTy(sp_pvy);
	SparseMatrix<double> mat_Bx(sp_vxp);
	SparseMatrix<double> mat_By(sp_vyp);
	SparseMatrix<double> mat_Ax(sp_vxvx);
	SparseMatrix<double> mat_Ay(sp_vyvy);

	for (int i = 0; i < sp_vxvx.n_nonzero_elements(); ++i)
		mat_Ax.global_entry(i) = matrix.global_entry(index_vxvx[i]);
	for (int i = 0; i < sp_vyvy.n_nonzero_elements(); ++i)
		mat_Ay.global_entry(i) = matrix.global_entry(index_vyvy[i]);
	for (int i = 0; i < sp_pvx.n_nonzero_elements(); ++i)
		mat_BTx.global_entry(i) = matrix.global_entry(index_pvx[i]);
	for (int i = 0; i < sp_pvy.n_nonzero_elements(); ++i)
		mat_BTy.global_entry(i) = matrix.global_entry(index_pvy[i]);
	for (int i = 0; i < sp_vxp.n_nonzero_elements(); ++i)
		mat_Bx.global_entry(i) = matrix.global_entry(index_vxp[i]);
	for (int i = 0; i < sp_vyp.n_nonzero_elements(); ++i)
		mat_By.global_entry(i) = matrix.global_entry(index_vyp[i]);

	/// alp对AMGSolver的初始化影响比较大, 如果取得很小,初始化很快.
        double alp = dt * viscosity;
	AMGSolver solverQ(mat_Ax, 1.0e-12, 3, 100, 0.382, alp);
//	AMGSolver solverQ(mat_Ax);
	InverseMatrix AInv(mat_Ax, solverQ);
	/// 这里没有对速度质量阵进行边界条件处理.
	InverseMatrix QInv(mat_v_mass, solverQ);
	SchurComplement schur_complement(mat_BTx, mat_BTy, mat_Bx, mat_By, mat_v_mass, QInv, QInv);
	AMGSolver solverP(mat_p_mass);
	ApproxSchurComplement asc(mat_p_mass, solverQ);
	
	LSCPreconditioner lsc_preconditioner(mat_BTx, mat_BTy, mat_Bx, mat_By, mat_Ax, mat_Ax, mat_v_mass, schur_complement, asc, QInv,
					     AInv, AInv);
	/// 矩阵求解.
	dealii::SolverControl solver_control (400000, l_Euler_tol * rhs.l2_norm(), 0);
	SolverMinRes<Vector<double> > minres(solver_control);
	
	minres.solve(matrix, x, rhs, lsc_preconditioner);
	/// 将整体数值解分割成速度和压力.
	for (int i = 0; i < n_dof_v; ++i)
	{
		v_h[0](i) = x(i);
		v_h[1](i) = x(i + n_dof_v);
	}
	for (int i = 0; i < n_dof_p; ++i)
		p_h(i) =  x(i + 2 * n_dof_v);
	
	/// 计算误差, t为时间参数.
	computeError(t);


// 	/// 矩阵求解.
// 	SparseMatrix<double> mat_BTx(sp_pvx);
// 	SparseMatrix<double> mat_BTy(sp_pvy);
// 	SparseMatrix<double> mat_Bx(sp_vxp);
// 	SparseMatrix<double> mat_By(sp_vyp);
// 	SparseMatrix<double> mat_Ax(sp_vxvx);
// 	SparseMatrix<double> mat_Ay(sp_vyvy);

// 	for (int i = 0; i < sp_vxvx.n_nonzero_elements(); ++i)
// 		mat_Ax.global_entry(i) = matrix.global_entry(index_vxvx[i]);
// 	for (int i = 0; i < sp_vyvy.n_nonzero_elements(); ++i)
// 		mat_Ay.global_entry(i) = matrix.global_entry(index_vyvy[i]);
// 	for (int i = 0; i < sp_pvx.n_nonzero_elements(); ++i)
// 		mat_BTx.global_entry(i) = matrix.global_entry(index_pvx[i]);
// 	for (int i = 0; i < sp_pvy.n_nonzero_elements(); ++i)
// 		mat_BTy.global_entry(i) = matrix.global_entry(index_pvy[i]);
// 	for (int i = 0; i < sp_vxp.n_nonzero_elements(); ++i)
// 		mat_Bx.global_entry(i) = matrix.global_entry(index_vxp[i]);
// 	for (int i = 0; i < sp_vyp.n_nonzero_elements(); ++i)
// 		mat_By.global_entry(i) = matrix.global_entry(index_vyp[i]);
	
// 	Vector<double> tmp1(n_dof_v);
// 	Vector<double> tmp2(n_dof_v);
// 	Vector<double> rhs_vx(n_dof_v);
// 	Vector<double> rhs_vy(n_dof_v);
// 	Vector<double> rhs_p(n_dof_p);

// 	for (int i = 0; i < n_dof_v; ++i)
// 	{
// 		rhs_vx(i) = rhs(i);
// 		v_h[0](i) = x(i);
// 		rhs_vy(i) = rhs(n_dof_v + i);
// 		v_h[1](i) = x(n_dof_v + i);
// 	}
// 	for (int i = 0; i < n_dof_p; ++i)
// 	{
// 		rhs_p(i) = rhs(2 * n_dof_v + i);
// 		p_h(i) = x(2 * n_dof_v + i);
// 	}

// 	Vector<double> schur_rhs (n_dof_p);
// 	AMGSolver solverQ(mat_Ax);
// 	InverseMatrix M(mat_Ax, solverQ);
// 	M.vmult (tmp1, rhs_vx);
// 	M.vmult (tmp2, rhs_vy);
// 	mat_Bx.vmult(schur_rhs, tmp1);
// 	mat_By.vmult_add(schur_rhs, tmp2);
// 	schur_rhs -= rhs_p;

// 	SchurComplement schur_complement(mat_BTx, mat_BTy, mat_Bx, mat_By, mat_v_mass, M, M, dt);

// 	SolverControl solver_control_cg (n_dof_p * 2,
// 					 1e-12*schur_rhs.l2_norm());
// 	SolverCG<>    cg (solver_control_cg);

// 	AMGSolver AQ(mat_p_mass);
// 	ApproxSchurComplement asc(mat_p_mass, AQ);
// 	cg.solve (schur_complement, p_h, schur_rhs, asc);

// //	cg.solve (schur_complement, p_h, schur_rhs, PreconditionIdentity());
// 	std::cout << solver_control_cg.last_step()
//             		  << " CG Schur complement iterations to obtain convergence."
//             		  << std::endl;

// 	mat_BTx.vmult(tmp1, *dynamic_cast<const Vector<double>* >(&p_h));
// 	mat_BTy.vmult(tmp2, *dynamic_cast<const Vector<double>* >(&p_h));
// 	tmp1 *= -1;
// 	tmp2 *= -1;
// 	tmp1 += rhs_vx;
// 	tmp2 += rhs_vy;

// 	M.vmult(v_h[0], tmp1);
// 	M.vmult(v_h[1], tmp2);
// 	std::cout << "Stokes system solved." << std::endl;
// 	/// 计算误差, t为时间参数.
// 	computeError(t);
// 	/// debug, 计算惨量的L2 norm。
// 	Vector<double> res(n_total_dof);
// 	matrix.vmult(res, x);
// 	res *= -1;
// 	res += rhs;
// 	std::cout << "res_l2norm =" << res.l2_norm() << std::endl;
};