PRISMS-PF  v2.1
init.cc
Go to the documentation of this file.
1 // init() method for MatrixFreePDE class
2 
3 #include "../../include/matrixFreePDE.h"
4 #include "../../include/varBCs.h"
5 #include <deal.II/grid/grid_generator.h>
6 
7  //populate with fields and setup matrix free system
8 template <int dim, int degree>
10  computing_timer.enter_section("matrixFreePDE: initialization");
11 
12  //creating mesh
13 
14  pcout << "creating problem mesh...\n";
15  // Create the coarse mesh and mark the boundaries
16  makeTriangulation(triangulation);
17 
18  // Set which (if any) faces of the triangulation are periodic
19  setPeriodicity();
20 
21  // If resuming from a checkpoint, load the refined triangulation, otherwise refine globally per the parameters.in file
22  if (userInputs.resume_from_checkpoint){
23  load_checkpoint_triangulation();
24  }
25  else {
26  // Do the initial global refinement
27  triangulation.refine_global (userInputs.refine_factor);
28  }
29 
30 
31  // Write out the size of the computational domain and the total number of elements
32  if (dim < 3){
33  pcout << "problem dimensions: " << userInputs.domain_size[0] << "x" << userInputs.domain_size[1] << std::endl;
34  }
35  else {
36  pcout << "problem dimensions: " << userInputs.domain_size[0] << "x" << userInputs.domain_size[1] << "x" << userInputs.domain_size[2] << std::endl;
37  }
38  pcout << "number of elements: " << triangulation.n_global_active_cells() << std::endl;
39  pcout << std::endl;
40 
41  // Setup system
42  pcout << "initializing matrix free object\n";
43  totalDOFs=0;
44  for(typename std::vector<Field<dim> >::iterator it = fields.begin(); it != fields.end(); ++it){
45  currentFieldIndex=it->index;
46 
47  char buffer[100];
48 
49  //print to std::out
50  std::string var_type;
51  if (it->pdetype == EXPLICIT_TIME_DEPENDENT){
52  var_type = "EXPLICIT_TIME_DEPENDENT";
53  }
54  else if (it->pdetype == IMPLICIT_TIME_DEPENDENT){
55  var_type = "IMPLICIT_TIME_DEPENDENT";
56  }
57  else if (it->pdetype == TIME_INDEPENDENT){
58  var_type = "TIME_INDEPENDENT";
59  }
60  else if (it->pdetype == AUXILIARY){
61  var_type = "AUXILIARY";
62  }
63 
64  sprintf(buffer,"initializing finite element space P^%u for %9s:%6s field '%s'\n", \
65  degree, \
66  var_type.c_str(), \
67  (it->type==SCALAR ? "SCALAR":"VECTOR"), \
68  it->name.c_str());
69  pcout << buffer;
70 
71  // Check if any time dependent fields present (note: I should get rid of parabolicFieldIndex and ellipticFieldIndex, they only work if there is at max one of each)
72  if (it->pdetype==EXPLICIT_TIME_DEPENDENT){
73  isTimeDependentBVP=true;
74  parabolicFieldIndex=it->index;
75  hasExplicitEquation=true;
76  }
77  else if (it->pdetype==IMPLICIT_TIME_DEPENDENT){
78  isTimeDependentBVP=true;
79  ellipticFieldIndex=it->index;
80  hasNonExplicitEquation=true;
81  std::cerr << "PRISMS-PF Error: IMPLICIT_TIME_DEPENDENT equation types are not currently supported" << std::endl;
82  abort();
83  }
84  else if (it->pdetype==AUXILIARY){
85  parabolicFieldIndex=it->index;
86  ellipticFieldIndex=it->index;
87  hasNonExplicitEquation=true;
88  }
89  else if (it->pdetype==TIME_INDEPENDENT){
90  isEllipticBVP=true;
91  ellipticFieldIndex=it->index;
92  hasNonExplicitEquation=true;
93  }
94 
95  //create FESystem
96  FESystem<dim>* fe;
97 
98  if (it->type==SCALAR){
99  fe=new FESystem<dim>(FE_Q<dim>(QGaussLobatto<1>(degree+1)),1);
100  }
101  else if (it->type==VECTOR){
102  fe=new FESystem<dim>(FE_Q<dim>(QGaussLobatto<1>(degree+1)),dim);
103  }
104  else{
105  pcout << "\nmatrixFreePDE.h: unknown field type\n";
106  exit(-1);
107  }
108  FESet.push_back(fe);
109 
110  //distribute DOFs
111  DoFHandler<dim>* dof_handler;
112 
113  dof_handler=new DoFHandler<dim>(triangulation);
114  dofHandlersSet.push_back(dof_handler);
115  dofHandlersSet_nonconst.push_back(dof_handler);
116 
117  dof_handler->distribute_dofs (*fe);
118  totalDOFs+=dof_handler->n_dofs();
119 
120  // Extract locally_relevant_dofs
121  IndexSet* locally_relevant_dofs;
122 
123  locally_relevant_dofs=new IndexSet;
124  locally_relevant_dofsSet.push_back(locally_relevant_dofs);
125  locally_relevant_dofsSet_nonconst.push_back(locally_relevant_dofs);
126 
127  locally_relevant_dofs->clear();
128  DoFTools::extract_locally_relevant_dofs (*dof_handler, *locally_relevant_dofs);
129 
130  // Create constraints
131  ConstraintMatrix *constraintsDirichlet, *constraintsOther;
132 
133  constraintsDirichlet=new ConstraintMatrix; constraintsDirichletSet.push_back(constraintsDirichlet);
134  constraintsDirichletSet_nonconst.push_back(constraintsDirichlet);
135  constraintsOther=new ConstraintMatrix; constraintsOtherSet.push_back(constraintsOther);
136  constraintsOtherSet_nonconst.push_back(constraintsOther);
137  valuesDirichletSet.push_back(new std::map<dealii::types::global_dof_index, double>);
138 
139  constraintsDirichlet->clear(); constraintsDirichlet->reinit(*locally_relevant_dofs);
140  constraintsOther->clear(); constraintsOther->reinit(*locally_relevant_dofs);
141 
142  // Get hanging node constraints
143  DoFTools::make_hanging_node_constraints (*dof_handler, *constraintsOther);
144 
145  // Add a constraint to fix the value at the origin to zero if all BCs are zero-derivative or periodic
146  std::vector<int> rigidBodyModeComponents;
147  //getComponentsWithRigidBodyModes(rigidBodyModeComponents);
148  //setRigidBodyModeConstraints(rigidBodyModeComponents,constraintsOther,dof_handler);
149 
150  // Get constraints for periodic BCs
151  setPeriodicityConstraints(constraintsOther,dof_handler);
152 
153  // Check if Dirichlet BCs are used
154  has_Dirichlet_BCs = false;
155  for (unsigned int i=0; i<fields.size(); i++){
156  for (unsigned int direction = 0; direction < 2*dim; direction++){
157  if (userInputs.BC_list[i].var_BC_type[direction] == DIRICHLET){
158  has_Dirichlet_BCs = true;
159  break;
160  }
161  }
162  }
163 
164  // Get constraints for Dirichlet BCs
165  applyDirichletBCs();
166 
167  constraintsDirichlet->close();
168  constraintsOther->close();
169 
170  // Store Dirichlet BC DOF's
171  valuesDirichletSet[it->index]->clear();
172  for (types::global_dof_index i=0; i<dof_handler->n_dofs(); i++){
173  if (locally_relevant_dofs->is_element(i)){
174  if (constraintsDirichlet->is_constrained(i)){
175  (*valuesDirichletSet[it->index])[i] = constraintsDirichlet->get_inhomogeneity(i);
176  }
177  }
178  }
179 
180  sprintf(buffer, "field '%2s' DOF : %u (Constraint DOF : %u)\n", \
181  it->name.c_str(), dof_handler->n_dofs(), constraintsDirichlet->n_constraints());
182  pcout << buffer;
183  }
184  pcout << "total DOF : " << totalDOFs << std::endl;
185 
186  // Setup the matrix free object
187  typename MatrixFree<dim,double>::AdditionalData additional_data;
188  // The member "mpi_communicator" was removed in deal.II version 8.5 but is required before it
189  #if (DEAL_II_VERSION_MAJOR < 9 && DEAL_II_VERSION_MINOR < 5)
190  additional_data.mpi_communicator = MPI_COMM_WORLD;
191  #endif
192  additional_data.tasks_parallel_scheme = MatrixFree<dim,double>::AdditionalData::partition_partition;
193  //additional_data.tasks_parallel_scheme = MatrixFree<dim,double>::AdditionalData::none;
194  additional_data.mapping_update_flags = (update_values | update_gradients | update_JxW_values | update_quadrature_points);
195  QGaussLobatto<1> quadrature (degree+1);
196  matrixFreeObject.clear();
197  matrixFreeObject.reinit (dofHandlersSet, constraintsOtherSet, quadrature, additional_data);
198 
199  bool dU_scalar_init = false;
200  bool dU_vector_init = false;
201 
202  // Setup solution vectors
203  pcout << "initializing parallel::distributed residual and solution vectors\n";
204  for(unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
205  vectorType *U, *R;
206 
207  U=new vectorType; R=new vectorType;
208  solutionSet.push_back(U); residualSet.push_back(R);
209  matrixFreeObject.initialize_dof_vector(*R, fieldIndex); *R=0;
210 
211  matrixFreeObject.initialize_dof_vector(*U, fieldIndex); *U=0;
212 
213  // Initializing temporary dU vector required for implicit solves of the elliptic equation.
214  if (fields[fieldIndex].pdetype==TIME_INDEPENDENT || fields[fieldIndex].pdetype==IMPLICIT_TIME_DEPENDENT || (fields[fieldIndex].pdetype==AUXILIARY && userInputs.var_nonlinear[fieldIndex])){
215  if (fields[fieldIndex].type == SCALAR){
216  if (dU_scalar_init == false){
217  matrixFreeObject.initialize_dof_vector(dU_scalar, fieldIndex);
218  dU_scalar_init = true;
219  }
220  }
221  else {
222  if (dU_vector_init == false){
223  matrixFreeObject.initialize_dof_vector(dU_vector, fieldIndex);
224  dU_vector_init = true;
225  }
226  }
227  }
228  }
229 
230  //check if time dependent BVP and compute invM
231  if (isTimeDependentBVP){
232  computeInvM();
233  }
234 
235  // Apply the initial conditions to the solution vectors
236  // The initial conditions are re-applied below in the "adaptiveRefine" function so that the mesh can
237  // adapt based on the initial conditions.
238  if (userInputs.resume_from_checkpoint){
239  load_checkpoint_fields();
240  }
241  else {
242  applyInitialConditions();
243  }
244 
245 
246  // Create new solution transfer sets (needed for the "refineGrid" call, might be able to move this elsewhere)
247  soltransSet.clear();
248  for(unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
249  soltransSet.push_back(new parallel::distributed::SolutionTransfer<dim, vectorType>(*dofHandlersSet_nonconst[fieldIndex]));
250  }
251 
252  // Ghost the solution vectors. Also apply the constraints (if any) on the solution vectors
253  for(unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
254  constraintsDirichletSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
255  constraintsOtherSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
256  solutionSet[fieldIndex]->update_ghost_values();
257  }
258 
259  // If not resuming from a checkpoint, check and perform adaptive mesh refinement, which reinitializes the system with the new mesh
260  if (!userInputs.resume_from_checkpoint){
261  adaptiveRefine(0);
262  }
263 
264  // If resuming from a checkpoint, load the proper starting increment and time
265  if (userInputs.resume_from_checkpoint){
266  load_checkpoint_time_info();
267  }
268 
269  computing_timer.exit_section("matrixFreePDE: initialization");
270 }
271 
272 template <int dim, int degree>
273  void MatrixFreePDE<dim,degree>::makeTriangulation(parallel::distributed::Triangulation<dim> & tria) const{
274  if (dim == 3){
275  GridGenerator::subdivided_hyper_rectangle (tria, userInputs.subdivisions, Point<dim>(), Point<dim>(userInputs.domain_size[0],userInputs.domain_size[1],userInputs.domain_size[2]));
276  }
277  else if (dim == 2){
278  GridGenerator::subdivided_hyper_rectangle (tria, userInputs.subdivisions, Point<dim>(), Point<dim>(userInputs.domain_size[0],userInputs.domain_size[1]));
279  }
280  else {
281  GridGenerator::subdivided_hyper_rectangle (tria, userInputs.subdivisions, Point<dim>(), Point<dim>(userInputs.domain_size[0]));
282  }
283 
284  // Mark boundaries for applying the boundary conditions
285  markBoundaries(tria);
286 
287  }
288 
289 #include "../../include/matrixFreePDE_template_instantiations.h"
virtual void makeTriangulation(parallel::distributed::Triangulation< dim > &) const
Definition: init.cc:273
Definition: fields.h:9
dealii::parallel::distributed::Vector< double > vectorType
Definition: FloodFiller.h:15
virtual void init()
Definition: init.cc:9