libMesh
Classes | Namespaces | Functions
vector_fe_ex5.C File Reference

Go to the source code of this file.

Classes

class  libMesh::NumericVector< T >
 Provides a uniform interface to vector storage schemes for different linear algebra libraries. More...
 
class  libMesh::SparseMatrix< T >
 Generic sparse matrix. More...
 

Namespaces

 libMesh
 The libMesh namespace provides an interface to certain functionality in the library.
 

Functions

void compute_residual (const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &S)
 
void compute_jacobian (const NumericVector< Number > &X, SparseMatrix< Number > &J, NonlinearImplicitSystem &S)
 
int main (int argc, char **argv)
 

Function Documentation

◆ compute_jacobian()

void compute_jacobian ( const NumericVector< Number > &  X,
SparseMatrix< Number > &  J,
NonlinearImplicitSystem S 
)

Definition at line 311 of file assembly.C.

314 {
315  // It is a good idea to make sure we are assembling
316  // the proper system.
317  libmesh_assert_equal_to(system.name(), "Poisson");
318 
319  // Get the DG parameters
320  auto & es = system.get_equation_systems();
321  const auto sigma = es.parameters.get<Real>("sigma");
322  const auto epsilon = es.parameters.get<Real>("epsilon");
323 
324  // Get a constant reference to the mesh object.
325  const MeshBase & mesh = system.get_mesh();
326 
327  // The dimension that we are running
328  const auto dim = mesh.mesh_dimension();
329 
330  // A reference to the DofMap object for this system. The DofMap
331  // object handles the index translation from node and element numbers
332  // to degree of freedom numbers. We will talk more about the DofMap
333  // in future examples.
334  const DofMap & dof_map = system.get_dof_map();
335 
336  // Get a constant reference to the Finite Element type
337  // for the first (and only) variable in the system.
338  FEType fe_type = dof_map.variable_type(0);
339 
340  // Build a Finite Element object of the specified type.
341  // Note that FEVectorBase is a typedef for the templated FE
342  // class.
343  std::unique_ptr<FEVectorBase> fe(FEVectorBase::build(dim, fe_type));
344 
345  // An automatically determined Gauss quadrature rule for numerical integration.
346  QGauss qrule(dim, fe_type.default_quadrature_order());
347 
348  // Tell the finite element object to use our quadrature rule.
349  fe->attach_quadrature_rule(&qrule);
350 
351  // Declare a special finite element object for face integration.
352  std::unique_ptr<FEVectorBase> fe_face(FEVectorBase::build(dim, fe_type));
353  // And for neighbor integration
354  std::unique_ptr<FEVectorBase> fe_neighbor_face(FEVectorBase::build(dim, fe_type));
355 
356  // Boundary integration requires one quadrature rule,
357  // with dimensionality one less than the dimensionality
358  // of the element.
359  QGauss qface(dim - 1, fe_type.default_quadrature_order());
360 
361  // Tell the face finite element objects to use our
362  // quadrature rule.
363  fe_face->attach_quadrature_rule(&qface);
364  fe_neighbor_face->attach_quadrature_rule(&qface);
365 
366  // Here we define some references to cell-specific data that
367  // will be used to assemble the linear system.
368  //
369  // The element Jacobian * quadrature weight at each integration point.
370  const auto & JxW = fe->get_JxW();
371 
372  // The element shape function gradients evaluated at the quadrature points.
373  const auto & dphi = fe->get_dphi();
374 
375  // face integration points
376  const auto & face_xyz = fe_face->get_xyz();
377 
378  // Face shape function values
379  const auto & phi_face = fe_face->get_phi();
380 
381  // Face shape function gradients
382  const auto & dphi_face = fe_face->get_dphi();
383 
384  // Neighbor shape function values
385  const auto & phi_neighbor = fe_neighbor_face->get_phi();
386 
387  // Neighbor face shape function gradients
388  const auto & dphi_neighbor = fe_neighbor_face->get_dphi();
389 
390  // face normals
391  const auto & normals = fe_face->get_normals();
392 
393  // face JxW
394  const auto & JxW_face = fe_face->get_JxW();
395 
400 
401  // This vector will hold the degree of freedom indices for
402  // the element. These define where in the global system
403  // the element degrees of freedom get mapped.
404  std::vector<dof_id_type> dof_indices;
405  std::vector<dof_id_type> dof_indices_neighbor;
406 
407  // Now we will loop over all the elements in the mesh.
408  // We will compute the element matrix and right-hand-side
409  // contribution.
410  //
411  // Element iterators are a nice way to iterate through all the
412  // elements, or all the elements that have some property. The
413  // iterator el will iterate from the first to the last element on
414  // the local processor. The iterator end_el tells us when to stop.
415  // It is smart to make this one const so that we don't accidentally
416  // mess it up! In case users later modify this program to include
417  // refinement, we will be safe and will only consider the active
418  // elements; hence we use a variant of the active_elem_iterator.
419  for (const auto & elem : mesh.active_local_element_ptr_range())
420  {
421  // Get the degree of freedom indices for the
422  // current element. These define where in the global
423  // matrix and right-hand-side this element will
424  // contribute to.
425  dof_map.dof_indices(elem, dof_indices);
426 
427  // Compute the element-specific data for the current
428  // element. This involves computing the location of the
429  // quadrature points (q_point) and the shape functions
430  // (phi, dphi) for the current element.
431  fe->reinit(elem);
432 
433  libmesh_assert_msg(dphi.size() == dof_indices.size(),
434  "dphi size doesn't match dof_indices size");
435 
436  // DenseMatrix::resize() member will automatically zero out the matrix.
437  Kee.resize(dof_indices.size(), dof_indices.size());
438 
439  // diffusion elemental jacobian
440  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
441  for (std::size_t i = 0; i < dof_indices.size(); i++)
442  for (std::size_t j = 0; j < dof_indices.size(); j++)
443  Kee(i, j) += JxW[qp] * dphi[i][qp].contract(dphi[j][qp]);
444 
445  // Now we consider jacobian contributions from the sides
446  for (auto side : elem->side_index_range())
447  {
448  // We need to compute h for penalty terms
449  std::unique_ptr<const Elem> elem_side(elem->build_side_ptr(side));
450  fe_face->reinit(elem, side);
451  const auto elem_b_order = static_cast<unsigned int>(fe_face->get_order());
452  const auto h_elem = elem->volume() / elem_side->volume() / std::pow(elem_b_order, 2);
453 
454  // No neighbor means we must be on a boundary
455  if (!elem->neighbor_ptr(side))
456  {
457  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
458  for (std::size_t i = 0; i < dof_indices.size(); i++)
459  for (std::size_t j = 0; j < dof_indices.size(); j++)
460 
461  {
462  Kee(i, j) -= dphi_face[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
463  Kee(i, j) +=
464  epsilon * phi_face[j][qp] * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
465  Kee(i, j) += sigma / h_elem * phi_face[j][qp] * phi_face[i][qp] * JxW_face[qp];
466  }
467  }
468  else // We must be on an interior side
469  {
470  const Elem * neighbor = elem->neighbor_ptr(side);
471 
472  const auto elem_id = elem->id();
473  const auto neighbor_id = neighbor->id();
474 
475  // We don't want to erroneously add multiple contributions from the same interior face
476  if ((neighbor->active() && (neighbor->level() == elem->level()) &&
477  (elem_id < neighbor_id)) ||
478  (neighbor->level() < elem->level()))
479  {
480  dof_map.dof_indices(neighbor, dof_indices_neighbor);
481 
482  // Make sure we have the matching quadrature points on face and neighbor
483  std::vector<Point> neighbor_xyz;
484  FEMap::inverse_map(elem->dim(), neighbor, face_xyz,
485  neighbor_xyz);
486 
487  fe_neighbor_face->reinit(neighbor, &neighbor_xyz);
488 
489  libmesh_assert_msg(dphi_neighbor.size() == dof_indices_neighbor.size(),
490  "dphi_neighbor size doesn't match dof_indices_neighbor size");
491 
492  Ken.resize(dof_indices.size(), dof_indices_neighbor.size());
493  Kne.resize(dof_indices_neighbor.size(), dof_indices.size());
494  Knn.resize(dof_indices_neighbor.size(), dof_indices_neighbor.size());
495 
496  // Now add the DG contribution to the local jacobian
497  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
498  {
499  // element-element contribution
500  for (std::size_t i = 0; i < dof_indices.size(); i++)
501  for (std::size_t j = 0; j < dof_indices.size(); j++)
502  {
503  Kee(i, j) -= 0.5 * dphi_face[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
504  Kee(i, j) +=
505  epsilon * 0.5 * phi_face[j][qp] * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
506  Kee(i, j) += sigma / h_elem * phi_face[j][qp] * phi_face[i][qp] * JxW_face[qp];
507  }
508  // element-neighbor contribution
509  for (std::size_t i = 0; i < dof_indices.size(); i++)
510  for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
511  {
512  Ken(i, j) -=
513  0.5 * dphi_neighbor[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
514  Ken(i, j) += epsilon * 0.5 * -phi_neighbor[j][qp] * dphi_face[i][qp] * normals[qp] *
515  JxW_face[qp];
516  Ken(i, j) += sigma / h_elem * -phi_neighbor[j][qp] * phi_face[i][qp] * JxW_face[qp];
517  }
518  // Neighbor-element contribution
519  for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
520  for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
521  {
522  Kne(i, j) +=
523  0.5 * dphi_face[j][qp] * normals[qp] * phi_neighbor[i][qp] * JxW_face[qp];
524  Kne(i, j) -= epsilon * 0.5 * phi_face[j][qp] * dphi_neighbor[i][qp] * normals[qp] *
525  JxW_face[qp];
526  Kne(i, j) -= sigma / h_elem * phi_face[j][qp] * phi_neighbor[i][qp] * JxW_face[qp];
527  }
528  // Neighbor-neighbor contribution
529  for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
530  for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
531  {
532  Knn(i, j) +=
533  0.5 * dphi_neighbor[j][qp] * normals[qp] * phi_neighbor[i][qp] * JxW_face[qp];
534  Knn(i, j) -= epsilon * 0.5 * -phi_neighbor[j][qp] * dphi_neighbor[i][qp] *
535  normals[qp] * JxW_face[qp];
536  Knn(i, j) -=
537  sigma / h_elem * -phi_neighbor[j][qp] * phi_neighbor[i][qp] * JxW_face[qp];
538  }
539  }
540 
541  J.add_matrix(Ken, dof_indices, dof_indices_neighbor);
542  J.add_matrix(Kne, dof_indices_neighbor, dof_indices);
543  J.add_matrix(Knn, dof_indices_neighbor, dof_indices_neighbor);
544  } // whether we've done this internal side integral before
545  } // whether we're on an internal side
546  } // loop over sides
547 
548  J.add_matrix(Kee, dof_indices, dof_indices);
549  } // element loop
550 }

References libMesh::Elem::active(), libMesh::MeshBase::active_local_element_ptr_range(), libMesh::SparseMatrix< T >::add_matrix(), libMesh::FEGenericBase< OutputType >::build(), libMesh::FEType::default_quadrature_order(), dim, libMesh::DofMap::dof_indices(), libMesh::Parameters::get(), libMesh::System::get_dof_map(), libMesh::System::get_equation_systems(), libMesh::System::get_mesh(), libMesh::DofObject::id(), libMesh::FEMap::inverse_map(), libMesh::Elem::level(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::System::name(), libMesh::Elem::neighbor_ptr(), libMesh::EquationSystems::parameters, std::pow(), libMesh::Real, libMesh::DenseMatrix< T >::resize(), and libMesh::DofMap::variable_type().

Referenced by libMesh::FirstOrderUnsteadySolver::compute_second_order_eqns(), PoissonSystem::element_time_derivative(), LaplaceSystem::element_time_derivative(), HeatSystem::element_time_derivative(), main(), and LaplaceSystem::side_constraint().

◆ compute_residual()

void compute_residual ( const NumericVector< Number > &  X,
NumericVector< Number > &  R,
NonlinearImplicitSystem S 
)

Vectors to hold the local solution degree of freedom values

Vector to hold the local solution

Definition at line 26 of file assembly.C.

29 {
30  // It is a good idea to make sure we are assembling
31  // the proper system.
32  libmesh_assert_equal_to(system.name(), "Poisson");
33 
34  // Get the DG parameters
35  auto & es = system.get_equation_systems();
36  const auto sigma = es.parameters.get<Real>("sigma");
37  const auto epsilon = es.parameters.get<Real>("epsilon");
38 
39  // Get a constant reference to the mesh object.
40  const MeshBase & mesh = system.get_mesh();
41 
42  // The dimension that we are running
43  const auto dim = mesh.mesh_dimension();
44 
45  // A reference to the DofMap object for this system. The DofMap
46  // object handles the index translation from node and element numbers
47  // to degree of freedom numbers. We will talk more about the DofMap
48  // in future examples.
49  const DofMap & dof_map = system.get_dof_map();
50 
51  // Get a constant reference to the Finite Element type
52  // for the first (and only) variable in the system.
53  FEType fe_type = dof_map.variable_type(0);
54 
55  // Build a Finite Element object of the specified type.
56  // Note that FEVectorBase is a typedef for the templated FE
57  // class.
58  std::unique_ptr<FEVectorBase> fe(FEVectorBase::build(dim, fe_type));
59 
60  // An automatically determined Gauss quadrature rule for numerical integration.
61  QGauss qrule(dim, fe_type.default_quadrature_order());
62 
63  // Tell the finite element object to use our quadrature rule.
64  fe->attach_quadrature_rule(&qrule);
65 
66  // Declare a special finite element object for face integration.
67  std::unique_ptr<FEVectorBase> fe_face(FEVectorBase::build(dim, fe_type));
68  // And for neighbor integration
69  std::unique_ptr<FEVectorBase> fe_neighbor_face(FEVectorBase::build(dim, fe_type));
70 
71  // Boundary integration requires one quadrature rule,
72  // with dimensionality one less than the dimensionality
73  // of the element.
74  QGauss qface(dim - 1, fe_type.default_quadrature_order());
75 
76  // Tell the face finite element objects to use our
77  // quadrature rule.
78  fe_face->attach_quadrature_rule(&qface);
79  fe_neighbor_face->attach_quadrature_rule(&qface);
80 
81  // Here we define some references to cell-specific data that
82  // will be used to assemble the linear system.
83  //
84  // The element Jacobian * quadrature weight at each integration point.
85  const auto & JxW = fe->get_JxW();
86 
87  // element integration points
88  const auto & xyz = fe->get_xyz();
89 
90  // The element shape function values evaluated at the quadrature points
91  const auto & phi = fe->get_phi();
92 
93  // The element shape function gradients evaluated at the quadrature points.
94  const auto & dphi = fe->get_dphi();
95 
96  // face integration points
97  const auto & face_xyz = fe_face->get_xyz();
98 
99  // Face shape function values
100  const auto & phi_face = fe_face->get_phi();
101 
102  // Face shape function gradients
103  const auto & dphi_face = fe_face->get_dphi();
104 
105  // Neighbor shape function values
106  const auto & phi_neighbor = fe_neighbor_face->get_phi();
107 
108  // Neighbor face shape function gradients
109  const auto & dphi_neighbor = fe_neighbor_face->get_dphi();
110 
111  // face normals
112  const auto & normals = fe_face->get_normals();
113 
114  // face JxW
115  const auto & JxW_face = fe_face->get_JxW();
116 
119 
120  // This vector will hold the degree of freedom indices for
121  // the element. These define where in the global system
122  // the element degrees of freedom get mapped.
123  std::vector<dof_id_type> dof_indices;
124  std::vector<dof_id_type> dof_indices_neighbor;
125 
127  std::vector<Number> dof_u;
128  std::vector<Number> dof_u_neighbor;
129 
131  std::vector<VectorValue<Number>> u;
132  std::vector<TensorValue<Number>> grad_u;
133  std::vector<VectorValue<Number>> u_neighbor;
134  std::vector<TensorValue<Number>> grad_u_neighbor;
135 
136  // Now we will loop over all the elements in the mesh.
137  // We will compute the element matrix and right-hand-side
138  // contribution.
139  //
140  // Element iterators are a nice way to iterate through all the
141  // elements, or all the elements that have some property. The
142  // iterator el will iterate from the first to the last element on
143  // the local processor. The iterator end_el tells us when to stop.
144  // It is smart to make this one const so that we don't accidentally
145  // mess it up! In case users later modify this program to include
146  // refinement, we will be safe and will only consider the active
147  // elements; hence we use a variant of the active_elem_iterator.
148  for (const auto & elem : mesh.active_local_element_ptr_range())
149  {
150  // Get the degree of freedom indices for the
151  // current element. These define where in the global
152  // matrix and right-hand-side this element will
153  // contribute to.
154  dof_map.dof_indices(elem, dof_indices);
155 
156  // Compute the element-specific data for the current
157  // element. This involves computing the location of the
158  // quadrature points (q_point) and the shape functions
159  // (phi, dphi) for the current element.
160  fe->reinit(elem);
161 
162  libmesh_assert_msg(dphi.size() == dof_indices.size(),
163  "dphi size doesn't match dof_indices size");
164 
165  // DenseVector::resize() member will automatically zero out the vector.
166  Fe.resize(dof_indices.size());
167 
168  // Get the local solution vector
169  X.get(dof_indices, dof_u);
170 
171  // build the element solution gradient
172  grad_u.resize(qrule.n_points());
173  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
174  {
175  grad_u[qp] = 0;
176  for (std::size_t i = 0; i < dof_indices.size(); i++)
177  grad_u[qp] += dof_u[i] * dphi[i][qp];
178  }
179 
180  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
181  {
182  auto forcing_func = VectorValue<Number>(forcing_function(0, xyz[qp](0), xyz[qp](1)),
183  forcing_function(1, xyz[qp](0), xyz[qp](1)),
184  0);
185  for (std::size_t i = 0; i < dof_indices.size(); i++)
186  {
187  // diffusion elemental residual
188  Fe(i) += JxW[qp] * dphi[i][qp].contract(grad_u[qp]);
189 
190  // forcing function
191  Fe(i) += JxW[qp] * phi[i][qp] * forcing_func;
192  }
193  }
194 
195  // Now we consider residual contributions from the sides
196  for (auto side : elem->side_index_range())
197  {
198  // We need to compute h for penalty terms
199  std::unique_ptr<const Elem> elem_side(elem->build_side_ptr(side));
200  fe_face->reinit(elem, side);
201  const auto elem_b_order = static_cast<unsigned int>(fe_face->get_order());
202  const auto h_elem = elem->volume() / elem_side->volume() / std::pow(elem_b_order, 2);
203 
204  // build the face solution value and gradient
205  u.resize(qface.n_points());
206  grad_u.resize(qface.n_points());
207  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
208  {
209  u[qp] = 0;
210  grad_u[qp] = 0;
211  for (std::size_t i = 0; i < dof_indices.size(); i++)
212  {
213  u[qp] += dof_u[i] * phi_face[i][qp];
214  grad_u[qp] += dof_u[i] * dphi_face[i][qp];
215  }
216  }
217 
218  // No neighbor means we must be on a boundary
219  if (!elem->neighbor_ptr(side))
220  {
221  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
222  {
223  auto fn = VectorValue<Number>(exact_solution(0, face_xyz[qp](0), face_xyz[qp](1)),
224  exact_solution(1, face_xyz[qp](0), face_xyz[qp](1)),
225  0);
226  for (std::size_t i = 0; i < dof_indices.size(); i++)
227  {
228  Fe(i) -= grad_u[qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
229  Fe(i) += epsilon * (u[qp] - fn) * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
230  Fe(i) += sigma / h_elem * (u[qp] - fn) * phi_face[i][qp] * JxW_face[qp];
231  }
232  }
233  }
234  else // We must be on an interior side
235  {
236  const Elem * neighbor = elem->neighbor_ptr(side);
237 
238  const auto elem_id = elem->id();
239  const auto neighbor_id = neighbor->id();
240 
241  // We don't want to erroneously add multiple contributions from the same interior face
242  if ((neighbor->active() && (neighbor->level() == elem->level()) &&
243  (elem_id < neighbor_id)) ||
244  (neighbor->level() < elem->level()))
245  {
246  dof_map.dof_indices(neighbor, dof_indices_neighbor);
247 
248  // Make sure we have the matching quadrature points on face and neighbor
249  std::vector<Point> neighbor_xyz;
250  FEMap::inverse_map(elem->dim(), neighbor, face_xyz,
251  neighbor_xyz);
252 
253  fe_neighbor_face->reinit(neighbor, &neighbor_xyz);
254 
255  libmesh_assert_msg(dphi_neighbor.size() == dof_indices_neighbor.size(),
256  "dphi_neighbor size doesn't match dof_indices_neighbor size");
257 
258  Fn.resize(dof_indices_neighbor.size());
259  X.get(dof_indices_neighbor, dof_u_neighbor);
260 
261  // build the neighbor solution value and gradient
262  u_neighbor.resize(qface.n_points());
263  grad_u_neighbor.resize(qface.n_points());
264  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
265  {
266  u_neighbor[qp] = 0;
267  grad_u_neighbor[qp] = 0;
268  for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
269  {
270  u_neighbor[qp] += dof_u_neighbor[i] * phi_neighbor[i][qp];
271  grad_u_neighbor[qp] += dof_u_neighbor[i] * dphi_neighbor[i][qp];
272  }
273  }
274 
275  // Now add the DG contribution to the local residual
276  for (unsigned int qp = 0; qp < qface.n_points(); qp++)
277  {
278  // element contribution
279  for (std::size_t i = 0; i < dof_indices.size(); i++)
280  {
281  Fe(i) -= 0.5 * (grad_u[qp] * normals[qp] + grad_u_neighbor[qp] * normals[qp]) *
282  phi_face[i][qp] * JxW_face[qp];
283  Fe(i) += epsilon * 0.5 * (u[qp] - u_neighbor[qp]) * dphi_face[i][qp] * normals[qp] *
284  JxW_face[qp];
285  Fe(i) += sigma / h_elem * (u[qp] - u_neighbor[qp]) * phi_face[i][qp] * JxW_face[qp];
286  }
287  // Neighbor contribution
288  for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
289  {
290  Fn(i) += 0.5 * (grad_u[qp] * normals[qp] + grad_u_neighbor[qp] * normals[qp]) *
291  phi_neighbor[i][qp] * JxW_face[qp];
292  Fn(i) -= epsilon * 0.5 * (u[qp] - u_neighbor[qp]) * dphi_neighbor[i][qp] *
293  normals[qp] * JxW_face[qp];
294  Fn(i) -=
295  sigma / h_elem * (u[qp] - u_neighbor[qp]) * phi_neighbor[i][qp] * JxW_face[qp];
296  }
297  }
298 
299  R.add_vector(Fn, dof_indices_neighbor);
300  } // whether we've done this internal side integral before
301  } // whether we're on an internal side
302  } // loop over sides
303 
304  R.add_vector(Fe, dof_indices);
305  } // element loop
306 }

References libMesh::Elem::active(), libMesh::MeshBase::active_local_element_ptr_range(), libMesh::NumericVector< T >::add_vector(), libMesh::FEGenericBase< OutputType >::build(), libMesh::FEType::default_quadrature_order(), dim, libMesh::DofMap::dof_indices(), exact_solution(), forcing_function(), libMesh::Parameters::get(), libMesh::NumericVector< T >::get(), libMesh::System::get_dof_map(), libMesh::System::get_equation_systems(), libMesh::System::get_mesh(), libMesh::DofObject::id(), libMesh::FEMap::inverse_map(), libMesh::Elem::level(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::System::name(), libMesh::Elem::neighbor_ptr(), libMesh::EquationSystems::parameters, std::pow(), libMesh::Real, libMesh::DenseVector< T >::resize(), and libMesh::DofMap::variable_type().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 62 of file vector_fe_ex5.C.

63 {
64  // Initialize libraries.
65  LibMeshInit init(argc, argv);
66 
67  // This example requires a non-linear solver package.
68  libmesh_example_requires(libMesh::default_solver_package() == PETSC_SOLVERS ||
70  "--enable-petsc or --enable-trilinos");
71 
72  // Parse input file
73  GetPot input_file("vector_fe_ex5.in");
74 
75  // Read DG parameters
76  const Real epsilon = input_file("epsilon", -1);
77  const Real sigma = input_file("sigma", 6);
78 
79  // Read mesh size
80  const std::size_t nx = input_file("nx", 15);
81  const std::size_t ny = input_file("ny", 15);
82 
83  // Brief message to the user regarding the program name
84  // and command line arguments.
85  libMesh::out << "Running " << argv[0];
86 
87  for (int i = 1; i < argc; i++)
88  libMesh::out << " " << argv[i];
89 
90  libMesh::out << std::endl << std::endl;
91 
92  // Skip this 2D example if libMesh was compiled as 1D-only.
93  libmesh_example_requires(2 <= LIBMESH_DIM, "2D support");
94 
95  // Create a mesh, with dimension to be overridden later, on the
96  // default MPI communicator.
97  Mesh mesh(init.comm());
98 
99  // Use the MeshTools::Generation mesh generator to create a uniform
100  // 2D grid on the square [-1,1]^2. We instruct the mesh generator
101  // to build a mesh of 15x15 QUAD4 elements. Note that at the end of this
102  // fuction call, the mesh will be prepared and remote elements will be deleted
103  MeshTools::Generation::build_square(mesh, nx, ny, -1., 1., -1., 1., QUAD4);
104 
105  // Print information about the mesh to the screen.
106  mesh.print_info();
107 
108  // Create an equation systems object.
109  EquationSystems equation_systems(mesh);
110  equation_systems.parameters.set<Real>("epsilon") = epsilon;
111  equation_systems.parameters.set<Real>("sigma") = sigma;
112 
113  // Declare the Poisson system and its variables.
114  // The Poisson system is another example of a steady system.
115  auto & nl_system = equation_systems.add_system<NonlinearImplicitSystem>("Poisson");
116 
117  // Adds the variable "u" to "Poisson". "u"
118  // will be approximated using first-order vector monomial elements.
119  // Since the mesh is 2-D, "u" will have two components.
120  nl_system.add_variable("u", FIRST, MONOMIAL_VEC);
121 
122  // Set the residual and Jacobian evaluation functions
123  auto & nl_solver = *nl_system.nonlinear_solver;
124  nl_solver.residual = compute_residual;
125  nl_solver.jacobian = compute_jacobian;
126 
127  // Initialize the data structures for the equation system.
128  equation_systems.init();
129 
130  // Prints information about the system to the screen.
131  equation_systems.print_info();
132 
133  nl_system.solve();
134 
135 #ifdef LIBMESH_HAVE_EXODUS_API
136  ExodusII_IO(mesh).write_equation_systems("out.e", equation_systems);
137 #endif
138 
139  // All done.
140  return 0;
141 }

References libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), libMesh::MeshTools::Generation::build_square(), compute_jacobian(), compute_residual(), libMesh::default_solver_package(), libMesh::FIRST, libMesh::TriangleWrapper::init(), libMesh::EquationSystems::init(), mesh, libMesh::MONOMIAL_VEC, libMesh::out, libMesh::EquationSystems::parameters, libMesh::PETSC_SOLVERS, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::QUAD4, libMesh::Real, libMesh::Parameters::set(), libMesh::TRILINOS_SOLVERS, and libMesh::MeshOutput< MT >::write_equation_systems().

libMesh::Mesh
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
libMesh::QGauss
This class implements specific orders of Gauss quadrature.
Definition: quadrature_gauss.h:39
libMesh::PETSC_SOLVERS
Definition: enum_solver_package.h:36
libMesh::DofMap::dof_indices
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1967
libMesh::Elem::level
unsigned int level() const
Definition: elem.h:2478
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
compute_jacobian
void compute_jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &J, NonlinearImplicitSystem &S)
Definition: assembly.C:311
libMesh::DenseMatrix< Number >
libMesh::MONOMIAL_VEC
Definition: enum_fe_family.h:62
libMesh::default_solver_package
SolverPackage default_solver_package()
Definition: libmesh.C:993
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::ExodusII_IO
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:51
libMesh::NonlinearImplicitSystem
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
Definition: nonlinear_implicit_system.h:54
libMesh::Elem::active
bool active() const
Definition: elem.h:2345
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DenseMatrix::resize
void resize(const unsigned int new_m, const unsigned int new_n)
Resize the matrix.
Definition: dense_matrix.h:822
libMesh::VectorValue< Number >
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::MeshTools::Generation::build_square
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
Definition: mesh_generation.C:1501
libMesh::NumericVector::add_vector
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i].
Definition: numeric_vector.C:363
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
compute_residual
void compute_residual(const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &S)
Definition: assembly.C:26
libMesh::System::add_variable
unsigned int add_variable(const std::string &var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1069
libMesh::QUAD4
Definition: enum_elem_type.h:41
forcing_function
Real forcing_function(const int component, const Real x, const Real y, const Real z=0.)
Definition: exact_solution.C:59
std::pow
double pow(double a, int b)
Definition: libmesh_augment_std_namespace.h:58
libMesh::DofMap::variable_type
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1924
libMesh::LibMeshInit
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:83
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::MeshOutput::write_equation_systems
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition: mesh_output.C:31
libMesh::TRILINOS_SOLVERS
Definition: enum_solver_package.h:37
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::SparseMatrix::add_matrix
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
libMesh::MeshBase::print_info
void print_info(std::ostream &os=libMesh::out) const
Prints relevant information about the mesh.
Definition: mesh_base.C:585
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
exact_solution
Real exact_solution(const int component, const Real x, const Real y, const Real z=0.)
This is the exact solution that we are trying to obtain.
Definition: exact_solution.C:39
libMesh::NumericVector::get
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
Definition: numeric_vector.h:821
libMesh::Elem::neighbor_ptr
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2085
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::FEType::default_quadrature_order
Order default_quadrature_order() const
Definition: fe_type.h:353
libMesh::out
OStreamProxy out
libMesh::FIRST
Definition: enum_order.h:42
libMesh::DenseVector< Number >