实例2是为了建立单元的自由度以及自由度的稀疏矩阵。
将自由度与单元、顶点、直线关联:
#include <deal.II/dofs/dof_handler.h>
对于平面四边形来说,双线性形函数的自由度只在单元顶点处,具体可以查看有限元形函数的内容。该类同样可以应用到一维和三维的情况:
#include <deal.II/fe/fe_q.h>
同时,还需要操纵自由度的工具:
#include <deal.II/dofs/dof_tools.h>
使用稀疏矩阵来存储自由度中的非零数值:
#include <deal.II/lac/sparse_matrix.h>
使用中间稀疏模式使非零元素尽量靠近对角线,减少存储消耗:
#include <deal.II/lac/dynamic_sparsity_pattern.h>
使用新的算法计算自由度:
#include <deal.II/dofs/dof_renumbering.h>
产生和加密网格:
void make_grid(Triangulation<2> &triangulation)
{
const Point<2> center(1, 0);
const double inner_radius = 0.5, outer_radius = 1.0;
GridGenerator::hyper_shell(
triangulation, center, inner_radius, outer_radius, 5);
for (unsigned int step = 0; step < 3; ++step)
{
for (auto &cell : triangulation.active_cell_iterators())
for (unsigned int v = 0; v < GeometryInfo<2>::vertices_per_cell; ++v)
{
const double distance_from_center =
center.distance(cell->vertex(v));
if (std::fabs(distance_from_center - inner_radius) < 1e-10)
{
cell->set_refine_flag();
break;
}
}
triangulation.execute_coarsening_and_refinement();
}
}
以上只是创建了一个网格,包含顶点位置及拓扑信息,还需要将自由度信息赋给顶点。使用类FE_Q来创建拉格朗日单元,需要给定多项式次数,1表示双线性单元。创建一个有限元对象,然后用DoFHandler分配自由度:
const FE_Q<2> finite_element(1);
dof_handler.distribute_dofs(finite_element);
将自由度分配到每个顶点之后,创建一个结构存储非0元素的位置。使用DynamicSparsityPattern类,传入的参数是自由度的大小:
DynamicSparsityPattern dynamic_sparsity_pattern(dof_handler.n_dofs(),
dof_handler.n_dofs());
通过自由度分布给出非零元素所在的位置:
DoFTools::make_sparsity_pattern(dof_handler, dynamic_sparsity_pattern);
然后将DynamicSparsityPattern的信息传回SpasityPattern,需要它进行计算:
SparsityPattern sparsity_pattern;
sparsity_pattern.copy_from(dynamic_sparsity_pattern);
最后存储到文件:
std::ofstream out("sparsity_pattern1.svg");
sparsity_pattern.print_svg(out);
对自由度进行编号
上面的方法得到的稀疏矩阵中非零元素离对角线较远,对于有些计算不够友好,可以通过重新编写自由度编号来改善,一般是同一个单元节点编号不要差太多,这里使用Cuthill_Mckee方法:
void renumber_dofs(DoFHandler<2> &dof_handler)
{
DoFRenumbering::Cuthill_McKee(dof_handler);
DynamicSparsityPattern dynamic_sparsity_pattern(dof_handler.n_dofs(),
dof_handler.n_dofs());
DoFTools::make_sparsity_pattern(dof_handler, dynamic_sparsity_pattern);
SparsityPattern sparsity_pattern;
sparsity_pattern.copy_from(dynamic_sparsity_pattern);
std::ofstream out("sparsity_pattern2.svg");
sparsity_pattern.print_svg(out);
}