PRISMS-PF  v2.1
boundaryConditions.cc
Go to the documentation of this file.
1 //methods to apply boundary conditons
2 
3 #include "../../include/matrixFreePDE.h"
4 #include "../../include/vectorBCFunction.h"
5 #include "../../include/varBCs.h"
6 #include "../../include/nonUniformDirichletBC.h"
7 
8 // =================================================================================
9 // Methods to apply non-zero Neumann BCs
10 // =================================================================================
11 template <int dim, int degree>
13  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14  // NOTE: Currently this function doesn't work and it's call is commented out in solveIncrement.
15  // The result is off by almost exactly a factor of 100,000. I don't know what the issue is.
16  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
17 
18  // Check to the BC for the current field
19  unsigned int starting_BC_list_index = 0;
20  for (unsigned int i=0; i<currentFieldIndex; i++){
21  if (userInputs.var_type[i] == SCALAR){
22  starting_BC_list_index++;
23  }
24  else {
25  starting_BC_list_index+=dim;
26  }
27  }
28 
29  if (userInputs.var_type[currentFieldIndex] == SCALAR){
30  for (unsigned int direction = 0; direction < 2*dim; direction++){
31  if (userInputs.BC_list[starting_BC_list_index].var_BC_type[direction] == NEUMANN){
32 
33  typename DoFHandler<dim>::active_cell_iterator cell = dofHandlersSet[0]->begin_active(), endc = dofHandlersSet[0]->end();
34  FESystem<dim>* fe= FESet[currentFieldIndex];
35  QGaussLobatto<dim-1> face_quadrature_formula(degree+1);
36  FEFaceValues<dim> fe_face_values (*fe, face_quadrature_formula, update_values | update_JxW_values);
37  const unsigned int n_face_q_points = face_quadrature_formula.size(), dofs_per_cell=fe->dofs_per_cell;
38  Vector<double> cell_rhs(dofs_per_cell);
39  std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
40 
41  // Loop over each face on a boundary
42  for (;cell!=endc; ++cell){
43  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f){
44  if (cell->face(f)->at_boundary()){
45  if (cell->face(f)->boundary_id() == direction){
46  fe_face_values.reinit (cell, f);
47  cell_rhs=0.0;
48  for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point){
49  double neumann_value = userInputs.BC_list[starting_BC_list_index].var_BC_val[direction];
50  for (unsigned int i=0; i<dofs_per_cell; ++i){
51  cell_rhs(i) += (neumann_value * fe_face_values.shape_value(i,q_point) * fe_face_values.JxW(q_point));
52  }
53  }
54  cell->get_dof_indices (local_dof_indices);
55  //assemble
56  for (unsigned int i=0; i<dofs_per_cell; ++i){
57  (*(residualSet[currentFieldIndex]))[local_dof_indices[i]] += cell_rhs(i);
58  }
59  }
60  }
61  }
62  }
63  }
64 
65  }
66  }
67 
68 }
69 
70 
71 // =================================================================================
72 // Methods to apply non-zero Dirichlet BCs
73 // =================================================================================
74 template <int dim, int degree>
76  // First, get the variable index of the current field
77  unsigned int starting_BC_list_index = 0;
78 
79  for (unsigned int i=0; i<currentFieldIndex; i++){
80 
81  if (userInputs.var_type[i] == SCALAR){
82  starting_BC_list_index++;
83  }
84  else {
85  starting_BC_list_index+=dim;
86  }
87  }
88 
89  if (userInputs.var_type[currentFieldIndex] == SCALAR){
90  for (unsigned int direction = 0; direction < 2*dim; direction++){
91  if (userInputs.BC_list[starting_BC_list_index].var_BC_type[direction] == DIRICHLET){
92  VectorTools::interpolate_boundary_values (*dofHandlersSet[currentFieldIndex],\
93  direction, ConstantFunction<dim>(userInputs.BC_list[starting_BC_list_index].var_BC_val[direction],1), *(ConstraintMatrix*) \
94  constraintsDirichletSet[currentFieldIndex]);
95 
96  }
97  else if (userInputs.BC_list[starting_BC_list_index].var_BC_type[direction] == NON_UNIFORM_DIRICHLET){
98  VectorTools::interpolate_boundary_values (*dofHandlersSet[currentFieldIndex],\
99  direction, NonUniformDirichletBC<dim,degree>(currentFieldIndex,direction,currentTime,this), *(ConstraintMatrix*) \
100  constraintsDirichletSet[currentFieldIndex]);
101  }
102  }
103  }
104  else {
105  for (unsigned int direction = 0; direction < 2*dim; direction++){
106 
107  std::vector<double> BC_values;
108  for (unsigned int component=0; component < dim; component++){
109  BC_values.push_back(userInputs.BC_list[starting_BC_list_index+component].var_BC_val[direction]);
110  }
111 
112  std::vector<bool> mask;
113  for (unsigned int component=0; component < dim; component++){
114  if (userInputs.BC_list[starting_BC_list_index+component].var_BC_type[direction] == DIRICHLET){
115  mask.push_back(true);
116  }
117  else {
118  mask.push_back(false);
119  }
120  }
121 
122  VectorTools::interpolate_boundary_values (*dofHandlersSet[currentFieldIndex],\
123  direction, vectorBCFunction<dim>(BC_values), *(ConstraintMatrix*) \
124  constraintsDirichletSet[currentFieldIndex],mask);
125 
126  // Mask again, this time for non-uniform Dirichlet BCs
127  mask.clear();
128  for (unsigned int component=0; component < dim; component++){
129  if (userInputs.BC_list[starting_BC_list_index+component].var_BC_type[direction] == NON_UNIFORM_DIRICHLET){
130  mask.push_back(true);
131  }
132  else {
133  mask.push_back(false);
134  }
135  }
136 
137  // VectorTools::interpolate_boundary_values (*dofHandlersSet[currentFieldIndex],\
138  // direction, NonUniformDirichletBC<dim,degree>(currentFieldIndex,direction,currentTime,this), *(ConstraintMatrix*) \
139  // constraintsDirichletSet[currentFieldIndex],mask);
140  VectorTools::interpolate_boundary_values (*dofHandlersSet[currentFieldIndex],\
141  direction, NonUniformDirichletBCVector<dim,degree>(currentFieldIndex,direction,currentTime,this), *(ConstraintMatrix*) \
142  constraintsDirichletSet[currentFieldIndex],mask);
143 
144 
145  }
146  }
147 }
148 
149 // Based on the contents of BC_list, mark faces on the triangulation as periodic
150 template <int dim, int degree>
152  std::vector<GridTools::PeriodicFacePair<typename parallel::distributed::Triangulation<dim>::cell_iterator> > periodicity_vector;
153  for (int i=0; i<dim; ++i){
154  bool periodic_pair = false;
155  for (unsigned int field_num=0; field_num < userInputs.BC_list.size(); field_num++){
156  if (userInputs.BC_list[field_num].var_BC_type[2*i] == PERIODIC){
157  periodic_pair = true;
158  }
159  }
160  if (periodic_pair == true){
161  GridTools::collect_periodic_faces(triangulation, /*b_id1*/ 2*i, /*b_id2*/ 2*i+1,
162  /*direction*/ i, periodicity_vector);
163  }
164  }
165 
166  triangulation.add_periodicity(periodicity_vector);
167  pcout << "periodic facepairs: " << periodicity_vector.size() << std::endl;
168 }
169 
170 // Set constraints to enforce periodic boundary conditions
171 template <int dim, int degree>
172 void MatrixFreePDE<dim,degree>::setPeriodicityConstraints(ConstraintMatrix * constraints, const DoFHandler<dim>* dof_handler) const {
173  // First, get the variable index of the current field
174  unsigned int starting_BC_list_index = 0;
175  for (unsigned int i=0; i<currentFieldIndex; i++){
176  if (userInputs.var_type[i] == SCALAR){
177  starting_BC_list_index++;
178  }
179  else {
180  starting_BC_list_index+=dim;
181  }
182  }
183 
184  std::vector<GridTools::PeriodicFacePair<typename DoFHandler<dim>::cell_iterator> > periodicity_vector;
185  for (int i=0; i<dim; ++i){
186  if (userInputs.BC_list[starting_BC_list_index].var_BC_type[2*i] == PERIODIC){
187  GridTools::collect_periodic_faces(*dof_handler, /*b_id1*/ 2*i, /*b_id2*/ 2*i+1,
188  /*direction*/ i, periodicity_vector);
189  }
190  }
191  DoFTools::make_periodicity_constraints<DoFHandler<dim> >(periodicity_vector, *constraints);
192 }
193 
194 // Determine which (if any) components of the current field have rigid body modes (i.e no Dirichlet BCs) if the
195 // equation is elliptic
196 template <int dim, int degree>
197 void MatrixFreePDE<dim,degree>::getComponentsWithRigidBodyModes( std::vector<int> & rigidBodyModeComponents) const {
198  // Rigid body modes only matter for elliptic equations
199  if (userInputs.var_eq_type[currentFieldIndex] == IMPLICIT_TIME_DEPENDENT || userInputs.var_eq_type[currentFieldIndex] == TIME_INDEPENDENT){
200 
201  // First, get the variable index of the current field
202  unsigned int starting_BC_list_index = 0;
203  for (unsigned int i=0; i<currentFieldIndex; i++){
204  if (userInputs.var_type[i] == SCALAR){
205  starting_BC_list_index++;
206  }
207  else {
208  starting_BC_list_index+=dim;
209  }
210  }
211 
212  // Get number of components of the field
213  unsigned int num_components = 1;
214  if (userInputs.var_type[currentFieldIndex] == VECTOR){
215  num_components = dim;
216  }
217 
218  // Loop over each component and determine if it has a rigid body mode (i.e. no Dirichlet BCs)
219  for (unsigned int component=0; component < num_components; component++){
220  bool rigidBodyMode = true;
221  for (unsigned int direction = 0; direction < 2*dim; direction++){
222 
223  if (userInputs.BC_list[starting_BC_list_index+component].var_BC_type[direction] == DIRICHLET){
224  rigidBodyMode = false;
225  }
226 
227  }
228  // If the component has a rigid body mode, add it to the list
229  if (rigidBodyMode == true){
230  rigidBodyModeComponents.push_back(component);
231  }
232  }
233  }
234 }
235 
236 // Set constraints to pin the solution if there are no Dirichlet BCs for a component of a variable in an elliptic equation
237 template <int dim, int degree>
238 void MatrixFreePDE<dim,degree>::setRigidBodyModeConstraints(const std::vector<int> rigidBodyModeComponents, ConstraintMatrix * constraints, const DoFHandler<dim>* dof_handler) const {
239 
240  if ( rigidBodyModeComponents.size() > 0 ){
241 
242  // Choose the point where the constraint will be placed. Must be the coordinates of a vertex.
243  dealii::Point<dim> target_point; // default constructor places the point at the origin
244 
245  unsigned int vertices_per_cell=GeometryInfo<dim>::vertices_per_cell;
246 
247  // Loop over each locally owned cell
248  typename DoFHandler<dim>::active_cell_iterator cell= dof_handler->begin_active(), endc = dof_handler->end();
249 
250  for (; cell!=endc; ++cell){
251  if (cell->is_locally_owned()){
252  for (unsigned int i=0; i<vertices_per_cell; ++i){
253 
254  // Check if the vertex is the target vertex
255  if (target_point.distance (cell->vertex(i)) < 1e-2 * cell->diameter()){
256 
257  // Loop through the list of components with rigid body modes and add an inhomogeneous constraint for each
258  for (unsigned int component_num = 0; component_num < rigidBodyModeComponents.size(); component_num++){
259  unsigned int nodeID=cell->vertex_dof_index(i,component_num);
260  constraints->add_line(nodeID);
261  constraints->set_inhomogeneity(nodeID,0.0);
262  }
263  }
264  }
265  }
266  }
267  }
268 }
269 
270 #include "../../include/matrixFreePDE_template_instantiations.h"
void getComponentsWithRigidBodyModes(std::vector< int > &) const
void setRigidBodyModeConstraints(const std::vector< int >, ConstraintMatrix *, const DoFHandler< dim > *) const
void setPeriodicityConstraints(ConstraintMatrix *, const DoFHandler< dim > *) const
Definition: varBCs.h:12