ios_prec.cpp

由于博客内容为空,暂无法提供包含关键信息的摘要。
 
/* make mpirun --use-hwthread-cpus -np 6 main mpirun --use-hwthread-cpus -np 6 -- main -NN 6 -dt 0.1 */ //MFEM #include "mfem.hpp" #include <fstream> #include <iostream> #include <algorithm> #include <iomanip> #include "Integ.hpp" using namespace std; using namespace mfem; #define mfemPrintf(...) { \ if (Mpi::Root()) { \ printf(__VA_ARGS__); \ } \ }//令mfemPrintf函数可用 const real_t PARAM_NU = 1.0; // viscosity const real_t PARAM_KAPPA = 1.0; // thermal diffusivity const real_t PARAM_BETA = 1.0; // thermal expansion coefficient //exampleC void uFun_ex(const Vector & x,real_t t, Vector & u) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); u(0) = yi*sin(t)*sin(t); u(1) = zi*sin(t)*sin(t); u(2) = xi*sin(t)*sin(t); } void gradu_exact(const Vector &xx,real_t t, Vector &u) { real_t x(xx(0)); real_t y(xx(1)); real_t z(xx(2)); // grad u1 u[0] = 0.0; u[1] = sin(t)*sin(t); u[2] = 0.0; // grad u2 u[3] = 0.0; u[4] = 0.0; u[5] = sin(t)*sin(t); // grad u3 u[6] = sin(t)*sin(t); u[7] = 0.0; u[8] = 0.0; } real_t pFun_ex(const Vector & x,real_t t) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); return (xi+yi+zi-1.5)*sin(t)*sin(t); } void fFun(const Vector & x,real_t t, Vector & f) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); f(0) = zi*pow(sin(t),4)+pow(sin(t),2)+2*yi*cos(t)*sin(t); f(1) = xi*pow(sin(t),4)+pow(sin(t),2)+2*zi*cos(t)*sin(t); f(2) = yi*pow(sin(t),4)+pow(sin(t),2)+2*xi*cos(t)*sin(t); } // 温度场的解析解和源项 real_t thetaFun_ex(const Vector & x, real_t t) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); return (xi + yi + zi - 1.5) * sin(t) * sin(t); } real_t psiFun(const Vector & x, real_t t) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); // 根据方程推导的源项 return (xi + yi + zi - 1.5) * (2 * sin(t) * cos(t)) + PARAM_KAPPA * 3 * sin(t) * sin(t) + (yi * sin(t) * sin(t) * sin(t) * sin(t) + zi * sin(t) * sin(t) * sin(t) * sin(t) + xi * sin(t) * sin(t) * sin(t) * sin(t)); } // 浮力项系数 class BuoyancyCoefficient : public VectorCoefficient { private: Coefficient &theta_coeff; Coefficient &beta_coeff; Vector gravity; public: BuoyancyCoefficient(int dim, Coefficient &theta_, Coefficient &beta_) : VectorCoefficient(dim), theta_coeff(theta_), beta_coeff(beta_) { gravity.SetSize(dim); gravity = 0.0; gravity(2) = -1.0; // 重力方向为负z轴 } virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip) { real_t theta_val = theta_coeff.Eval(T, ip); real_t beta_val = beta_coeff.Eval(T, ip); V.Set(beta_val * theta_val, gravity); } }; //向量函数的H1误差 real_t ComputeVectorGradError(ParGridFunction &sol, VectorCoefficient &exgrad, const IntegrationRule *irs[]) { ParFiniteElementSpace *fes = sol.ParFESpace(); real_t error = 0.0; const FiniteElement *fe; ElementTransformation *Tr; DenseMatrix grad; int intorder; int sdim = fes->GetMesh()->SpaceDimension(); int vdim = fes->GetVDim(); Vector vec(vdim * sdim); for (int i = 0; i < fes->GetNE(); i++) { fe = fes->GetFE(i); Tr = fes->GetElementTransformation(i); intorder = 2 * fe->GetOrder() + 3; // <-------- const IntegrationRule *ir; if (irs) { ir = irs[fe->GetGeomType()]; } else { ir = &(IntRules.Get(fe->GetGeomType(), intorder)); } for (int j = 0; j < ir->GetNPoints(); j++) { const IntegrationPoint &ip = ir->IntPoint(j); Tr->SetIntPoint(&ip); sol.GetVectorGradient(*Tr, grad); exgrad.Eval(vec, *Tr, ip); for (int d = 0; d < vdim; d++) { for (int k = 0; k < sdim; k++) { vec(d * sdim + k) -= grad(d, k); } } error += ip.weight * Tr->Weight() * (vec * vec); } } real_t glb_error = 0.0; MPI_Allreduce(&error, &glb_error, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM, fes->GetComm()); return sqrt(glb_error); } // Function to compute the integral of a ParGridFunction and subtract its mean value void Zeromean(ParGridFunction &p) { ParFiniteElementSpace *p_space = p.ParFESpace(); ParLinearForm int_form(p_space); ConstantCoefficient one_coeff(1.0); int_form.AddDomainIntegrator(new DomainLFIntegrator(one_coeff)); int_form.Assemble(); real_t int_p = 0.0; real_t int_p_loc = InnerProduct(int_form, p); //使用 MPI 的 MPI_Allreduce 函数将所有进程中的局部积分结果 int_p_loc 进行全局归约(求和),并将结果存储在 int_p 中 MPI_Allreduce(&int_p_loc, &int_p, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //mfemPrintf("Integral of p: %lg, ", int_p); ParGridFunction one_gf(p_space); one_gf.ProjectCoefficient(one_coeff); real_t vol_loc = InnerProduct(int_form, one_gf); real_t vol = 0.0; MPI_Allreduce(&vol_loc, &vol, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); real_t mean_p = int_p / vol; p.Add(-mean_p, one_gf); int_p_loc = InnerProduct(int_form, p); MPI_Allreduce(&int_p_loc, &int_p, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //mfemPrintf("after modification: %lg\n", int_p); } // 改进的预条件器类,处理速度-压力-温度三场耦合 class BoussinesqPC : public mfem::Solver { private: ParFiniteElementSpace *V_space; ParFiniteElementSpace *P_space; ParFiniteElementSpace *T_space; BlockOperator &block_op; Array<int> &block_trueOffsets; // 速度块预条件器组件 HypreParMatrix *pc_Fmat; // 修改名称,添加pc_前缀 HypreBoomerAMG *prec_F; CGSolver *solver_F; // 压力Schur补预条件器组件 HypreParMatrix *pc_Kpmat; // 修改名称,添加pc_前缀 HypreBoomerAMG *prec_Kp; CGSolver *solver_Kp; HypreParMatrix *pc_Mpmat; // 修改名称,添加pc_前缀 HypreDiagScale *prec_Mp; CGSolver *solver_Mp; // 温度Schur补预条件器组件 HypreParMatrix *pc_Ktmat; // 修改名称,添加pc_前缀 HypreBoomerAMG *prec_Kt; CGSolver *solver_Kt; HypreParMatrix *pc_Mtmat; // 修改名称,添加pc_前缀 HypreDiagScale *prec_Mt; CGSolver *solver_Mt; // 耦合项矩阵 HypreParMatrix *pc_Gmat; // 修改名称,添加pc_前缀 real_t dt_, nu_, kappa_, beta_; public: BoussinesqPC(ParFiniteElementSpace *V_space_, ParFiniteElementSpace *P_space_, ParFiniteElementSpace *T_space_, BlockOperator &block_op_, Array<int> &offsets_, real_t dt_, real_t nu_, real_t kappa_, real_t beta_) : Solver(offsets_[3]), V_space(V_space_), P_space(P_space_), T_space(T_space_), block_op(block_op_), block_trueOffsets(offsets_), dt_(dt_), nu_(nu_), kappa_(kappa_), beta_(beta_), pc_Fmat(nullptr), pc_Kpmat(nullptr), pc_Mpmat(nullptr), pc_Ktmat(nullptr), pc_Mtmat(nullptr), pc_Gmat(nullptr) { // 初始化速度块预条件器 ConstantCoefficient oneondt(1.0 / dt_); ConstantCoefficient nu_coeff(nu_); ParBilinearForm F_varf(V_space); F_varf.AddDomainIntegrator(new VectorMassIntegrator(oneondt)); F_varf.AddDomainIntegrator(new VectorDiffusionIntegrator(nu_coeff)); F_varf.Assemble(); F_varf.Finalize(); pc_Fmat = F_varf.ParallelAssemble(); if (pc_Fmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Fmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } prec_F = new HypreBoomerAMG(*pc_Fmat); prec_F->SetPrintLevel(0); solver_F = new CGSolver(MPI_COMM_WORLD); solver_F->SetPreconditioner(*prec_F); solver_F->SetOperator(*pc_Fmat); solver_F->SetRelTol(1e-5); solver_F->SetMaxIter(100); solver_F->SetPrintLevel(0); // 初始化压力Schur补预条件器 ParBilinearForm Mp_varf(P_space); Mp_varf.AddDomainIntegrator(new MassIntegrator); Mp_varf.Assemble(); Mp_varf.Finalize(); pc_Mpmat = Mp_varf.ParallelAssemble(); if (pc_Mpmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Mpmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } prec_Mp = new HypreDiagScale(*pc_Mpmat); solver_Mp = new CGSolver(MPI_COMM_WORLD); solver_Mp->SetPreconditioner(*prec_Mp); solver_Mp->SetOperator(*pc_Mpmat); solver_Mp->SetRelTol(1e-5); solver_Mp->SetMaxIter(100); solver_Mp->SetPrintLevel(0); ParBilinearForm Kp_varf(P_space); Kp_varf.AddDomainIntegrator(new DiffusionIntegrator); Kp_varf.Assemble(); Array<int> ess_vdofs_p; if(Mpi::Root()) { ess_vdofs_p.Append(0); } Kp_varf.EliminateVDofs(ess_vdofs_p); Kp_varf.Finalize(); pc_Kpmat = Kp_varf.ParallelAssemble(); if (pc_Kpmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Kpmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } prec_Kp = new HypreBoomerAMG(*pc_Kpmat); prec_Kp->SetPrintLevel(0); solver_Kp = new CGSolver(MPI_COMM_WORLD); solver_Kp->SetPreconditioner(*prec_Kp); solver_Kp->SetOperator(*pc_Kpmat); solver_Kp->SetRelTol(1e-5); solver_Kp->SetMaxIter(100); solver_Kp->SetPrintLevel(0); // 初始化温度Schur补预条件器 ParBilinearForm Mt_varf(T_space); Mt_varf.AddDomainIntegrator(new MassIntegrator); Mt_varf.Assemble(); Mt_varf.Finalize(); pc_Mtmat = Mt_varf.ParallelAssemble(); if (pc_Mtmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Mtmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } prec_Mt = new HypreDiagScale(*pc_Mtmat); solver_Mt = new CGSolver(MPI_COMM_WORLD); solver_Mt->SetPreconditioner(*prec_Mt); solver_Mt->SetOperator(*pc_Mtmat); solver_Mt->SetRelTol(1e-5); solver_Mt->SetMaxIter(100); solver_Mt->SetPrintLevel(0); ParBilinearForm Kt_varf(T_space); Kt_varf.AddDomainIntegrator(new DiffusionIntegrator); Kt_varf.Assemble(); Array<int> ess_vdofs_t; if(Mpi::Root()) { ess_vdofs_t.Append(0); } Kt_varf.EliminateVDofs(ess_vdofs_t); Kt_varf.Finalize(); pc_Ktmat = Kt_varf.ParallelAssemble(); if (pc_Ktmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Ktmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } prec_Kt = new HypreBoomerAMG(*pc_Ktmat); prec_Kt->SetPrintLevel(0); solver_Kt = new CGSolver(MPI_COMM_WORLD); solver_Kt->SetPreconditioner(*prec_Kt); solver_Kt->SetOperator(*pc_Ktmat); solver_Kt->SetRelTol(1e-5); solver_Kt->SetMaxIter(100); solver_Kt->SetPrintLevel(0); // 初始化浮力耦合项矩阵 Vector gravity(3); gravity = 0.0; gravity(2) = -1.0; // 重力方向为负z轴 VectorConstantCoefficient g_coeff(gravity); ParMixedBilinearForm G_varf(T_space, V_space); G_varf.AddDomainIntegrator(new VectorMassIntegrator(g_coeff)); G_varf.Assemble(); G_varf.Finalize(); pc_Gmat = G_varf.ParallelAssemble(); if (pc_Gmat == nullptr) { if (Mpi::Root()) { std::cerr << "错误: pc_Gmat 矩阵装配失败!" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } }; ~BoussinesqPC() { delete pc_Fmat; delete pc_Kpmat; delete pc_Mpmat; delete pc_Ktmat; delete pc_Mtmat; delete pc_Gmat; delete prec_F; delete solver_F; delete prec_Kp; delete solver_Kp; delete prec_Mp; delete solver_Mp; delete prec_Kt; delete solver_Kt; delete prec_Mt; delete solver_Mt; } void Mult(const mfem::Vector &x, mfem::Vector &y) const { StopWatch timer; Vector v_in(x.GetData() + block_trueOffsets[0], block_trueOffsets[1] - block_trueOffsets[0]); Vector p_in(x.GetData() + block_trueOffsets[1], block_trueOffsets[2] - block_trueOffsets[1]); Vector t_in(x.GetData() + block_trueOffsets[2], block_trueOffsets[3] - block_trueOffsets[2]); Vector v_out(y.GetData() + block_trueOffsets[0], block_trueOffsets[1] - block_trueOffsets[0]); Vector p_out(y.GetData() + block_trueOffsets[1], block_trueOffsets[2] - block_trueOffsets[1]); Vector t_out(y.GetData() + block_trueOffsets[2], block_trueOffsets[3] - block_trueOffsets[2]); // 第一步:求解温度Schur补系统 Vector t_temp(t_in.Size()); timer.Clear(); timer.Start(); solver_Kt->Mult(t_in, t_temp); pc_Mtmat->Mult(t_temp, t_temp); solver_Mt->Mult(t_temp, t_out); timer.Stop(); // 第二步:求解压力Schur补系统 Vector p_temp(p_in.Size()); timer.Clear(); timer.Start(); solver_Kp->Mult(p_in, p_temp); pc_Mpmat->Mult(p_temp, p_temp); solver_Mp->Mult(p_temp, p_out); timer.Stop(); // 第三步:求解速度系统,考虑浮力耦合 Vector v_temp(v_in.Size()); // 添加浮力项贡献 Vector Gt_result(v_temp.Size()); if (pc_Gmat != nullptr) { pc_Gmat->Mult(t_out, Gt_result); v_temp.Add(-beta_, Gt_result); } else { if (Mpi::Root()) { std::cerr << "警告: pc_Gmat 为空,跳过浮力项" << std::endl; } } // 添加压力项贡献 - 修复这里 Operator& Bt_op = block_op.GetBlock(0, 1); Vector Bp_result(v_temp.Size()); Bt_op.Mult(p_out, Bp_result); // 直接使用运算符,不进行dynamic_cast v_temp.Add(-1.0, Bp_result); timer.Clear(); timer.Start(); solver_F->Mult(v_temp, v_out); timer.Stop(); }; void SetOperator(const Operator &op) {}; }; int main(int argc, char *argv[]) { StopWatch chrono; // 1. Initialize MPI and HYPRE. Mpi::Init(argc, argv); int myid = Mpi::WorldRank(); Hypre::Init(); bool verbose = (myid == 0); // 2. Parse command-line options. const char *mesh_file = "../data/star.mesh"; int ref_levels = -1; int order = 1; real_t dt = 0.05; real_t t_final = 0.05; int NN = 4;//空间每个坐标轴划分为NN等分 /* make NS_1 mpirun --use-hwthread-cpus -np 6 NS_1 */ bool par_format = false; bool pa = false; const char *device_config = "cpu"; bool visualization = 1; bool adios2 = false; OptionsParser args(argc, argv); args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use."); args.AddOption(&ref_levels, "-r", "--refine", "Number of times to refine the mesh uniformly."); args.AddOption(&order, "-o", "--order", "Finite element order (polynomial degree)."); args.AddOption(&par_format, "-pf", "--parallel-format", "-sf", "--serial-format", "Format to use when saving the results for VisIt."); args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa", "--no-partial-assembly", "Enable Partial Assembly."); args.AddOption(&device_config, "-d", "--device", "Device configuration string, see Device::Configure()."); args.AddOption(&visualization, "-vis", "--visualization", "-no-vis", "--no-visualization", "Enable or disable GLVis visualization."); args.AddOption(&adios2, "-adios2", "--adios2-streams", "-no-adios2", "--no-adios2-streams", "Save data using adios2 streams."); args.AddOption(&dt, "-dt", "--dt", "dt."); args.AddOption(&NN, "-NN", "--NN", "NN."); args.AddOption(&t_final, "-t_final", "--t_final", "t_final."); args.Parse(); if (!args.Good()) { if (verbose) { args.PrintUsage(cout); } return 1; } if (verbose) { args.PrintOptions(cout); } int nsteps = ceil(t_final / dt); dt = t_final / nsteps; // 3. Enable hardware devices such as GPUs, and programming models such as // CUDA, OCCA, RAJA and OpenMP based on command line options. Device device(device_config); if (myid == 0) { device.Print(); } //Mesh int Nx = NN, Ny = NN, Nz = NN; real_t Sx = 1.0, Sy = 1.0, Sz = 1.0; Mesh mesha = Mesh::MakeCartesian3D(Nx, Ny, Nz, Element::TETRAHEDRON, Sx, Sy, Sz); Mesh *mesh=&mesha; int dim = mesh->Dimension(); ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh); pmesh->PrintInfo(std::cout); //delete mesh; //FiniteElementSpace FiniteElementCollection *P2(new H1_FECollection(order+1, dim)); FiniteElementCollection *P1(new H1_FECollection(order)); ParFiniteElementSpace *V_space = new ParFiniteElementSpace(pmesh, P2, dim); ParFiniteElementSpace *P_space = new ParFiniteElementSpace(pmesh, P1); ParFiniteElementSpace *T_space = new ParFiniteElementSpace(pmesh, P1); // 温度空间 HYPRE_BigInt dimR = V_space->GlobalTrueVSize(); HYPRE_BigInt dimW = P_space->GlobalTrueVSize();//查看全局的真实向量自由度(True Vector DoFs)总数 HYPRE_BigInt dimT = T_space->GlobalTrueVSize(); if (verbose)//若当前进程是主进程,查看维数 { std::cout << "***********************************************************\n"; std::cout << "dim(R) = " << dimR << "\n"; std::cout << "dim(W) = " << dimW << "\n"; std::cout << "dim(T) = " << dimT << "\n"; std::cout << "dim(R+W+T) = " << dimR + dimW + dimT << "\n"; std::cout << "***********************************************************\n"; } //Define the coefficients, analytical solution, and rhs of the PDE. ConstantCoefficient k(1.0); ConstantCoefficient nu(PARAM_NU); ConstantCoefficient kappa(PARAM_KAPPA); ConstantCoefficient beta_coeff(PARAM_BETA); ConstantCoefficient m_one(-1.0); ConstantCoefficient oneondt1(1.0 / dt); VectorFunctionCoefficient fcoeff(dim, fFun); VectorFunctionCoefficient ucoeff(dim, uFun_ex); FunctionCoefficient pcoeff(pFun_ex); FunctionCoefficient thetacoeff(thetaFun_ex); FunctionCoefficient psicoeff(psiFun); Array<int> block_Offsets(4);//分块方法 block_Offsets[0] = 0; block_Offsets[1] = V_space->GetTrueVSize(); block_Offsets[2] = P_space->GetTrueVSize(); block_Offsets[3] = T_space->GetTrueVSize(); block_Offsets.PartialSum(); //存储解向量和右端向量,每个时间步都更新 Vector rhs(block_Offsets[3]); Vector sol(block_Offsets[3]); Vector rhs_u(rhs.GetData(), block_Offsets[1] - block_Offsets[0]);//使用rhs的内存,不分配新的内存 Vector rhs_p(rhs.GetData() + block_Offsets[1], block_Offsets[2] - block_Offsets[1]); Vector rhs_t(rhs.GetData() + block_Offsets[2], block_Offsets[3] - block_Offsets[2]); Vector sol_u(sol.GetData(), block_Offsets[1] - block_Offsets[0]); Vector sol_p(sol.GetData() + block_Offsets[1], block_Offsets[2] - block_Offsets[1]); Vector sol_t(sol.GetData() + block_Offsets[2], block_Offsets[3] - block_Offsets[2]); //使用低阶格式得到前面几步的值 ParGridFunction uh_0(V_space),ph(P_space),th(T_space); ParGridFunction beta_kn(V_space),gamma_kn(V_space); ucoeff.SetTime(0.0); pcoeff.SetTime(0.0); thetacoeff.SetTime(0.0); real_t t = 0.0; uh_0.ProjectCoefficient(ucoeff);//设置初值 th.ProjectCoefficient(thetacoeff); chrono.Clear(); chrono.Start(); real_t errp=0.0; real_t errt=0.0; Array<int> ess_bdr(mesh->bdr_attributes.Max()); ess_bdr = 1; // Dirichlet boundary on all boundary faces ParBilinearForm F_old_varf(V_space); F_old_varf.AddDomainIntegrator(new VectorMassIntegrator(oneondt1)); F_old_varf.Assemble(); // 在时间循环外声明矩阵指针,使用不同的名称 HypreParMatrix *main_Fmat = nullptr; HypreParMatrix *main_Bmat = nullptr; HypreParMatrix *main_Btmat = nullptr; HypreParMatrix *main_Cmat = nullptr; HypreParMatrix *main_Gmat = nullptr; HypreParMatrix *main_Gtmat = nullptr; ParGridFunction uh_n(V_space),uh(V_space),theta_n(T_space),theta(T_space); uh_n=uh_0; theta_n=th; if (verbose) { std::cout << "开始时间循环..." << std::endl; } for (int n = 0; n < nsteps; n++) { if (verbose && myid == 0) { std::cout << "时间步 " << n + 1 << "/" << nsteps << std::endl; } // 删除已存在的矩阵 if (main_Fmat) { delete main_Fmat; main_Fmat = nullptr; } if (main_Bmat) { delete main_Bmat; main_Bmat = nullptr; } if (main_Btmat) { delete main_Btmat; main_Btmat = nullptr; } if (main_Cmat) { delete main_Cmat; main_Cmat = nullptr; } if (main_Gmat) { delete main_Gmat; main_Gmat = nullptr; } if (main_Gtmat) { delete main_Gtmat; main_Gtmat = nullptr; } if(n>0){ uh_n=uh; theta_n=theta; } ucoeff.SetTime(t+dt); pcoeff.SetTime(t+dt); thetacoeff.SetTime(t+dt); uh=0.0; theta=0.0; uh.ProjectBdrCoefficient(ucoeff, ess_bdr); theta.ProjectBdrCoefficient(thetacoeff, ess_bdr); beta_kn=uh_n; gamma_kn=uh_n; fcoeff.SetTime(t+dt); ParLinearForm f_form(V_space); f_form.AddDomainIntegrator(new VectorDomainLFIntegrator(fcoeff)); f_form.AddDomainIntegrator(new VectorConvectionLFIntegrator(gamma_kn,-1.0)); f_form.Assemble(); F_old_varf.AddMult(beta_kn, f_form, 1.0);//将F_old*beta_kn(矩阵乘向量)加到f_form上 // 添加浮力项 BuoyancyCoefficient buoyancy_coeff(dim, thetacoeff, beta_coeff); ParLinearForm buoyancy_form(V_space); buoyancy_form.AddDomainIntegrator(new VectorDomainLFIntegrator(buoyancy_coeff)); buoyancy_form.Assemble(); f_form += buoyancy_form; ParLinearForm g_form(P_space); g_form.Assemble(); psicoeff.SetTime(t+dt); ParLinearForm psi_form(T_space); psi_form.AddDomainIntegrator(new DomainLFIntegrator(psicoeff)); psi_form.Assemble(); //Bilinear forms ParBilinearForm F_varf(V_space); F_varf.AddDomainIntegrator(new VectorDiffusionIntegrator(nu)); F_varf.AddDomainIntegrator(new VectorMassIntegrator(oneondt1)); F_varf.Assemble(); ParMixedBilinearForm B_varf(V_space,P_space); B_varf.AddDomainIntegrator(new VectorDivergenceIntegrator(m_one)); B_varf.Assemble(); ParBilinearForm C_varf(T_space); C_varf.AddDomainIntegrator(new DiffusionIntegrator(kappa)); C_varf.AddDomainIntegrator(new MassIntegrator(oneondt1)); C_varf.Assemble(); Vector gravity(3); gravity = 0.0; gravity(2) = -1.0; VectorConstantCoefficient g_coeff(gravity); ParMixedBilinearForm G_varf(T_space,V_space); G_varf.AddDomainIntegrator(new VectorMassIntegrator(g_coeff)); G_varf.Assemble(); // Dirichlet boundary F_varf.EliminateEssentialBC(ess_bdr, uh, f_form); B_varf.EliminateTrialEssentialBC(ess_bdr, uh, g_form); C_varf.EliminateEssentialBC(ess_bdr, theta, psi_form); F_varf.Finalize(); B_varf.Finalize(); C_varf.Finalize(); G_varf.Finalize(); // 创建新矩阵 main_Fmat = F_varf.ParallelAssemble(); main_Bmat = B_varf.ParallelAssemble(); main_Btmat = main_Bmat->Transpose(); main_Cmat = C_varf.ParallelAssemble(); main_Gmat = G_varf.ParallelAssemble(); main_Gtmat = main_Gmat->Transpose(); // 检查矩阵是否成功创建 if (main_Fmat == nullptr || main_Bmat == nullptr || main_Cmat == nullptr || main_Gmat == nullptr || main_Btmat == nullptr || main_Gtmat == nullptr) { if (myid == 0) { std::cerr << "错误: 矩阵装配失败!" << std::endl; if (main_Fmat == nullptr) std::cerr << "main_Fmat is null" << std::endl; if (main_Bmat == nullptr) std::cerr << "main_Bmat is null" << std::endl; if (main_Btmat == nullptr) std::cerr << "main_Btmat is null" << std::endl; if (main_Cmat == nullptr) std::cerr << "main_Cmat is null" << std::endl; if (main_Gmat == nullptr) std::cerr << "main_Gmat is null" << std::endl; if (main_Gtmat == nullptr) std::cerr << "main_Gtmat is null" << std::endl; } MPI_Abort(MPI_COMM_WORLD, 1); } { BlockOperator block_op(block_Offsets); block_op.SetBlock(0, 0, main_Fmat); block_op.SetBlock(0, 1, main_Btmat); block_op.SetBlock(0, 2, main_Gtmat); block_op.SetBlock(1, 0, main_Bmat); block_op.SetBlock(2, 0, main_Gmat); block_op.SetBlock(2, 2, main_Cmat); sol = 0.0;rhs=0.0; f_form.ParallelAssemble(rhs_u); g_form.ParallelAssemble(rhs_p); psi_form.ParallelAssemble(rhs_t);//组装右端向量 // compatibility condition Vector one_vec(rhs_p.Size()); one_vec = 1.0; real_t rhs_p_sum_loc = InnerProduct(rhs_p, one_vec); real_t rhs_p_sum; MPI_Allreduce(&rhs_p_sum_loc, &rhs_p_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); rhs_p -= (rhs_p_sum) / P_space->GlobalTrueVSize(); BoussinesqPC prec(V_space, P_space, T_space, block_op, block_Offsets, dt, PARAM_NU, PARAM_KAPPA, PARAM_BETA); FGMRESSolver solver(MPI_COMM_WORLD); solver.SetRelTol(1e-12); solver.SetMaxIter(500); solver.SetOperator(block_op); solver.SetPreconditioner(prec); solver.SetPrintLevel(1); solver.Mult(rhs, sol); uh.Distribute(sol_u); ph.Distribute(sol_p); theta.Distribute(sol_t);//提取解 if(myid == 0){ cout <<"t = "<< t+dt << endl; } t += dt; } } // 在程序最后统一清理矩阵 delete main_Fmat; delete main_Bmat; delete main_Btmat; delete main_Cmat; delete main_Gmat; delete main_Gtmat; Zeromean(ph); errp += pow(ph.ComputeL2Error(pcoeff),2); errt += pow(theta.ComputeL2Error(thetacoeff),2); //计算误差 //H1误差 int gradu_dim = dim*dim; VectorFunctionCoefficient gradu_exact_coeff(gradu_dim, gradu_exact); gradu_exact_coeff.SetTime(t); real_t GradError = ComputeVectorGradError(uh, gradu_exact_coeff,nullptr); //计算L2误差 real_t err_u; err_u = uh.ComputeL2Error(ucoeff); errp=sqrt(errp*dt); real_t err_p=ph.ComputeL2Error(pcoeff); errt=sqrt(errt*dt); real_t err_theta=theta.ComputeL2Error(thetacoeff); int order_quad = max(2, 2*order+1); const IntegrationRule *irs[Geometry::NumGeom]; for (int i=0; i < Geometry::NumGeom; ++i) { irs[i] = &(IntRules.Get(i, order_quad)); } real_t norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs); chrono.Stop(); if (myid == 0) { cout <<"t = "<< t << " || u_h - u_ex || = " << err_u << endl; cout <<"t = "<< t << " err_p_L2 = " << err_p << endl; cout <<"t = "<< t << " err_theta_L2 = " << err_theta << endl; cout <<"t= "<< t << " H1_error = "<< GradError <<endl; cout << "t = "<< t <<" norm_u = "<< norm_u << "\n"; std::cout << "It took " << chrono.RealTime() << "s. \n"; std::ofstream out_file("parameters1.txt", std::ios::app); if (out_file.is_open()) { out_file << "\n##################### " << "\n"; out_file << std::scientific << std::setprecision(10); out_file << "k = 1" << "\n"; out_file << "T = " << t_final << "\n"; out_file << "dt = " << dt << "\n"; out_file << "NN = " << NN << "\n"; out_file << "err_u = " << err_u << "\n"; out_file << "err_p_L2 = " << err_p << "\n"; out_file << "err_theta_L2 = " << err_theta << "\n"; out_file << "H1_error = "<< GradError << "\n"; out_file << "It took " << chrono.RealTime() << "\n"; out_file.close(); std::cout << "参数已保存到 parameters1.txt" << std::endl; } else { std::cerr << "错误:无法打开文件!" << std::endl; } } // Free the used memory. delete V_space; delete P_space; delete T_space; delete P2; delete P1; delete pmesh; return 0; }该代码可以编译但不能运行,运行后出现下面的报错Options used: --mesh ../data/star.mesh --refine -1 --order 1 --serial-format --no-partial-assembly --device cpu --visualization --no-adios2-streams --dt 0.05 --NN 4 --t_final 0.05 Device configuration: cpu Memory configuration: host-std Parallel Mesh Stats: minimum average maximum total vertices 48 62 77 125 edges 268 302 336 604 faces 411 432 453 864 elements 191 192 193 384 neighbors 1 1 1 minimum maximum h 0.280616 0.280616 kappa 2.41421 2.41421 *********************************************************** dim(R) = 2187 dim(W) = 125 dim(T) = 125 dim(R+W+T) = 2437 *********************************************************** 开始时间循环... 时间步 1/1 [LAPTOP-QL5QOURA:00495] *** Process received signal *** [LAPTOP-QL5QOURA:00495] Signal: Segmentation fault (11) [LAPTOP-QL5QOURA:00495] Signal code: Address not mapped (1) [LAPTOP-QL5QOURA:00495] Failing at address: (nil) [LAPTOP-QL5QOURA:00496] *** Process received signal *** [LAPTOP-QL5QOURA:00496] Signal: Segmentation fault (11) [LAPTOP-QL5QOURA:00496] Signal code: Address not mapped (1) [LAPTOP-QL5QOURA:00496] Failing at address: (nil) [LAPTOP-QL5QOURA:00495] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x7e1f49645330] [LAPTOP-QL5QOURA:00495] [ 1] ./NS_1(+0x44ca78)[0x5675352dba78] [LAPTOP-QL5QOURA:00495] [ 2] ./NS_1(+0x44179f)[0x5675352d079f] [LAPTOP-QL5QOURA:00495] [ 3] ./NS_1(+0x4986ed)[0x5675353276ed] [LAPTOP-QL5QOURA:00495] [ 4] ./NS_1(+0xa06ef)[0x567534f2f6ef] [LAPTOP-QL5QOURA:00495] [ 5] [LAPTOP-QL5QOURA:00496] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x7e6862445330] [LAPTOP-QL5QOURA:00496] [ 1] ./NS_1(+0x44ca78)[0x555f7df7ea78] [LAPTOP-QL5QOURA:00496] [ 2] ./NS_1(+0x44179f)[0x555f7df7379f] [LAPTOP-QL5QOURA:00496] [ 3] ./NS_1(+0x4986ed)[0x555f7dfca6ed] [LAPTOP-QL5QOURA:00496] [ 4] ./NS_1(+0xa06ef)[0x555f7dbd26ef] [LAPTOP-QL5QOURA:00496] [ 5] /lib/x86_64-linux-gnu/libc.so.6(+0x2a1ca)[0x7e686242a1ca] [LAPTOP-QL5QOURA:00496] [ 6] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x8b)[0x7e686242a28b] [LAPTOP-QL5QOURA:00496] [ 7] ./NS_1(+0xa7e15)[0x555f7dbd9e15] [LAPTOP-QL5QOURA:00496] *** End of error message *** /lib/x86_64-linux-gnu/libc.so.6(+0x2a1ca)[0x7e1f4962a1ca] [LAPTOP-QL5QOURA:00495] [ 6] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x8b)[0x7e1f4962a28b] [LAPTOP-QL5QOURA:00495] [ 7] ./NS_1(+0xa7e15)[0x567534f36e15] [LAPTOP-QL5QOURA:00495] *** End of error message *** -------------------------------------------------------------------------- Primary job terminated normally, but 1 process returned a non-zero exit code. Per user-direction, the job has been aborted. -------------------------------------------------------------------------- -------------------------------------------------------------------------- mpirun noticed that process rank 0 with PID 0 on node LAPTOP-QL5QOURA exited on signal 11 (Segmentation fault). --------------------------------------------------------------------------给我提供详细的修改方案使其可以运行
09-20
wyj@LAPTOP-QL5QOURA:~/NS_highorder$ mpirun -np 2 ./NS_1 Options used: --mesh ../data/star.mesh --refine -1 --order 1 --serial-format --no-partial-assembly --device cpu --visualization --no-adios2-streams --dt 0.05 --NN 4 --t_final 0.05 Device configuration: cpu Memory configuration: host-std Parallel Mesh Stats: minimum average maximum total vertices 48 62 77 125 edges 268 302 336 604 faces 411 432 453 864 elements 191 192 193 384 neighbors 1 1 1 minimum maximum h 0.280616 0.280616 kappa 2.41421 2.41421 *********************************************************** dim(R) = 2187 dim(W) = 125 dim(T) = 125 dim(R+W+T) = 2437 *********************************************************** 开始时间循环... 时间步 1/1 [LAPTOP-QL5QOURA:00562] *** Process received signal *** [LAPTOP-QL5QOURA:00562] Signal: Segmentation fault (11) [LAPTOP-QL5QOURA:00562] Signal code: Address not mapped (1) [LAPTOP-QL5QOURA:00562] Failing at address: (nil) [LAPTOP-QL5QOURA:00562] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x7d7dbb045330] [LAPTOP-QL5QOURA:00562] [ 1] ./NS_1(+0x44c638)[0x5fd56a1f5638] [LAPTOP-QL5QOURA:00562] [ 2] ./NS_1(+0x44135f)[0x5fd56a1ea35f] [LAPTOP-QL5QOURA:00562] [ 3] ./NS_1(+0x4982ad)[0x5fd56a2412ad] [LAPTOP-QL5QOURA:00562] [ 4] ./NS_1(+0xa0737)[0x5fd569e49737] [LAPTOP-QL5QOURA:00562] [ 5] /lib/x86_64-linux-gnu/libc.so.6(+0x2a1ca)[0x7d7dbb02a1ca] [LAPTOP-QL5QOURA:00562] [ 6] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x8b)[0x7d7dbb02a28b] [LAPTOP-QL5QOURA:00562] [ 7] ./NS_1(+0xa7ea5)[0x5fd569e50ea5] [LAPTOP-QL5QOURA:00562] *** End of error message *** [LAPTOP-QL5QOURA:00561] *** Process received signal *** [LAPTOP-QL5QOURA:00561] Signal: Segmentation fault (11) [LAPTOP-QL5QOURA:00561] Signal code: Address not mapped (1) [LAPTOP-QL5QOURA:00561] Failing at address: (nil) [LAPTOP-QL5QOURA:00561] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x45330)[0x7c3874e45330] [LAPTOP-QL5QOURA:00561] [ 1] ./NS_1(+0x44c638)[0x5aa5caf1d638] [LAPTOP-QL5QOURA:00561] [ 2] ./NS_1(+0x44135f)[0x5aa5caf1235f] [LAPTOP-QL5QOURA:00561] [ 3] ./NS_1(+0x4982ad)[0x5aa5caf692ad] [LAPTOP-QL5QOURA:00561] [ 4] ./NS_1(+0xa0737)[0x5aa5cab71737] [LAPTOP-QL5QOURA:00561] [ 5] /lib/x86_64-linux-gnu/libc.so.6(+0x2a1ca)[0x7c3874e2a1ca] [LAPTOP-QL5QOURA:00561] [ 6] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x8b)[0x7c3874e2a28b] [LAPTOP-QL5QOURA:00561] [ 7] ./NS_1(+0xa7ea5)[0x5aa5cab78ea5] [LAPTOP-QL5QOURA:00561] *** End of error message *** -------------------------------------------------------------------------- Primary job terminated normally, but 1 process returned a non-zero exit code. Per user-direction, the job has been aborted. -------------------------------------------------------------------------- -------------------------------------------------------------------------- mpirun noticed that process rank 0 with PID 0 on node LAPTOP-QL5QOURA exited on signal 11 (Segmentation fault). --------------------------------------------------------------------------还是报错,这是未添加温度变量的代码/* make mpirun --use-hwthread-cpus -np 6 main mpirun --use-hwthread-cpus -np 6 -- main -NN 6 -dt 0.1 */ //MFEM #include "mfem.hpp" #include <fstream> #include <iostream> #include <algorithm> #include "Integ.hpp" using namespace std; using namespace mfem; #define mfemPrintf(...) { \ if (Mpi::Root()) { \ printf(__VA_ARGS__); \ } \ }//令mfemPrintf函数可用 const real_t PARAM_NU = 1.0; // viscosity //exampleC void uFun_ex(const Vector & x,real_t t, Vector & u) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); u(0) = yi*sin(t)*sin(t); u(1) = zi*sin(t)*sin(t); u(2) = xi*sin(t)*sin(t); } void gradu_exact(const Vector &xx,real_t t, Vector &u) { // real_t x(xx(0)); // real_t y(xx(1)); // real_t z(xx(2)); //real_t pi = M_PI; // M_PI 是数学常量 π 的值 // grad u1 u[0] = 0.0; u[1] = sin(t)*sin(t); u[2] = 0.0; // grad u2 u[3] = 0.0; u[4] = 0.0; u[5] = sin(t)*sin(t); // grad u3 u[6] = sin(t)*sin(t); u[7] = 0.0; u[8] = 0.0; } real_t pFun_ex(const Vector & x,real_t t) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); return (xi+yi+zi-1.5)*sin(t)*sin(t); } void fFun(const Vector & x,real_t t, Vector & f) { real_t xi(x(0)); real_t yi(x(1)); real_t zi(x(2)); f(0) = zi*pow(sin(t),4)+pow(sin(t),2)+2*yi*cos(t)*sin(t); f(1) = xi*pow(sin(t),4)+pow(sin(t),2)+2*zi*cos(t)*sin(t); f(2) = yi*pow(sin(t),4)+pow(sin(t),2)+2*xi*cos(t)*sin(t); } //向量函数的H1误差 real_t ComputeVectorGradError(ParGridFunction &sol, VectorCoefficient &exgrad, const IntegrationRule *irs[]) { ParFiniteElementSpace *fes = sol.ParFESpace(); real_t error = 0.0; const FiniteElement *fe; ElementTransformation *Tr; DenseMatrix grad; int intorder; int sdim = fes->GetMesh()->SpaceDimension(); int vdim = fes->GetVDim(); Vector vec(vdim * sdim); for (int i = 0; i < fes->GetNE(); i++) { fe = fes->GetFE(i); Tr = fes->GetElementTransformation(i); intorder = 2 * fe->GetOrder() + 3; // <-------- const IntegrationRule *ir; if (irs) { ir = irs[fe->GetGeomType()]; } else { ir = &(IntRules.Get(fe->GetGeomType(), intorder)); } for (int j = 0; j < ir->GetNPoints(); j++) { const IntegrationPoint &ip = ir->IntPoint(j); Tr->SetIntPoint(&ip); sol.GetVectorGradient(*Tr, grad); exgrad.Eval(vec, *Tr, ip); for (int d = 0; d < vdim; d++) { for (int k = 0; k < sdim; k++) { vec(d * sdim + k) -= grad(d, k); } } error += ip.weight * Tr->Weight() * (vec * vec); } } real_t glb_error = 0.0; MPI_Allreduce(&error, &glb_error, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM, fes->GetComm()); return sqrt(glb_error); } // Function to compute the integral of a ParGridFunction and subtract its mean value void Zeromean(ParGridFunction &p) { ParFiniteElementSpace *p_space = p.ParFESpace(); ParLinearForm int_form(p_space); ConstantCoefficient one_coeff(1.0); int_form.AddDomainIntegrator(new DomainLFIntegrator(one_coeff)); int_form.Assemble(); real_t int_p = 0.0; real_t int_p_loc = InnerProduct(int_form, p); //使用 MPI 的 MPI_Allreduce 函数将所有进程中的局部积分结果 int_p_loc 进行全局归约(求和),并将结果存储在 int_p 中 MPI_Allreduce(&int_p_loc, &int_p, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //mfemPrintf("Integral of p: %lg, ", int_p); ParGridFunction one_gf(p_space); one_gf.ProjectCoefficient(one_coeff); real_t vol_loc = InnerProduct(int_form, one_gf); real_t vol = 0.0; MPI_Allreduce(&vol_loc, &vol, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); real_t mean_p = int_p / vol; p.Add(-mean_p, one_gf); int_p_loc = InnerProduct(int_form, p); MPI_Allreduce(&int_p_loc, &int_p, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //mfemPrintf("after modification: %lg\n", int_p); } // Pressure Convection Diffusion (PCD) preconditioner, designed for Navier-Stokes problems class StokesPC : public mfem::Solver { private: ParFiniteElementSpace *P_space; BlockOperator &block_op; Array<int> &block_trueOffsets; HypreParMatrix *Kpmat; HypreBoomerAMG *prec_Kp; CGSolver *solver_Kp; HypreParMatrix *Mpmat; HypreDiagScale *prec_Mp; CGSolver *solver_Mp; HypreParMatrix *Fpmat; HypreBoomerAMG *prec_F; CGSolver *solver_F; public: StokesPC(ParFiniteElementSpace *P_space_, BlockOperator &block_op_, Array<int> &offsets_,real_t dt_,real_t nu_,real_t alphak_) : Solver(offsets_[2]), P_space(P_space_), block_op(block_op_), block_trueOffsets(offsets_) { ParBilinearForm Mp_varf(P_space); Mp_varf.AddDomainIntegrator(new MassIntegrator); Mp_varf.Assemble(); Mp_varf.Finalize(); Mpmat = Mp_varf.ParallelAssemble(); prec_Mp = new HypreDiagScale(*Mpmat); solver_Mp = new CGSolver(MPI_COMM_WORLD); solver_Mp->SetPreconditioner(*prec_Mp); solver_Mp->SetOperator(*Mpmat); solver_Mp->SetRelTol(1e-5); solver_Mp->SetMaxIter(100); solver_Mp->SetPrintLevel(0); ParBilinearForm Kp_varf(P_space); Kp_varf.AddDomainIntegrator(new DiffusionIntegrator); Kp_varf.Assemble(); Array<int> ess_vdofs_p; if(Mpi::Root())//检查当前进程是否是MPI通信组中的根进程(Root Process) { ess_vdofs_p.Append(0); } Kp_varf.EliminateVDofs(ess_vdofs_p); Kp_varf.Finalize(); Kpmat = Kp_varf.ParallelAssemble(); prec_Kp = new HypreBoomerAMG(*Kpmat); prec_Kp->SetPrintLevel(0); solver_Kp = new CGSolver(MPI_COMM_WORLD); solver_Kp->SetPreconditioner(*prec_Kp); solver_Kp->SetOperator(*Kpmat); solver_Kp->SetRelTol(1e-5); solver_Kp->SetMaxIter(100); solver_Kp->SetPrintLevel(0); ConstantCoefficient oneondt(alphak_ / dt_); ConstantCoefficient nu_Coefficient(nu_ ); ParBilinearForm Fp_varf(P_space); Fp_varf.AddDomainIntegrator(new MassIntegrator(oneondt)); Fp_varf.AddDomainIntegrator(new DiffusionIntegrator(nu_Coefficient)); Fp_varf.Assemble(); Fp_varf.Finalize(); Fpmat = Fp_varf.ParallelAssemble(); prec_F = new HypreBoomerAMG; prec_F->SetPrintLevel(0); solver_F = new CGSolver(MPI_COMM_WORLD); solver_F->SetPreconditioner(*prec_F); solver_F->SetOperator(block_op.GetBlock(0, 0)); solver_F->SetRelTol(1e-5); solver_F->SetMaxIter(100); solver_F->SetPrintLevel(0); }; // Define the action of the Solver void Mult(const mfem::Vector &x, mfem::Vector &y) const { StopWatch timer; Vector v_in(x.GetData() + block_trueOffsets[0], block_trueOffsets[1] - block_trueOffsets[0]); Vector v_out(y.GetData() + block_trueOffsets[0], block_trueOffsets[1] - block_trueOffsets[0]); Vector p_in(x.GetData() + block_trueOffsets[1], block_trueOffsets[2] - block_trueOffsets[1]); Vector p_out(y.GetData() + block_trueOffsets[1], block_trueOffsets[2] - block_trueOffsets[1]); Vector p_temp(p_in); Vector p_temp2(p_in); timer.Clear(); timer.Start(); solver_Kp->Mult(p_in, p_temp); Fpmat->Mult(p_temp, p_temp2); solver_Mp->Mult(p_temp2, p_out); timer.Stop(); Vector u_temp(v_in); block_op.GetBlock(0,1).AddMult(p_out, u_temp, -1.0); timer.Clear(); timer.Start(); solver_F->Mult(u_temp, v_out); timer.Stop(); }; void SetOperator(const Operator &op) {}; }; int main(int argc, char *argv[]) { StopWatch chrono; // 1. Initialize MPI and HYPRE. Mpi::Init(argc, argv); //int num_procs = Mpi::WorldSize(); int myid = Mpi::WorldRank(); Hypre::Init(); bool verbose = (myid == 0); // 2. Parse command-line options. const char *mesh_file = "../data/star.mesh"; int ref_levels = -1; int order = 1; //real_t PARAM_NU = 1.0; real_t dt = 0.05; real_t t_final = 0.05; int NN = 4;//空间每个坐标轴划分为NN等分 /* make NS_1 mpirun --use-hwthread-cpus -np 6 NS_1 */ bool par_format = false; bool pa = false; const char *device_config = "cpu"; bool visualization = 1; bool adios2 = false; OptionsParser args(argc, argv); args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use."); args.AddOption(&ref_levels, "-r", "--refine", "Number of times to refine the mesh uniformly."); args.AddOption(&order, "-o", "--order", "Finite element order (polynomial degree)."); args.AddOption(&par_format, "-pf", "--parallel-format", "-sf", "--serial-format", "Format to use when saving the results for VisIt."); args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa", "--no-partial-assembly", "Enable Partial Assembly."); args.AddOption(&device_config, "-d", "--device", "Device configuration string, see Device::Configure()."); args.AddOption(&visualization, "-vis", "--visualization", "-no-vis", "--no-visualization", "Enable or disable GLVis visualization."); args.AddOption(&adios2, "-adios2", "--adios2-streams", "-no-adios2", "--no-adios2-streams", "Save data using adios2 streams."); args.AddOption(&dt, "-dt", "--dt", "dt."); args.AddOption(&NN, "-NN", "--NN", "NN."); args.AddOption(&t_final, "-t_final", "--t_final", "t_final."); args.Parse(); if (!args.Good()) { if (verbose) { args.PrintUsage(cout); } return 1; } if (verbose) { args.PrintOptions(cout); } int nsteps = ceil(t_final / dt); dt = t_final / nsteps; // 3. Enable hardware devices such as GPUs, and programming models such as // CUDA, OCCA, RAJA and OpenMP based on command line options. Device device(device_config); if (myid == 0) { device.Print(); } //Mesh int Nx = NN, Ny = NN, Nz = NN; real_t Sx = 1.0, Sy = 1.0, Sz = 1.0; Mesh mesha = Mesh::MakeCartesian3D(Nx, Ny, Nz, Element::TETRAHEDRON, Sx, Sy, Sz); Mesh *mesh=&mesha; int dim = mesh->Dimension(); ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh); pmesh->PrintInfo(std::cout); //delete mesh; //FiniteElementSpace FiniteElementCollection *P2(new H1_FECollection(order+1, dim)); FiniteElementCollection *P1(new H1_FECollection(order)); ParFiniteElementSpace *V_space = new ParFiniteElementSpace(pmesh, P2, dim); ParFiniteElementSpace *P_space = new ParFiniteElementSpace(pmesh, P1); HYPRE_BigInt dimR = V_space->GlobalTrueVSize(); HYPRE_BigInt dimW = P_space->GlobalTrueVSize();//查看全局的真实向量自由度(True Vector DoFs)总数 if (verbose)//若当前进程是主进程,查看维数 { std::cout << "***********************************************************\n"; std::cout << "dim(R) = " << dimR << "\n"; std::cout << "dim(W) = " << dimW << "\n"; std::cout << "dim(R+W) = " << dimR + dimW << "\n"; std::cout << "***********************************************************\n"; } //Define the coefficients, analytical solution, and rhs of the PDE. ConstantCoefficient k(1.0); ConstantCoefficient nu(PARAM_NU); ConstantCoefficient m_one(-1.0); ConstantCoefficient oneondt1(1.0 / dt); VectorFunctionCoefficient fcoeff(dim, fFun); VectorFunctionCoefficient ucoeff(dim, uFun_ex); FunctionCoefficient pcoeff(pFun_ex); Array<int> block_Offsets(3);//分块方法 block_Offsets[0] = 0; block_Offsets[1] = V_space->GetTrueVSize(); block_Offsets[2] = P_space->GetTrueVSize(); block_Offsets.PartialSum(); //存储解向量和右端向量,每个时间步都更新 Vector rhs(block_Offsets[2]); Vector sol(block_Offsets[2]); Vector rhs_u(rhs.GetData(), block_Offsets[1] - block_Offsets[0]);//使用rhs的内存,不分配新的内存 Vector rhs_p(rhs.GetData() + block_Offsets[1], block_Offsets[2] - block_Offsets[1]); Vector sol_u(sol.GetData(), block_Offsets[1] - block_Offsets[0]); Vector sol_p(sol.GetData() + block_Offsets[1], block_Offsets[2] - block_Offsets[1]); //使用低阶格式得到前面几步的值 ParGridFunction uh_0(V_space),ph(P_space); ParGridFunction beta_kn(V_space),gamma_kn(V_space); ucoeff.SetTime(0.0); pcoeff.SetTime(0.0); real_t t = 0.0; uh_0.ProjectCoefficient(ucoeff);//设置初值 chrono.Clear(); chrono.Start(); real_t errp=0.0; Array<int> ess_bdr(mesh->bdr_attributes.Max()); ess_bdr = 1; // Dirichlet boundary on all boundary faces ParBilinearForm F_old_varf(V_space); F_old_varf.AddDomainIntegrator(new VectorMassIntegrator(oneondt1)); F_old_varf.Assemble(); ParGridFunction uh_n(V_space),uh(V_space); uh_n=uh_0; for (int n = 0; n < nsteps; n++) { if(n>0){ uh_n=uh; } ucoeff.SetTime(t+dt); pcoeff.SetTime(t+dt); uh=0.0; uh.ProjectBdrCoefficient(ucoeff, ess_bdr); beta_kn=uh_n; gamma_kn=uh_n; fcoeff.SetTime(t+dt); ParLinearForm f_form(V_space); f_form.AddDomainIntegrator(new VectorDomainLFIntegrator(fcoeff)); f_form.AddDomainIntegrator(new VectorConvectionLFIntegrator(gamma_kn,-1.0)); f_form.Assemble(); F_old_varf.AddMult(beta_kn, f_form, 1.0);//将F_old*beta_kn(矩阵乘向量)加到f_form上 ParLinearForm g_form(P_space); g_form.Assemble(); //Bilinear forms ParBilinearForm F_varf(V_space); F_varf.AddDomainIntegrator(new VectorDiffusionIntegrator(nu)); F_varf.AddDomainIntegrator(new VectorMassIntegrator(oneondt1)); F_varf.Assemble(); ParMixedBilinearForm B_varf(V_space,P_space); B_varf.AddDomainIntegrator(new VectorDivergenceIntegrator(m_one)); B_varf.Assemble(); // Dirichlet boundary F_varf.EliminateEssentialBC(ess_bdr, uh, f_form); B_varf.EliminateTrialEssentialBC(ess_bdr, uh, g_form); F_varf.Finalize(); B_varf.Finalize(); HypreParMatrix *Fmat = F_varf.ParallelAssemble(); HypreParMatrix *Bmat = B_varf.ParallelAssemble(); HypreParMatrix *Btmat = Bmat->Transpose(); { BlockOperator block_op(block_Offsets); block_op.SetBlock(0, 0, Fmat); block_op.SetBlock(0, 1, Btmat); block_op.SetBlock(1, 0, Bmat);//组装左端矩阵 sol = 0.0;rhs=0.0; f_form.ParallelAssemble(rhs_u); g_form.ParallelAssemble(rhs_p);//组装右端向量 // compatibility condition Vector one_vec(rhs_p.Size()); one_vec = 1.0; real_t rhs_p_sum_loc = InnerProduct(rhs_p, one_vec); // cout << "nproc: " << Mpi::WorldRank() << " rhs_p_sum_loc = " << rhs_p_sum_loc << endl; real_t rhs_p_sum; //将所有进程上的局部和 rhs_p_sum_loc 归约为全局和 rhs_p_sum: MPI_Allreduce(&rhs_p_sum_loc, &rhs_p_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); //cout << "rhs_p_sum = " << rhs_p_sum << endl; rhs_p -= (rhs_p_sum) / P_space->GlobalTrueVSize(); StokesPC prec(P_space, block_op, block_Offsets, dt, PARAM_NU,1.0); FGMRESSolver solver(MPI_COMM_WORLD); //solver.SetAbsTol(1e-10); solver.SetRelTol(1e-12); solver.SetMaxIter(500); solver.SetOperator(block_op); solver.SetPreconditioner(prec); solver.SetPrintLevel(1); solver.Mult(rhs, sol); uh.Distribute(sol_u); ph.Distribute(sol_p);//提取解 if(myid == 0){ cout <<"t = "<< t+dt << endl; } t += dt; } delete Fmat; Fmat = nullptr; delete Bmat; Bmat = nullptr; delete Btmat; Btmat = nullptr; Zeromean(ph); errp += pow(ph.ComputeL2Error(pcoeff),2); } //计算误差 //H1误差 int gradu_dim = dim*dim; VectorFunctionCoefficient gradu_exact_coeff(gradu_dim, gradu_exact); gradu_exact_coeff.SetTime(t); real_t GradError = ComputeVectorGradError(uh, gradu_exact_coeff,nullptr); //计算L2误差 real_t err_u; err_u = uh.ComputeL2Error(ucoeff); errp=sqrt(errp*dt); real_t err_p=ph.ComputeL2Error(pcoeff); int order_quad = max(2, 2*order+1); const IntegrationRule *irs[Geometry::NumGeom]; for (int i=0; i < Geometry::NumGeom; ++i) { irs[i] = &(IntRules.Get(i, order_quad)); } real_t norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs); chrono.Stop(); if (myid == 0) { cout <<"t = "<< t << " || u_h - u_ex || = " << err_u << endl; //cout <<"t = "<< t << " errp = " << errp << endl; cout <<"t = "<< t << " err_p_L2 = " << err_p << endl; cout <<"t= "<< t << " H1_error = "<< GradError <<endl; //cout << "t = "<< t <<" || u_h - u_ex || / || u_ex || = " << err_u / norm_u << "\n"; cout << "t = "<< t <<" norm_u = "<< norm_u << "\n"; std::cout << "It took " << chrono.RealTime() << "s. \n"; // 将所有变量写入文件 std::ofstream out_file("parameters1.txt", std::ios::app); // 打开文件 if (out_file.is_open()) { // 写入带变量名的参数 out_file << "\n##################### " << "\n"; out_file << std::scientific << std::setprecision(10); //out_file << "Example2 " << "\n"; out_file << "k = 1" << "\n"; out_file << "T = " << t_final << "\n"; out_file << "dt = " << dt << "\n"; out_file << "NN = " << NN << "\n"; out_file << "err_u = " << err_u << "\n"; out_file << "err_p_L2 = " << err_p << "\n"; out_file << "H1_error = "<< GradError << "\n"; out_file << "It took " << chrono.RealTime() << "\n"; out_file.close(); // 关闭文件 std::cout << "参数已保存到 parameters1.txt" << std::endl; } else { std::cerr << "错误:无法打开文件!" << std::endl; } } // Free the used memory. delete V_space; delete P_space; delete P2; delete P1; delete pmesh; return 0; } 这个代码不会报错可以正常运行编译,会报错的代码是仿照这个代码编写的
最新发布
09-20
解释一下下面代码//lab9_1.cpp #include <fstream> #include <iostream> using namespace std; #define D(a) T << #a << endl; a ofstream T("output.out"); int main() { D(int i = 53;) D(float f = 4700113.141593;) char* s = "Is there any more?"; D(T.setf(ios::unitbuf);) D(T.setf(ios::showbase);) D(T.setf(ios::uppercase);) D(T.setf(ios::showpos);) D(T << i << endl;) D(T.setf(ios::hex, ios::basefield);) D(T << i << endl;) D(T.unsetf(ios::uppercase);) D(T.setf(ios::oct, ios::basefield);) D(T << i << endl;) D(T.unsetf(ios::showbase);) D(T.setf(ios::dec, ios::basefield);) D(T.setf(ios::left, ios::adjustfield);) D(T.fill('0');) D(T << "fill char: " << T.fill() << endl;) D(T.width(8);) T << i << endl; D(T.setf(ios::right, ios::adjustfield);) D(T.width(8);) T << i << endl; D(T.setf(ios::internal, ios::adjustfield);) D(T.width(8);) T << i << endl; D(T << i << endl;) // Without width(10) D(T.unsetf(ios::showpos);) D(T.setf(ios::showpoint);) D(T << "prec = " << T.precision() << endl;) D(T.setf(ios::scientific, ios::floatfield);) D(T << endl << f << endl;) D(T.setf(ios::fixed, ios::floatfield);) D(T << f << endl;) //D(T.setf(0, ios::floatfield);) D(T << f << endl;) D(T.precision(16);) D(T << "prec = " << T.precision() << endl;) D(T << endl << f << endl;) D(T.setf(ios::scientific, ios::floatfield);) D(T << endl << f << endl;) D(T.setf(ios::fixed, ios::floatfield);) D(T << f << endl;) //D(T.setf(0, ios::floatfield);) D(T << f << endl;) D(T.width(8);) T << s << endl; D(T.width(36);) T << s << endl; D(T.setf(ios::left, ios::adjustfield);) D(T.width(36);) T << s << endl; D(T.unsetf(ios::showpoint);) D(T.unsetf(ios::unitbuf);) }
06-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值