libMesh
poisson.C
Go to the documentation of this file.
1 /* This is where we define the assembly of the Laplace system */
2 
3 // General libMesh includes
4 #include "libmesh/getpot.h"
5 #include "libmesh/boundary_info.h"
6 #include "libmesh/dirichlet_boundaries.h"
7 #include "libmesh/dof_map.h"
8 #include "libmesh/fe_base.h"
9 #include "libmesh/fe_interface.h"
10 #include "libmesh/fem_context.h"
11 #include "libmesh/fem_system.h"
12 #include "libmesh/quadrature.h"
13 #include "libmesh/string_to_enum.h"
14 #include "libmesh/mesh.h"
15 #include "libmesh/parallel.h"
16 #include "libmesh/quadrature.h"
17 #include "libmesh/fem_context.h"
18 #include "libmesh/zero_function.h"
19 #include "libmesh/auto_ptr.h" // libmesh_make_unique
20 
21 // Local includes
22 #include "poisson.h"
23 
24 // Bring in everything from the libMesh namespace
25 using namespace libMesh;
26 
27 // Function to set the Dirichlet boundary function for the adjoint dirichlet boundary
28 class BdyFunction : public FunctionBase<Number>
29 {
30 public:
31  BdyFunction (unsigned int T_var)
32  : _T_var(T_var)
33  { this->_initialized = true; }
34 
35  virtual Number operator() (const Point &, const Real = 0)
36  { libmesh_not_implemented(); }
37 
38  virtual void operator() (const Point & p,
39  const Real,
40  DenseVector<Number> & output)
41  {
42  output.resize(2);
43  output.zero();
44  const Real x=p(0);
45  // Set the parabolic weighting
46  output(_T_var) = -x * (1 - x);
47  }
48 
49  virtual std::unique_ptr<FunctionBase<Number>> clone() const
50  { return libmesh_make_unique<BdyFunction>(_T_var); }
51 
52 private:
53  const unsigned int _T_var;
54 };
55 
57 {
58  T_var =
59  this->add_variable ("T", static_cast<Order>(_fe_order),
60  Utility::string_to_enum<FEFamily>(_fe_family));
61 
62  GetPot infile("poisson.in");
63  exact_QoI[0] = infile("QoI_0", 0.0);
64  alpha = infile("alpha", 100.0);
65 
66  // The temperature is evolving, with a first order time derivative
67  this->time_evolving(T_var, 1);
68 
69 #ifdef LIBMESH_ENABLE_DIRICHLET
70  // Now we will set the Dirichlet boundary conditions
71 
72  // Get boundary ids for all the boundaries
73  const boundary_id_type all_bdry_id[4] = {0, 1, 2, 3};
74  std::set<boundary_id_type> all_bdy(all_bdry_id, all_bdry_id+4);
75 
76  // For the adjoint problem, we will only set the bottom boundary to a non-zero value
77  const boundary_id_type bottom_bdry_id = 0;
78  std::set<boundary_id_type> bottom_bdry;
79  bottom_bdry.insert(bottom_bdry_id);
80 
81  // The T_only identifier for setting the boundary conditions for T
82  std::vector<unsigned int> T_only(1, T_var);
83 
84  // The zero function pointer for the primal all bdry bcs
86  // Boundary function for bottom bdry adjoint condition
87  BdyFunction bottom_adjoint(T_var);
88 
89  this->get_dof_map().add_dirichlet_boundary(DirichletBoundary (all_bdy, T_only, &zero));
90 
91  this->get_dof_map().add_adjoint_dirichlet_boundary(DirichletBoundary (bottom_bdry, T_only, &bottom_adjoint), 0);
92 #endif // LIBMESH_ENABLE_DIRICHLET
93 
94  // Do the parent's initialization after variables are defined
96 }
97 
99 {
100  FEMContext & c = cast_ref<FEMContext &>(context);
101 
102  // Now make sure we have requested all the data
103  // we need to build the linear system.
104  FEBase* elem_fe = nullptr;
105  c.get_element_fe( 0, elem_fe );
106  elem_fe->get_JxW();
107  elem_fe->get_phi();
108  elem_fe->get_dphi();
109  elem_fe->get_xyz();
110 
111  FEBase* side_fe = nullptr;
112  c.get_side_fe( 0, side_fe );
113 
114  side_fe->get_JxW();
115  side_fe->get_phi();
116  side_fe->get_dphi();
117  side_fe->get_xyz();
118 
119 }
120 
121 #define optassert(X) {if (!(X)) libmesh_error_msg("Assertion " #X " failed.");}
122 
123 // Assemble the element contributions to the stiffness matrix
124 bool PoissonSystem::element_time_derivative (bool request_jacobian,
125  DiffContext & context)
126 {
127  // Are the jacobians specified analytically ?
128  bool compute_jacobian = request_jacobian && _analytic_jacobians;
129 
130  FEMContext & c = cast_ref<FEMContext &>(context);
131 
132  // First we get some references to cell-specific data that
133  // will be used to assemble the linear system.
134  FEBase* elem_fe = nullptr;
135  c.get_element_fe( 0, elem_fe );
136 
137  // Element Jacobian * quadrature weights for interior integration
138  const std::vector<Real> & JxW = elem_fe->get_JxW();
139 
140  // Element basis functions
141  const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
142  const std::vector<std::vector<RealGradient>> & dphi = elem_fe->get_dphi();
143 
144  // Quadrature point locations
145  const std::vector<Point > & q_point = elem_fe->get_xyz();
146 
147  // The number of local degrees of freedom in each variable
148  const unsigned int n_T_dofs = c.n_dof_indices(0);
149 
150  // The subvectors and submatrices we need to fill:
153 
154  // Now we will build the element Jacobian and residual.
155  // Constructing the residual requires the solution and its
156  // gradient from the previous timestep. This must be
157  // calculated at each quadrature point by summing the
158  // solution degree-of-freedom values by the appropriate
159  // weight functions.
160  unsigned int n_qpoints = c.get_element_qrule().n_points();
161 
162  for (unsigned int qp=0; qp != n_qpoints; qp++)
163  {
164  // Compute the solution gradient at the Newton iterate
165  Gradient grad_T = c.interior_gradient(0, qp);
166 
167  // Location of the current qp
168  const Real x = q_point[qp](0);
169  const Real y = q_point[qp](1);
170 
171  // Forcing function
172  Real f = -alpha * ( ( (- 4 * alpha * alpha) * exp(-alpha*x) * y * (1 - y) ) + ( -8 + ( 8 * exp(-alpha*x) ) + ( 8 * ( 1 - exp(-alpha) )* x) ) );
173 
174  // The residual contribution from this element
175  for (unsigned int i=0; i != n_T_dofs; i++)
176  F(i) += JxW[qp] * ( (f * phi[i][qp]) - alpha*(grad_T * dphi[i][qp]) ) ;
177  if (compute_jacobian)
178  for (unsigned int i=0; i != n_T_dofs; i++)
179  for (unsigned int j=0; j != n_T_dofs; ++j)
180  // The analytic jacobian
181  K(i,j) += JxW[qp] * ( -alpha*(dphi[i][qp] * dphi[j][qp]) );
182  } // end of the quadrature point qp-loop
183 
184  return compute_jacobian;
185 }
186 
187 // Override the default DiffSystem postprocess function to compute the
188 // approximations to the QoIs
190 {
191  // Reset the array holding the computed QoIs
192  computed_QoI[0] = 0.0;
193 
195 
196  this->comm().sum(computed_QoI[0]);
197 }
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::DiffContext::get_elem_residual
const DenseVector< Number > & get_elem_residual() const
Const accessor for element residual.
Definition: diff_context.h:249
libMesh::FEMContext::get_element_qrule
const QBase & get_element_qrule() const
Accessor for element interior quadrature rule for the dimension of the current _elem.
Definition: fem_context.h:790
libMesh::FunctionBase
Base class for functors that can be evaluated at a point and (optionally) time.
Definition: dirichlet_boundaries.h:44
libMesh::FEAbstract::get_xyz
const std::vector< Point > & get_xyz() const
Definition: fe_abstract.h:237
PoissonSystem::postprocess
virtual void postprocess(void)
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides.
Definition: poisson.C:189
compute_jacobian
void compute_jacobian(const NumericVector< Number > &, SparseMatrix< Number > &J, NonlinearImplicitSystem &system)
Definition: assembly.C:311
libMesh::FEMSystem::init_data
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
Definition: fem_system.C:843
libMesh::DenseSubMatrix
Defines a dense submatrix for use in Finite Element-type computations.
Definition: dense_submatrix.h:45
libMesh::QBase::n_points
unsigned int n_points() const
Definition: quadrature.h:126
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::DenseVector::zero
virtual void zero() override
Set every element in the vector to 0.
Definition: dense_vector.h:379
libMesh::FEGenericBase
This class forms the foundation from which generic finite elements may be derived.
Definition: exact_error_estimator.h:39
libMesh::FEAbstract::get_JxW
const std::vector< Real > & get_JxW() const
Definition: fe_abstract.h:244
BdyFunction
Definition: coupled_system.C:38
libMesh::FEGenericBase::get_dphi
const std::vector< std::vector< OutputGradient > > & get_dphi() const
Definition: fe_base.h:214
libMesh::boundary_id_type
int8_t boundary_id_type
Definition: id_types.h:51
libMesh::VectorValue< Number >
libMesh::zero
const Number zero
.
Definition: libmesh.h:243
libMesh::FEMSystem::postprocess
virtual void postprocess() override
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides.
Definition: fem_system.C:1097
BdyFunction::_T_var
const unsigned int _T_var
Definition: poisson.C:53
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
PoissonSystem::init_data
virtual void init_data()
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
Definition: poisson.C:56
BdyFunction::clone
virtual std::unique_ptr< FunctionBase< Number > > clone() const
Definition: poisson.C:49
libMesh::DiffContext::n_dof_indices
unsigned int n_dof_indices() const
Total number of dof indices on the element.
Definition: diff_context.h:399
libMesh::ZeroFunction
ConstFunction that simply returns 0.
Definition: zero_function.h:36
libMesh::DiffContext
This class provides all data required for a physics package (e.g.
Definition: diff_context.h:55
PoissonSystem::element_time_derivative
virtual bool element_time_derivative(bool request_jacobian, DiffContext &context)
Adds the time derivative contribution on elem to elem_residual.
Definition: poisson.C:124
BdyFunction::BdyFunction
BdyFunction(unsigned int T_var)
Definition: poisson.C:31
libMesh::DenseSubVector< Number >
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::FEMContext::get_element_fe
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for interior finite element object for variable var for the largest dimension in the mesh.
Definition: fem_context.h:275
libMesh::FEMContext::interior_gradient
Gradient interior_gradient(unsigned int var, unsigned int qp) const
Definition: fem_context.C:426
poisson.h
libMesh::DiffContext::get_elem_jacobian
const DenseMatrix< Number > & get_elem_jacobian() const
Const accessor for element Jacobian.
Definition: diff_context.h:283
libMesh::DirichletBoundary
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Definition: dirichlet_boundaries.h:88
libMesh::FEMContext::get_side_fe
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for edge/face (2D/3D) finite element object for variable var for the largest dimension in th...
Definition: fem_context.h:312
libMesh::FEGenericBase::get_phi
const std::vector< std::vector< OutputShape > > & get_phi() const
Definition: fe_base.h:206
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
PoissonSystem::init_context
virtual void init_context(DiffContext &context)
Definition: poisson.C:98
libMesh::DenseVector< Number >
libMesh::FEMContext
This class provides all data required for a physics package (e.g.
Definition: fem_context.h:62