libMesh
heatsystem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #include "libmesh/getpot.h"
21 
22 #include "heatsystem.h"
23 
24 #include "libmesh/fe_base.h"
25 #include "libmesh/fe_interface.h"
26 #include "libmesh/fem_context.h"
27 #include "libmesh/mesh.h"
28 #include "libmesh/quadrature.h"
29 #include "libmesh/string_to_enum.h"
30 #include "libmesh/system.h"
31 #include "libmesh/equation_systems.h"
32 #include "libmesh/zero_function.h"
33 #include "libmesh/dirichlet_boundaries.h"
34 #include "libmesh/dof_map.h"
35 
37 {
38  T_var = this->add_variable ("T", static_cast<Order>(_fe_order),
39  Utility::string_to_enum<FEFamily>(_fe_family));
40 
41  // Make sure the input file heat.in exists, and parse it.
42  {
43  std::ifstream i("heat.in");
44  if (!i)
45  libmesh_error_msg('[' << this->processor_id() << "] Can't find heat.in; exiting early.");
46  }
47  GetPot infile("heat.in");
48  _k = infile("k", 1.0);
49  _analytic_jacobians = infile("analytic_jacobians", true);
50 
51  parameters.push_back(_k);
52 
53  // Set equation system parameters _k and theta, so they can be read by the exact solution
54  this->get_equation_systems().parameters.set<Real>("_k") = _k;
55 
56  // The temperature is evolving, with a first order time derivative
57  this->time_evolving(T_var, 1);
58 
59  const boundary_id_type all_ids[4] = {0, 1, 2, 3};
60  std::set<boundary_id_type> all_bdys(all_ids, all_ids+(2*2));
61 
62  std::vector<unsigned int> T_only(1, T_var);
63 
64  ZeroFunction<Number> zero;
65 
66 #ifdef LIBMESH_ENABLE_DIRICHLET
67  // Most DirichletBoundary users will want to supply a "locally
68  // indexed" functor
70  (DirichletBoundary (all_bdys, T_only, zero,
72 #endif
73 
74  FEMSystem::init_data();
75 }
76 
77 
78 
79 void HeatSystem::init_context(DiffContext & context)
80 {
81  FEMContext & c = cast_ref<FEMContext &>(context);
82 
83  FEBase * elem_fe = nullptr;
84  c.get_element_fe(0, elem_fe);
85 
86  // Now make sure we have requested all the data
87  // we need to build the linear system.
88  elem_fe->get_JxW();
89  elem_fe->get_dphi();
90 
91  // We'll have a more automatic solution to preparing adjoint
92  // solutions for time integration, eventually...
93  if (c.is_adjoint())
94  {
95  // A reference to the system context is built with
96  const System & sys = c.get_system();
97 
98  // Get a pointer to the adjoint solution vector
99  NumericVector<Number> & adjoint_solution =
100  const_cast<System &>(sys).get_adjoint_solution(0);
101 
102  // Add this adjoint solution to the vectors that diff context should localize
103  c.add_localized_vector(adjoint_solution, sys);
104  }
105 
106  FEMSystem::init_context(context);
107 }
108 
109 #define optassert(X) {if (!(X)) libmesh_error_msg("Assertion " #X " failed.");}
110 //#define optassert(X) libmesh_assert(X);
111 
112 bool HeatSystem::element_time_derivative (bool request_jacobian,
113  DiffContext & context)
114 {
115  bool compute_jacobian = request_jacobian && _analytic_jacobians;
116 
117  FEMContext & c = cast_ref<FEMContext &>(context);
118 
119  // First we get some references to cell-specific data that
120  // will be used to assemble the linear system.
121  FEBase * elem_fe = nullptr;
122  c.get_element_fe(0, elem_fe);
123 
124  // Element Jacobian * quadrature weights for interior integration
125  const std::vector<Real> & JxW = elem_fe->get_JxW();
126 
127  // Element basis functions
128  const std::vector<std::vector<RealGradient>> & dphi = elem_fe->get_dphi();
129 
130  // The number of local degrees of freedom in each variable
131  const unsigned int n_u_dofs = c.n_dof_indices(0);
132 
133  // The subvectors and submatrices we need to fill:
134  DenseSubMatrix<Number> & K = c.get_elem_jacobian(0, 0);
135  DenseSubVector<Number> & F = c.get_elem_residual(0);
136 
137  // Now we will build the element Jacobian and residual.
138  // Constructing the residual requires the solution and its
139  // gradient from the previous timestep. This must be
140  // calculated at each quadrature point by summing the
141  // solution degree-of-freedom values by the appropriate
142  // weight functions.
143  unsigned int n_qpoints = c.get_element_qrule().n_points();
144 
145  for (unsigned int qp=0; qp != n_qpoints; qp++)
146  {
147  // Compute the solution gradient at the Newton iterate
148  Gradient grad_T = c.interior_gradient(0, qp);
149 
150  for (unsigned int i=0; i != n_u_dofs; i++)
151  F(i) += JxW[qp] * -parameters[0] * (grad_T * dphi[i][qp]);
152  if (compute_jacobian)
153  for (unsigned int i=0; i != n_u_dofs; i++)
154  for (unsigned int j=0; j != n_u_dofs; ++j)
155  K(i,j) += JxW[qp] * -parameters[0] * (dphi[i][qp] * dphi[j][qp]);
156  } // end of the quadrature point qp-loop
157 
158  return compute_jacobian;
159 }
160 
161 // Perturb and accumulate dual weighted residuals
162 void HeatSystem::perturb_accumulate_residuals(ParameterVector & parameters_in)
163 {
164  this->update();
165 
166  for (std::size_t j=0, Np = parameters_in.size(); j != Np; ++j)
167  {
168  Number old_parameter = *parameters_in[j];
169 
170  *parameters_in[j] = old_parameter - dp;
171 
172  this->assembly(true, false);
173 
174  this->rhs->close();
175 
176  std::unique_ptr<NumericVector<Number>> R_minus = this->rhs->clone();
177 
178  // The contribution at a single time step would be [f(z;p+dp) - <partialu/partialt, z>(p+dp) - <g(u),z>(p+dp)] * dt
179  // But since we compute the residual already scaled by dt, there is no need for the * dt
180  R_minus_dp += -R_minus->dot(this->get_adjoint_solution(0));
181 
182  *parameters_in[j] = old_parameter + dp;
183 
184  this->assembly(true, false);
185 
186  this->rhs->close();
187 
188  std::unique_ptr<NumericVector<Number>> R_plus = this->rhs->clone();
189 
190  R_plus_dp += -R_plus->dot(this->get_adjoint_solution(0));
191 
192  *parameters_in[j] = old_parameter;
193  }
194 }
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::System::get_equation_systems
const EquationSystems & get_equation_systems() const
Definition: system.h:720
libMesh::DifferentiablePhysics::time_evolving
virtual void time_evolving(unsigned int var)
Tells the DiffSystem that variable var is evolving with respect to time.
Definition: diff_physics.h:250
HeatSystem::init_context
virtual void init_context(DiffContext &context)
Definition: heatsystem.C:79
libMesh::ExplicitSystem::rhs
NumericVector< Number > * rhs
The system matrix.
Definition: explicit_system.h:114
compute_jacobian
void compute_jacobian(const NumericVector< Number > &, SparseMatrix< Number > &J, NonlinearImplicitSystem &system)
Definition: assembly.C:311
libMesh::DofMap::add_dirichlet_boundary
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
Definition: dof_map_constraints.C:4390
HeatSystem::_fe_order
unsigned int _fe_order
Definition: heatsystem.h:122
libMesh::System::get_adjoint_solution
NumericVector< Number > & get_adjoint_solution(unsigned int i=0)
Definition: system.C:957
HeatSystem::perturb_accumulate_residuals
void perturb_accumulate_residuals(ParameterVector &parameters)
Definition: heatsystem.C:162
libMesh::NumericVector::close
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
libMesh::NumericVector::clone
virtual std::unique_ptr< NumericVector< T > > clone() const =0
libMesh::boundary_id_type
int8_t boundary_id_type
Definition: id_types.h:51
libMesh::zero
const Number zero
.
Definition: libmesh.h:243
libMesh::LOCAL_VARIABLE_ORDER
Definition: dirichlet_boundaries.h:62
HeatSystem::_fe_family
std::string _fe_family
Definition: heatsystem.h:121
HeatSystem::init_data
virtual void init_data()
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
Definition: heatsystem.C:36
libMesh::FEBase
FEGenericBase< Real > FEBase
Definition: exact_error_estimator.h:39
HeatSystem::R_plus_dp
Number R_plus_dp
Definition: heatsystem.h:131
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
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::System::System
System(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
Definition: system.C:61
HeatSystem::R_minus_dp
Number R_minus_dp
Definition: heatsystem.h:132
HeatSystem::element_time_derivative
virtual bool element_time_derivative(bool request_jacobian, DiffContext &context)
Adds the time derivative contribution on elem to elem_residual.
Definition: heatsystem.C:112
HeatSystem::dp
Real dp
Definition: heatsystem.h:135
libMesh::FEMSystem::assembly
virtual void assembly(bool get_residual, bool get_jacobian, bool apply_heterogeneous_constraints=false, bool apply_no_constraints=false) override
Prepares matrix or rhs for matrix assembly.
Definition: fem_system.C:850
libMesh::Parameters::set
T & set(const std::string &)
Definition: parameters.h:460
libMesh::Gradient
NumberVectorValue Gradient
Definition: exact_solution.h:58
HeatSystem::_k
Real _k
Definition: heatsystem.h:112
HeatSystem::parameters
std::vector< Number > parameters
Definition: heatsystem.h:105
HeatSystem::T_var
unsigned int T_var
Definition: heatsystem.h:125
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
HeatSystem::_analytic_jacobians
bool _analytic_jacobians
Definition: heatsystem.h:128
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::System::update
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition: system.C:408
libMesh::EquationSystems::parameters
Parameters parameters
Data structure holding arbitrary parameters.
Definition: equation_systems.h:557