PRISMS-PF  v2.1
matrixFreePDE.h
Go to the documentation of this file.
1 //base class for matrix Free implementation of PDE's
2 #ifndef MATRIXFREEPDE_H
3 #define MATRIXFREEPDE_H
4 
5 // general headers
6 #include <fstream>
7 #include <sstream>
8 #include <iterator>
9 
10 // dealii headers
11 #include <deal.II/base/quadrature.h>
12 #include <deal.II/base/timer.h>
13 #include <deal.II/lac/vector.h>
14 #include <deal.II/lac/constraint_matrix.h>
15 #include <deal.II/fe/fe_system.h>
16 #include <deal.II/fe/fe_q.h>
17 #include <deal.II/fe/fe_values.h>
18 #include <deal.II/grid/tria.h>
19 #include <deal.II/grid/tria_accessor.h>
20 #include <deal.II/grid/tria_iterator.h>
21 #include <deal.II/grid/grid_tools.h>
22 #include <deal.II/dofs/dof_tools.h>
23 #include <deal.II/dofs/dof_handler.h>
24 #include <deal.II/numerics/vector_tools.h>
25 #include <deal.II/lac/parallel_vector.h>
26 #include <deal.II/matrix_free/matrix_free.h>
27 #include <deal.II/matrix_free/fe_evaluation.h>
28 #include <deal.II/base/config.h>
29 #include <deal.II/base/exceptions.h>
30 #include <deal.II/distributed/tria.h>
31 #include <deal.II/distributed/solution_transfer.h>
32 #include <deal.II/grid/manifold_lib.h>
33 
34 // PRISMS headers
35 #include "fields.h"
36 #include "userInputParameters.h"
37 #include "nucleus.h"
38 #include "variableValueContainer.h"
39 #include "variableContainer.h"
41 
42 // define data types
43 #ifndef scalarType
44 typedef dealii::VectorizedArray<double> scalarType;
45 #endif
46 #ifndef vectorType
47 typedef dealii::parallel::distributed::Vector<double> vectorType;
48 #endif
49 
50 //macro for constants
51 #define constV(a) make_vectorized_array(a)
52 
53 //
54 using namespace dealii;
55 //
56 //base class for matrix free PDE's
57 //
58 /**
59  * This is the abstract base class for the matrix free implementation of Parabolic and Elliptic BVP's,
60  * and supports MPI, Threads and Vectorization (Hybrid Parallel).
61  * This class contains the parallel data structures, mesh (referred to as triangulation),
62  * parallel degrees of freedom distribution, constraints, and general utility methods.
63  *
64  * All the physical models in this package inherit this base class.
65  */
66 template <int dim, int degree>
67 class MatrixFreePDE:public Subscriptor
68 {
69  public:
70  /**
71  * Class contructor
72  */
74  ~MatrixFreePDE();
75  /**
76  * Initializes the mesh, degrees of freedom, constraints and data structures using the user provided
77  * inputs in the application parameters file.
78  */
79  virtual void init ();
80 
81  virtual void makeTriangulation(parallel::distributed::Triangulation<dim> &) const;
82 
83  /**
84  * Initializes the data structures for enabling unit tests.
85  *
86  * This method initializes the MatrixFreePDE object with a fixed geometry, discretization and
87  * other custom selected options specifically to help with unit tests, and should not be called
88  * in any of the physical models.
89  */
90  void initForTests();
91 
92  /**
93  * This method implements the time stepping algorithm and invokes the solveIncrement() method.
94  */
95  void solve ();
96  /**
97  * This method essentially converts the MatrixFreePDE object into a matrix object which can be
98  * used with matrix free iterative solvers. Provides the A*x functionality for solving the system of
99  * equations AX=b.
100  */
101  void vmult (vectorType &dst, const vectorType &src) const;
102  /**
103  * Vector of all the physical fields in the problem. Fields are identified by dimentionality (SCALAR/VECTOR),
104  * the kind of PDE (ELLIPTIC/PARABOLIC) used to compute them and a character identifier (e.g.: "c" for composition)
105  * which is used to write the fields to the output files.
106  */
107  std::vector<Field<dim> > fields;
108 
109  void buildFields();
110 
111  // Parallel message stream
112  ConditionalOStream pcout;
113 
114  // Initial conditions function
115  virtual void setInitialCondition(const dealii::Point<dim> &p, const unsigned int index, double & scalar_IC, dealii::Vector<double> & vector_IC) = 0;
116 
117  // Non-uniform boundary conditions function
118  virtual void setNonUniformDirichletBCs(const dealii::Point<dim> &p, const unsigned int index, const unsigned int direction, const double time, double & scalar_BC, dealii::Vector<double> & vector_BC) = 0;
119 
120  protected:
122 
123  unsigned int totalDOFs;
124 
125  // Virtual methods to set the attributes of the primary field variables and the postprocessing field variables
126  //virtual void setVariableAttriubutes() = 0;
127  //virtual void setPostProcessingVariableAttriubutes(){};
129 
130  // Elasticity matrix variables
131  const static unsigned int CIJ_tensor_size = 2*dim-1+dim/3;
132 
133  // Method to reinitialize the mesh, degrees of freedom, constraints and data structures when the mesh is adapted
134  void reinit ();
135 
136  /**
137  * Method to reassign grains when multiple grains are stored in a single order parameter.
138  */
139  void reassignGrains();
140 
141  std::vector<SimplifiedGrainRepresentation<dim>> simplified_grain_representations;
142 
143  /**
144  * Method to solve each time increment of a time-dependent problem. For time-independent problems
145  * this method is called only once. This method solves for all the fields in a staggered manner (one after another)
146  * and also invokes the corresponding solvers: Explicit solver for Parabolic problems, Implicit (matrix-free) solver for Elliptic problems.
147  */
148  virtual void solveIncrement (bool skip_time_dependent);
149  /* Method to write solution fields to vtu and pvtu (parallel) files.
150  *
151  * This method can be enabled/disabled by setting the flag writeOutput to true/false. Also,
152  * the user can select how often the solution files are written by setting the flag
153  * skipOutputSteps in the parameters file.
154  */
155  void outputResults();
156 
157  /*Parallel mesh object which holds information about the FE nodes, elements and parallel domain decomposition
158  */
159  parallel::distributed::Triangulation<dim> triangulation;
160  /*A vector of finite element objects used in a model. For problems with only one primal field,
161  *the size of this vector is one,otherwise the size is the number of primal fields in the problem.
162  */
163  std::vector<FESystem<dim>*> FESet;
164  /*A vector of all the constraint sets in the problem. A constraint set is a map which holds the mapping between the degrees
165  *of freedom and the corresponding degree of freedom constraints. Currently the type of constraints stored are either
166  *Dirichlet boundary conditions or hanging node constraints for adaptive meshes.
167  */
168  std::vector<const ConstraintMatrix*> constraintsDirichletSet, constraintsOtherSet;
169  /*A vector of all the degree of freedom objects is the problem. A degree of freedom object handles the serial/parallel distribution
170  *of the degrees of freedom for all the primal fields in the problem.*/
171  std::vector<const DoFHandler<dim>*> dofHandlersSet;
172 
173  /*A vector of the locally relevant degrees of freedom. Locally relevant degrees of freedom in a parallel implementation is a collection of the
174  *degrees of freedom owned by the current processor and the surrounding ghost nodes which are required for the field computations in this processor.
175  */
176  std::vector<const IndexSet*> locally_relevant_dofsSet;
177  /*Copies of constraintSet elements, but stored as non-const to enable application of constraints.*/
178  std::vector<ConstraintMatrix*> constraintsDirichletSet_nonconst, constraintsOtherSet_nonconst;
179  /*Copies of dofHandlerSet elements, but stored as non-const.*/
180  std::vector<DoFHandler<dim>*> dofHandlersSet_nonconst;
181  /*Copies of locally_relevant_dofsSet elements, but stored as non-const.*/
182  std::vector<IndexSet*> locally_relevant_dofsSet_nonconst;
183  /*Vector all the solution vectors in the problem. In a multi-field problem, each primal field has a solution vector associated with it.*/
184  std::vector<vectorType*> solutionSet;
185  /*Vector all the residual (RHS) vectors in the problem. In a multi-field problem, each primal field has a residual vector associated with it.*/
186  std::vector<vectorType*> residualSet;
187  /*Vector of parallel solution transfer objects. This is used only when adaptive meshing is enabled.*/
188  std::vector<parallel::distributed::SolutionTransfer<dim, vectorType>*> soltransSet;
189 
190  // Objects for vectors
191  DoFHandler<dim>* vector_dofHandler;
192  FESystem<dim>* vector_fe;
193  MatrixFree<dim,double> vector_matrixFreeObject;
194 
195  //matrix free objects
196  /*Object of class MatrixFree<dim>. This is primarily responsible for all the base matrix free functionality of this MatrixFreePDE<dim> class.
197  *Refer to deal.ii documentation of MatrixFree<dim> class for details.
198  */
199  MatrixFree<dim,double> matrixFreeObject;
200  /*Vector to store the inverse of the mass matrix diagonal. Due to the choice of spectral elements with Guass-Lobatto quadrature, the mass matrix is diagonal.*/
202  /*Vector to store the solution increment. This is a temporary vector used during implicit solves of the Elliptic fields.*/
203  vectorType dU_vector, dU_scalar;
204 
205  //matrix free methods
206  /*Current field index*/
207  unsigned int currentFieldIndex;
208  /*Method to compute the inverse of the mass matrix*/
209  void computeInvM();
210 
211 
212  /*AMR methods*/
213  void refineGrid();
214  /*Virtual method to mark the regions to be adaptively refined. This is expected to be provided by the user.*/
215  void adaptiveRefine(unsigned int _currentIncrement);
216  /*Virtual method to define AMR refinement criterion. The default implementation uses the Kelly error estimate for estimative the error function. The user can supply a custom implementation to overload the default implementation.*/
217  virtual void adaptiveRefineCriterion();
218 
219  /*Method to compute the right hand side (RHS) residual vectors*/
220  void computeExplicitRHS();
221  void computeNonexplicitRHS();
222 
223  //virtual methods to be implemented in the derived class
224  /*Method to calculate LHS(implicit solve)*/
225  void getLHS(const MatrixFree<dim,double> &data,
226  vectorType &dst,
227  const vectorType &src,
228  const std::pair<unsigned int,unsigned int> &cell_range) const;
229 
230 
232  void getLaplaceLHS(const MatrixFree<dim,double> &data,
233  vectorType &dst,
234  const vectorType &src,
235  const std::pair<unsigned int,unsigned int> &cell_range) const;
236 
237 
238  void setNonlinearEqInitialGuess();
239  void computeLaplaceRHS(unsigned int fieldIndex);
240  void getLaplaceRHS (const MatrixFree<dim,double> &data,
241  vectorType &dst,
242  const vectorType &src,
243  const std::pair<unsigned int,unsigned int> &cell_range) const;
244 
245 
246  /*Method to calculate RHS (implicit/explicit). This is an abstract method, so every model which inherits MatrixFreePDE<dim> has to implement this method.*/
247  void getExplicitRHS (const MatrixFree<dim,double> &data,
248  std::vector<vectorType*> &dst,
249  const std::vector<vectorType*> &src,
250  const std::pair<unsigned int,unsigned int> &cell_range) const;
251 
252  void getNonexplicitRHS (const MatrixFree<dim,double> &data,
253  std::vector<vectorType*> &dst,
254  const std::vector<vectorType*> &src,
255  const std::pair<unsigned int,unsigned int> &cell_range) const;
256 
257  virtual void explicitEquationRHS(variableContainer<dim,degree,dealii::VectorizedArray<double> > & variable_list,
258  dealii::Point<dim, dealii::VectorizedArray<double> > q_point_loc) const=0;
259 
260  virtual void nonExplicitEquationRHS(variableContainer<dim,degree,dealii::VectorizedArray<double> > & variable_list,
261  dealii::Point<dim, dealii::VectorizedArray<double> > q_point_loc) const=0;
262 
263  virtual void equationLHS(variableContainer<dim,degree,dealii::VectorizedArray<double> > & variable_list,
264  dealii::Point<dim, dealii::VectorizedArray<double> > q_point_loc) const=0;
265 
266  virtual void postProcessedFields(const variableContainer<dim,degree,dealii::VectorizedArray<double> > & variable_list,
267  variableContainer<dim,degree,dealii::VectorizedArray<double> > & pp_variable_list,
268  const dealii::Point<dim, dealii::VectorizedArray<double> > q_point_loc) const {};
269  void computePostProcessedFields(std::vector<vectorType*> &postProcessedSet);
270 
271  void getPostProcessedFields(const dealii::MatrixFree<dim,double> &data,
272  std::vector<vectorType*> &dst,
273  const std::vector<vectorType*> &src,
274  const std::pair<unsigned int,unsigned int> &cell_range);
275 
276  //methods to apply dirichlet BC's
277  /*Map of degrees of freedom to the corresponding Dirichlet boundary conditions, if any.*/
278  std::vector<std::map<dealii::types::global_dof_index, double>*> valuesDirichletSet;
279  /*Virtual method to mark the boundaries for applying Dirichlet boundary conditions. This is usually expected to be provided by the user.*/
280  void markBoundaries(parallel::distributed::Triangulation<dim> &) const;
281  /** Method for applying Dirichlet boundary conditions.*/
282  void applyDirichletBCs();
283 
284  /** Method for applying Neumann boundary conditions.*/
285  void applyNeumannBCs();
286 
287  // Methods to apply periodic BCs
288  void setPeriodicity();
289  void setPeriodicityConstraints(ConstraintMatrix *, const DoFHandler<dim>*) const;
290  void getComponentsWithRigidBodyModes(std::vector<int> &) const;
291  void setRigidBodyModeConstraints(const std::vector<int>, ConstraintMatrix *, const DoFHandler<dim>*) const;
292 
293  //methods to apply initial conditions
294  /*Virtual method to apply initial conditions. This is usually expected to be provided by the user in IBVP (Initial Boundary Value Problems).*/
295 
296  void applyInitialConditions();
297 
298  // --------------------------------------------------------------------------
299  // Methods for saving and loading checkpoints
300  // --------------------------------------------------------------------------
301 
302  void save_checkpoint();
303 
304  void load_checkpoint_triangulation();
305  void load_checkpoint_fields();
306  void load_checkpoint_time_info();
307 
308  void move_file(const std::string&, const std::string&);
309 
310  void verify_checkpoint_file_exists(const std::string filename);
311 
312  // --------------------------------------------------------------------------
313  // Nucleation methods and variables
314  // --------------------------------------------------------------------------
315  // Vector of all the nuclei seeded in the problem
316  std::vector<nucleus<dim> > nuclei;
317 
318  // Method to get a list of new nuclei to be seeded
319  void updateNucleiList();
320  std::vector<nucleus<dim> > getNewNuclei();
321  void getLocalNucleiList(std::vector<nucleus<dim> > & newnuclei) const;
322  void safetyCheckNewNuclei(std::vector<nucleus<dim> > newnuclei, std::vector<unsigned int> & conflict_ids);
323  void refineMeshNearNuclei(std::vector<nucleus<dim> > newnuclei);
324  double weightedDistanceFromNucleusCenter(const dealii::Point<dim,double> center, const std::vector<double> semiaxes, const dealii::Point<dim,double> q_point_loc, const unsigned int var_index) const;
325  dealii::VectorizedArray<double> weightedDistanceFromNucleusCenter(const dealii::Point<dim,double> center, const std::vector<double> semiaxes, const dealii::Point<dim,dealii::VectorizedArray<double> > q_point_loc, const unsigned int var_index) const;
326 
327 
328  // Method to obtain the nucleation probability for an element, nontrival case must be implemented in the subsclass
329  virtual double getNucleationProbability(variableValueContainer, double, dealii::Point<dim>, unsigned int variable_index) const {return 0.0;};
330 
331  //utility functions
332  /*Returns index of given field name if exists, else throw error.*/
333  unsigned int getFieldIndex(std::string _name);
334 
335  std::vector<double> freeEnergyValues;
336  void outputFreeEnergy(const std::vector<double>& freeEnergyValues) const;
337 
338  /*Method to compute the integral of a field.*/
339  void computeIntegral(double& integratedField, int index, std::vector<vectorType*> postProcessedSet);
340 
341  //variables for time dependent problems
342  /*Flag used to see if invM, time stepping in run(), etc are necessary*/
344  /*Flag used to mark problems with Elliptic fields.*/
346 
350  //
351  unsigned int parabolicFieldIndex, ellipticFieldIndex;
352  double currentTime;
353  unsigned int currentIncrement, currentOutput, currentCheckpoint, current_grain_reassignment;
354 
355  /*Timer and logging object*/
356  mutable TimerOutput computing_timer;
357 
358  std::vector<double> integrated_postprocessed_fields;
359 
361 
362  // Methods and variables for integration
364  unsigned int integral_index;
365  dealii::Threads::Mutex assembler_lock;
366 
367  void computeIntegralMF(double& integratedField, int index, const std::vector<vectorType*> postProcessedSet);
368 
369  void getIntegralMF (const MatrixFree<dim,double> &data,
370  std::vector<vectorType*> &dst,
371  const std::vector<vectorType*> &src,
372  const std::pair<unsigned int,unsigned int> &cell_range);
373 
374 };
375 
376 #endif
std::vector< Field< dim > > fields
virtual void postProcessedFields(const variableContainer< dim, degree, dealii::VectorizedArray< double > > &variable_list, variableContainer< dim, degree, dealii::VectorizedArray< double > > &pp_variable_list, const dealii::Point< dim, dealii::VectorizedArray< double > > q_point_loc) const
std::vector< double > freeEnergyValues
ConditionalOStream pcout
std::vector< const IndexSet * > locally_relevant_dofsSet
unsigned int totalDOFs
bool hasExplicitEquation
bool isTimeDependentBVP
bool hasNonExplicitEquation
virtual double getNucleationProbability(variableValueContainer, double, dealii::Point< dim >, unsigned int variable_index) const
vectorType invM
bool has_Dirichlet_BCs
unsigned int integral_index
dealii::parallel::distributed::Vector< double > vectorType
Definition: matrixFreePDE.h:47
FESystem< dim > * vector_fe
double integrated_var
bool generatingInitialGuess
parallel::distributed::Triangulation< dim > triangulation
bool first_integrated_var_output_complete
MatrixFree< dim, double > matrixFreeObject
std::vector< parallel::distributed::SolutionTransfer< dim, vectorType > * > soltransSet
std::vector< std::map< dealii::types::global_dof_index, double > * > valuesDirichletSet
unsigned int currentFieldIndex
std::vector< DoFHandler< dim > * > dofHandlersSet_nonconst
std::vector< ConstraintMatrix * > constraintsOtherSet_nonconst
TimerOutput computing_timer
MatrixFree< dim, double > vector_matrixFreeObject
unsigned int currentOutput
dealii::parallel::distributed::Vector< double > vectorType
Definition: FloodFiller.h:15
std::vector< double > integrated_postprocessed_fields
vectorType dU_vector
std::vector< const ConstraintMatrix * > constraintsOtherSet
double currentTime
std::vector< FESystem< dim > * > FESet
std::vector< const DoFHandler< dim > * > dofHandlersSet
std::vector< vectorType * > residualSet
unsigned int parabolicFieldIndex
dealii::Threads::Mutex assembler_lock
std::vector< nucleus< dim > > nuclei
std::vector< IndexSet * > locally_relevant_dofsSet_nonconst
variableAttributeLoader var_attributes
std::vector< vectorType * > solutionSet
std::vector< SimplifiedGrainRepresentation< dim > > simplified_grain_representations
dealii::VectorizedArray< double > scalarType
Definition: matrixFreePDE.h:44
userInputParameters< dim > userInputs
DoFHandler< dim > * vector_dofHandler