代码拉取完成,页面将自动刷新
#include "FEMSpace.h"
#include "Mesh.h"
#include "Element.h"
#include "Equation.h"
#include <Eigen/Sparse>
#include "Error.h"
#include "Eigen/IterativeLinearSolvers"
#include "MultigridSolver.h"
#include "Surface.h"
#include <cmath>
#define pi 4*atan(1.0)
//===========右端项================//
double f(double *p,double t)
{
double x = p[0];
double y = p[1];
//return 2 * (t - 1) * std::exp(t * t + x + y);
return (1 + 2 * t * 4 * pi * pi) * sin(2 * pi * x) * sin(2 * pi * y);
//return (1 + 2 * t * pi * pi) * cos(pi * x) * cos(pi * y);
}
//===========初始条件==============//
double u0(double *p)
{
double x = p[0];
double y = p[1];
//return std::exp(x + y);
//return 0;
return 0;
}
//====真解 +边界条件 ==============//
double u(double *p,double t)
{
double x = p[0];
double y = p[1];
//return std::exp(t * t + x + y);
return t * sin(2 * pi * x) *sin(2 * pi * y);
//return t * cos(pi * x) *cos(pi * y);
}
// =======终止函数:用于计算误差 =====//
double u1(double *p)
{
double x = p[0];
double y = p[1];
//return std::exp(1 + x + y);
return sin(2 * pi * x) *sin(2 * pi * y);
//return cos(pi * x) *cos(pi * y);
}
// =======扩散系数 =============//
double c(double *p,double t)
{
return 1;
}
typedef Eigen::SparseMatrix<Real> SpMat;
typedef Eigen::Triplet<Real> Tri;
typedef Eigen::VectorXd VectorXd;
//for windows
//g++ -o main .\HeatEquation.cpp -std=c++11 -I \\wsl$\Ubuntu-18.04\usr\include\eigen3 .\include\tinyxml2.cpp
//for linux
//g++ -o main HeatEquation.cpp -std=c++11 -I /usr/include/eigen3/ ./include/tinyxml2.cpp -g
int main(int argv,char *argc[])
{
//======设置参数,网格大小,时间步数划分,单元选择,网格选择 =========//
double theta = 0.5;
int n = 6;
double T = 1.0;
int n_t = 16;
double d_t = T / double(n_t);
RectangleDomain * Domain= new RectangleDomain({{0,0},{1,0},{1,1},{0,1}});
Mesh<2> * mesh = new Q1Mesh(Domain,{POW2(n),POW2(n)});
Element<2> * element = new Quadrilateral_1_Element();
//============组装过程中需要的矩阵和向量========================//
int n_dofs_point = mesh ->n_dofs();
SpMat M(n_dofs_point,n_dofs_point);
SpMat A(n_dofs_point,n_dofs_point);
std::vector<VectorXd> solution_list;
std::vector<VectorXd> rhs_list;
int n_Dofs = element->n_Dofs();
std::vector<Tri> TriList((mesh->n_element()) * n_Dofs * n_Dofs);
std::vector<Tri> TriListM((mesh->n_element()) * n_Dofs * n_Dofs);
std::vector<Tri>::iterator it = TriList.begin();
std::vector<Tri>::iterator it_m = TriListM.begin();
//============组装刚度矩阵和Mass矩阵 ========================//
for (int k = 0; k < mesh -> n_element(); k++)
{
std::vector<int> Idx = mesh->NodeofEle(k);
std::vector<Dofs<2> > temp(n_Dofs);
for(int i = 0;i < n_Dofs; i++)
{
temp[i] = mesh->DofsofIndex(Idx[i]);
}
element->SetDofsList(temp);
for (int i = 1; i <= n_Dofs; i++)
for (int j = 1; j <= n_Dofs; j++)
{
Real det = element -> det_Jacobi(0,0);
Real a = 0;
Real m = 0;
for (int h = 0; h < element->n_GaussPnt(); h++)
{
Real xi = element->GaussionPoint(h)[0];
Real eta = element->GaussionPoint(h)[1];
a = a + element-> det_Jacobi(xi, eta) * element->GaussionWeight(h) * InnerProuduct(element->gradient(xi,eta,i),element->gradient(xi,eta,j));
m = m + element-> det_Jacobi(xi, eta) * element ->GaussionWeight(h) * element ->phi(xi,eta,i) * element -> phi(xi , eta , j);
}
*it = Tri(element->NdIdx(i), element->NdIdx(j), a);
*it_m = Tri(element->NdIdx(i), element->NdIdx(j), m);
it++;
it_m++;
}
}
A.setFromTriplets(TriList.begin(), TriList.end());
A.makeCompressed();
M.setFromTriplets(TriListM.begin(), TriListM.end());
M.makeCompressed();
//std::cout << A << std::endl;
//std::cout << M << std::endl;
//=============组装所有右端项 ==========================//
for(int m = 0;m <= n_t;m++)
{
VectorXd bm = Eigen::MatrixXd::Zero(n_dofs_point,1);
int n_GaussPnt = element->n_GaussPnt();
for (int k = 0; k < mesh -> n_element(); k++)
{
std::vector<int> Idx = mesh->NodeofEle(k);
std::vector<Dofs<2>> temp(n_Dofs);
for(int i = 0; i < n_Dofs; i++)
{
temp[i] = mesh ->DofsofIndex(Idx[i]);
}
element->SetDofsList(temp);
for(int i = 1; i <= n_Dofs; i++)
{
Real a = 0.0;
for (int j = 0; j < n_GaussPnt; j++)
{
double xi = element->GaussionPoint(j)[0];
double eta = element->GaussionPoint(j)[1];
double xi_ = element->Global_x(xi, eta);
double eta_ = element->Global_y(xi, eta);
Dofs<2> temp({xi_,eta_});
a = a + element->det_Jacobi(xi, eta) * element->GaussionWeight(j) * element->phi(xi, eta, i)* f(*temp,double(d_t * m));
}
bm[element->NdIdx(i)]+= a;
}
}
rhs_list.push_back(bm);
}
//======================初始条件离散=============================//
VectorXd x0 = VectorXd(n_dofs_point);
for(int j = 0; j <= POW2(n);j++)
{
for(int i = 0;i <= POW2(n);i++)
{
double point[2] = {i * mesh -> x_h(),j * mesh->y_h()};
x0[i + (POW2(n) + 1) * j] = u0(point);
}
}
solution_list.push_back(x0);
//================全离散格式并迭代求解 ====================================//
SpMat A_c(n_dofs_point,n_dofs_point);
VectorXd b_c(n_dofs_point);
Eigen::ConjugateGradient<Eigen::SparseMatrix<double> > Solver_sparse;
for(int m = 1;m <= n_t ;m++)
{
A_c = M *(1.0 / d_t) + theta * A;
b_c = theta * rhs_list[m] + (1 - theta) * rhs_list[m - 1] + (M *(1.0 / d_t) - (1 - theta) * A) * solution_list[m - 1];
for(auto k:mesh->Boundary())
{
Dofs<2> bnd_point = mesh ->DofsofIndex(k);
Real bnd_value = u(*bnd_point,double(d_t * m));
b_c[k] = bnd_value * A_c.coeffRef(k,k);
for(Eigen::SparseMatrix<Real>::InnerIterator it(A_c,k);it;++it)
{
int row = it.row();
if(row == k)
continue;
b_c[row] -= A_c.coeffRef(k,row)* bnd_value;
A_c.coeffRef(k,row) = 0.0;
A_c.coeffRef(row,k) = 0.0;
}
}
Solver_sparse.setTolerance(1e-12);
Solver_sparse.compute(A_c);
solution_list.push_back(Solver_sparse.solve(b_c));
}
//===============输出成VTK等格式进行可视化===============//
for(int m = 0; m <=n_t;m++)
{
Surface<2> S(mesh,element,solution_list[m]);
std::string s("surface_heat");
s+= std::to_string(m);
S.WriteVTKData(s);
}
//==============计算最终误差 ==========================//
Error<2> E(mesh,element,u1,solution_list[n_t]);
std::cout << "L2 error is :" << E.L2Norm() << std::endl;
//===========d_t = d_h 时,有二阶精度 ==================//
delete mesh;
delete element;
delete Domain;
return 0;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。