引言
用於枚舉基函數(形函數)的類稱爲DoFHandler。
要在網格上定義自由度,先要創建一個有限元對象,然後通過DoFHandler::distribute_dofs 函數傳給DoFHandler。(distribute DoFs 代表了枚舉基函數的過程。)DoFHandler 會提供總體裝配信息。
稀疏矩陣
DoFHandler 默認以隨機方式枚舉自由度,因此相應的稀疏矩陣也是隨機排列的。一般來說隨機性不影響求解,但某些預處理例如SSOR在特定排列下會更快些。
程序
網格庫
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/manifold_lib.h>
把自由度關聯到單元上的庫
#include <deal.II/dofs/dof_handler.h>
描述雙線性單元(包括1至3維)的庫
#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>
輸出
#include <fstream>
命名空間
using namespace dealii;
網格生成
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();
}
}
創建DoFHandler。首先要創建一個拉格朗日單元FE_Q,它的唯一參數表示多項式次數,雙線性爲1。接着把它傳給DoFHandler。
void distribute_dofs(DoFHandler<2> &dof_handler)
{
const FE_Q<2> finite_element(1);
dof_handler.distribute_dofs(finite_element);
然後考慮稀疏矩陣。存儲非零元素位置的類是SparsityPattern。這個類有一個毛病,必須先給定單行最大存儲數。二維時可以用DoFHandler::max_couplings_between_dofs()
函數自動獲取,但三維時總是會過分估計。爲此我們可以用一個DynamicSparsityPattern,再複製到SparsityPattern裏。DynamicSparsityPattern 需要輸入矩陣大小。
DynamicSparsityPattern dynamic_sparsity_pattern(dof_handler.n_dofs(),
dof_handler.n_dofs());
用自由度填充DynamicSparsityPattern。
DoFTools::make_sparsity_pattern(dof_handler, dynamic_sparsity_pattern);
最後曲線救國,把位置信息複製到SparsityPattern。
SparsityPattern sparsity_pattern;
sparsity_pattern.copy_from(dynamic_sparsity_pattern);
把SparsityPattern輸出到圖片。
std::ofstream out("sparsity_pattern1.svg");
sparsity_pattern.print_svg(out);