phaseflow
FEM solver for the Navier-Stokes-Boussinesq equations coupled with enthalpy-based phase change
 All Classes Namespaces Files Functions Variables Macros Pages
phaseflow.h
Go to the documentation of this file.
1  /* Phaseflow solves the Navier-Stokes-Boussinesq equations coupled with an energy equation in a phase-change material domain
2  *
3  * Originally extended from the convection-diffusion solver peclet, which was based on deal.II Tutorial 26 by Wolfgang Bangerth, Texas A&M University, 2013
4  *
5  * Some of the more notable extensions include:
6  * - Step time with Newton iterations; each Newton iteration requires a linear system solve
7  * - Assembles Newton linearized differential of the Navier-Stokes-Boussinesq equation with latent heat of phase-change
8  * - Supports time-dependent non-zero Dirichlet and Neumann boundary condition
9  * - Re-designed parmameter handling
10  * - Generalized boundary condition handling via the parameter input file
11  * - Writes FEFieldFunction to disk, and can read it from disk to initialize a restart
12  * - Extended the FEFieldFunction class for extrapolation
13  * - Added verification via Method of Manufactured Solutions (MMS) with error table based on approach from Tutorial 7
14  * - Added test suite using ctest and the standard deal.II approach
15  * - Added a parameteric sphere-cylinder grid
16  * - Added a boundary grid refinement routine
17  */
18 #include <deal.II/base/utilities.h>
19 #include <deal.II/base/quadrature_lib.h>
20 #include <deal.II/base/function.h>
21 #include <deal.II/base/logstream.h>
22 #include <deal.II/lac/vector.h>
23 #include <deal.II/lac/full_matrix.h>
24 #include <deal.II/lac/dynamic_sparsity_pattern.h>
25 #include <deal.II/lac/sparse_matrix.h>
26 #include <deal.II/lac/solver_cg.h>
27 #include <deal.II/lac/solver_bicgstab.h>
28 #include <deal.II/lac/solver_gmres.h>
29 #include <deal.II/lac/precondition.h>
30 #include <deal.II/lac/constraint_matrix.h>
31 #include <deal.II/grid/tria.h>
32 #include <deal.II/grid/grid_generator.h>
33 #include <deal.II/grid/grid_refinement.h>
34 #include <deal.II/grid/tria_accessor.h>
35 #include <deal.II/grid/tria_iterator.h>
36 #include <deal.II/dofs/dof_handler.h>
37 #include <deal.II/dofs/dof_renumbering.h>
38 #include <deal.II/dofs/dof_accessor.h>
39 #include <deal.II/dofs/dof_tools.h>
40 #include <deal.II/fe/fe_q.h>
41 #include <deal.II/fe/fe_system.h>
42 #include <deal.II/fe/fe_values.h>
43 #include <deal.II/numerics/vector_tools.h>
44 #include <deal.II/numerics/matrix_tools.h>
45 #include <deal.II/numerics/solution_transfer.h>
46 #include <deal.II/numerics/error_estimator.h>
47 #include <deal.II/numerics/fe_field_function.h>
48 #include <deal.II/base/table_handler.h>
49 
50 #include <iostream>
51 #include <functional>
52 
53 #include <assert.h>
54 #include <deal.II/grid/manifold_lib.h>
55 #include <deal.II/grid/tria_boundary_lib.h>
56 #include <deal.II/base/parsed_function.h>
57 #include <deal.II/lac/sparse_direct.h>
58 
59 #include "my_grid_generator.h"
60 #include "output.h"
61 
62 #include "pf_parameters.h"
63 
64 #include "pf_global_parameters.h"
65 
66 namespace Phaseflow
67 {
68  using namespace dealii;
69 
70  template<int dim>
71  class Phaseflow
72  {
73  public:
74 
75  Phaseflow();
77  void init(std::string file_path);
78  void run(const std::string parameter_file = "");
79 
80  private:
81 
82  void create_coarse_grid();
83 
84  void setup_system();
85 
86  void assemble_system();
87 
88  void interpolate_boundary_values(
89  Function<dim>* function,
90  std::map<types::global_dof_index, double> &boundary_values) const;
91 
92  void apply_boundary_values_and_constraints();
93 
94  void solve_linear_system();
95 
96  void step_newton();
97 
98  bool solve_nonlinear_problem();
99 
100  void set_time_step_size(double new_size);
101 
102  void step_time();
103 
104  void write_solution();
105 
106  Triangulation<dim> triangulation;
107 
108  FESystem<dim,dim> fe;
109 
110  const FEValuesExtractors::Vector velocity_extractor;
111 
112  const FEValuesExtractors::Scalar pressure_extractor;
113 
114  const FEValuesExtractors::Scalar temperature_extractor;
115 
116  DoFHandler<dim> dof_handler;
117 
118  ConstraintMatrix constraints;
119 
120  SparsityPattern sparsity_pattern;
121 
122  SparseMatrix<double> system_matrix;
123 
124  Vector<double> solution;
125 
126  Vector<double> newton_residual;
127 
128  Vector<double> newton_solution;
129 
130  Vector<double> old_solution;
131 
132  Vector<double> old_newton_solution;
133 
134  Vector<double> system_rhs;
135 
136  double time;
137 
138  double new_time;
139 
141 
142  unsigned int time_step_counter;
143 
144  unsigned int boundary_count;
145 
147  std::vector<unsigned int> manifold_ids;
148 
150  std::vector<std::string> manifold_descriptors;
151 
152  Functions::ParsedFunction<dim> source_function;
153 
154  Functions::ParsedFunction<dim> initial_values_function;
155 
156  Functions::ParsedFunction<dim> boundary_function;
157 
158  Functions::ParsedFunction<dim> exact_solution_function;
159 
160  void append_verification_table();
161 
162  void write_verification_table();
163 
164  TableHandler verification_table;
165 
166  std::string verification_table_file_name = "verification_table.txt";
167 
168  };
169 
170  template<int dim>
172  :
173  fe(FE_Q<dim>(SCALAR_DEGREE + 1), dim, // velocity
174  FE_Q<dim>(SCALAR_DEGREE), 1, // pressure
175  FE_Q<dim>(SCALAR_DEGREE), 1), // temperature
176  velocity_extractor(0),
177  pressure_extractor(dim),
178  temperature_extractor(dim + 1),
179  dof_handler(this->triangulation),
180  source_function(dim + 2),
181  initial_values_function(dim + 2),
182  boundary_function(dim + 2),
183  exact_solution_function(dim + 2)
184  {}
185 
186  #include "pf_system.h"
187 
189 
190  #include "pf_step_time.h"
191 
192  #include "pf_output.h"
193 
194  #include "pf_verification.h"
195 
196  template<int dim>
197  void Phaseflow<dim>::run(const std::string parameter_file)
198  {
199 
200  // Clean up the files in the working directory
201 
202  if (this->params.verification.enabled)
203  {
204  std::remove(this->verification_table_file_name.c_str());
205  }
206 
207  /*
208  Working with deal.II's Function class has been interesting, and I'm
209  sure many of my choices are unorthodox. The most important lesson learned has been that
210  a Function<dim>* can point to any class derived from Function<dim>. The general design pattern
211  then is to instantitate all of the functions that might be needed, and then to point to the ones
212  actually being used.
213  */
214 
215  this->params = Parameters::read<dim>(
216  parameter_file,
217  this->source_function,
218  this->initial_values_function,
219  this->boundary_function,
220  this->exact_solution_function);
221 
223  this->triangulation,
224  this->manifold_ids,
225  this->manifold_descriptors,
226  this->boundary_count,
227  this->params.geometry.grid_name,
228  params.geometry.sizes);
229 
230  /* Attach manifolds for exact geometry
231 
232  For now this only supports a single spherical manifold centered at the origin.
233 
234  */
235  SphericalManifold<dim> spherical_manifold;
236 
237  for (unsigned int i = 0; i < this->manifold_ids.size(); i++)
238  {
239  if (this->manifold_descriptors[i] == "spherical")
240  {
241  this->triangulation.set_manifold(this->manifold_ids[i], spherical_manifold);
242  }
243  }
244 
245  // Run initial refinement cycles
246 
247  this->triangulation.refine_global(this->params.refinement.initial_global_cycles);
248 
249  // Initialize the linear system
250 
251  this->setup_system();
252 
253  this->time = 0.;
254 
255  this->set_time_step_size(this->params.time.initial_step_size);
256 
257  this->time_step_counter = 0;
258 
259  VectorTools::interpolate(
260  this->dof_handler,
261  this->initial_values_function,
262  this->solution);
263 
264  this->write_solution();
265 
266  for (this->time_step_counter = 1; this->time_step_counter < this->params.time.max_steps; ++this->time_step_counter)
267  {
268  if (this->time > (this->params.time.end*(1. - EPSILON) - EPSILON))
269  {
270  break;
271  }
272 
273  this->step_time();
274 
275  this->write_solution();
276 
277  if (this->params.verification.enabled)
278  {
279  this->append_verification_table();
280  }
281 
282  if (this->params.time.stop_when_steady)
283  {
284  Vector<double> time_residual = this->solution; // There is evidently no Vector<Number> - Vector<Number> method.
285  time_residual -= this->old_solution;
286 
287  double unsteadiness = time_residual.l2_norm()/this->solution.l2_norm();
288 
289  std::cout << "Unsteadiness, || w_{n+1} - w_n || / || w_{n+1} || = " << unsteadiness << std::endl;
290 
291  if (unsteadiness < this->params.time.steady_tolerance)
292  {
293  std::cout << "Reached steady state." << std::endl;
294  break;
295  }
296 
297  }
298 
299  }
300 
301  /* Clean up.
302 
303  Manifolds must be detached from Triangulations before leaving this scope.
304 
305  */
306  this->triangulation.set_manifold(0);
307 
308  }
309 
310 }
ConstraintMatrix constraints
Definition: phaseflow.h:118
std::vector< unsigned int > manifold_ids
Definition: phaseflow.h:147
const FEValuesExtractors::Scalar temperature_extractor
Definition: phaseflow.h:114
DoFHandler< dim > dof_handler
Definition: phaseflow.h:116
Parameters::StructuredParameters params
Definition: phaseflow.h:76
TableHandler verification_table
Definition: phaseflow.h:164
double new_time
Definition: phaseflow.h:138
Vector< double > solution
Definition: phaseflow.h:124
const unsigned int SCALAR_DEGREE
Definition: pf_global_parameters.h:22
unsigned int boundary_count
Definition: phaseflow.h:144
Functions::ParsedFunction< dim > boundary_function
Definition: phaseflow.h:156
const double EPSILON
Definition: pf_global_parameters.h:24
double time
Definition: phaseflow.h:136
const FEValuesExtractors::Scalar pressure_extractor
Definition: phaseflow.h:112
void create_coarse_grid(Triangulation< dim > &triangulation, std::vector< unsigned int > &manifold_ids, std::vector< std::string > &manifold_descriptors, unsigned int &boundary_count, const std::string grid_name, const std::vector< double > sizes)
Definition: my_grid_generator.h:17
Vector< double > system_rhs
Definition: phaseflow.h:134
Vector< double > old_solution
Definition: phaseflow.h:130
Phaseflow()
Definition: phaseflow.h:171
Vector< double > newton_solution
Definition: phaseflow.h:128
std::vector< std::string > manifold_descriptors
Definition: phaseflow.h:150
Functions::ParsedFunction< dim > source_function
Definition: phaseflow.h:152
Vector< double > newton_residual
Definition: phaseflow.h:126
double time_step_size
Definition: phaseflow.h:140
const FEValuesExtractors::Vector velocity_extractor
Definition: phaseflow.h:110
Definition: pf_parameters.h:119
SparsityPattern sparsity_pattern
Definition: phaseflow.h:120
FESystem< dim, dim > fe
Definition: phaseflow.h:108
Triangulation< dim > triangulation
Definition: phaseflow.h:106
SparseMatrix< double > system_matrix
Definition: phaseflow.h:122
unsigned int time_step_counter
Definition: phaseflow.h:142
Functions::ParsedFunction< dim > exact_solution_function
Definition: phaseflow.h:158
Vector< double > old_newton_solution
Definition: phaseflow.h:132
Functions::ParsedFunction< dim > initial_values_function
Definition: phaseflow.h:154
Definition: phaseflow.h:71