[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
symmetric_functional_hessian.cpp
1 #include <Epetra_RowMatrixTransposer.h>
2 
3 #include <deal.II/base/conditional_ostream.h>
4 
5 #include <deal.II/distributed/tria.h>
6 #include <deal.II/grid/grid_generator.h>
7 #include <deal.II/grid/grid_tools.h>
8 
9 #include <deal.II/numerics/vector_tools.h>
10 
11 #include "physics/physics_factory.h"
12 #include "parameters/all_parameters.h"
13 #include "dg/dg_factory.hpp"
14 #include "functional/functional.h"
15 
16 #if PHILIP_DIM==1
17  using Triangulation = dealii::Triangulation<PHILIP_DIM>;
18 #else
19  using Triangulation = dealii::parallel::distributed::Triangulation<PHILIP_DIM>;
20 #endif
21 
22 const double STEPSIZE = 1e-7;
23 const double TOLERANCE = 1e-6;
24 
26 template <int dim, int nspecies, int nstate, typename real>
27 class L2_Norm_Functional : public PHiLiP::Functional<dim, nspecies, nstate, real>
28 {
29  using FadType = Sacado::Fad::DFad<double>;
30  using FadFadType = Sacado::Fad::DFad<FadType>;
31 
32 public:
35  std::shared_ptr<PHiLiP::DGBase<dim,nspecies,real>> dg_input,
36  const bool uses_solution_values = true,
37  const bool uses_solution_gradient = false)
38  : PHiLiP::Functional<dim,nspecies,nstate,real>(dg_input,uses_solution_values,uses_solution_gradient)
39  {}
40 
42  template <typename real2>
45  const dealii::Point<dim,real2> &phys_coord,
46  const std::array<real2,nstate> &soln_at_q,
47  const std::array<dealii::Tensor<1,dim,real2>,nstate> &/*soln_grad_at_q*/) const
48  {
49  real2 l2error = 0;
50 
51  for (int istate=0; istate<nstate; ++istate) {
52  const real2 uexact = physics.manufactured_solution_function->value(phys_coord, istate);
53  l2error += std::pow(soln_at_q[istate] - uexact, 2);
54  }
55 
56  return l2error;
57  }
58 
59 
61 
62  template<typename real2>
65  const unsigned int /*boundary_id*/,
66  const dealii::Point<dim,real2> &phys_coord,
67  const dealii::Tensor<1,dim,real2> &/*normal*/,
68  const std::array<real2,nstate> &soln_at_q,
69  const std::array<dealii::Tensor<1,dim,real2>,nstate> &/*soln_grad_at_q*/) const
70  {
71  real2 l1error = 0;
72  for (int istate=0; istate<nstate; ++istate) {
73  const real2 uexact = physics.manufactured_solution_function->value(phys_coord, istate);
74  l1error += std::abs(soln_at_q[istate] - uexact);
75  }
76  return l1error;
77  }
78 
80 
83  const unsigned int boundary_id,
84  const dealii::Point<dim,real> &phys_coord,
85  const dealii::Tensor<1,dim,real> &normal,
86  const std::array<real,nstate> &soln_at_q,
87  const std::array<dealii::Tensor<1,dim,real>,nstate> &soln_grad_at_q) const override
88  {
89  return evaluate_boundary_integrand<real>(
90  physics,
91  boundary_id,
92  phys_coord,
93  normal,
94  soln_at_q,
95  soln_grad_at_q);
96  }
98 
101  const unsigned int boundary_id,
102  const dealii::Point<dim,FadFadType> &phys_coord,
103  const dealii::Tensor<1,dim,FadFadType> &normal,
104  const std::array<FadFadType,nstate> &soln_at_q,
105  const std::array<dealii::Tensor<1,dim,FadFadType>,nstate> &soln_grad_at_q) const override
106  {
107  return evaluate_boundary_integrand<FadFadType>(
108  physics,
109  boundary_id,
110  phys_coord,
111  normal,
112  soln_at_q,
113  soln_grad_at_q);
114  }
115 
116 
120  const dealii::Point<dim,real> &phys_coord,
121  const std::array<real,nstate> &soln_at_q,
122  const std::array<dealii::Tensor<1,dim,real>,nstate> &soln_grad_at_q) const override
123  {
124  return evaluate_volume_integrand<>(physics, phys_coord, soln_at_q, soln_grad_at_q);
125  }
129  const dealii::Point<dim,FadFadType> &phys_coord,
130  const std::array<FadFadType,nstate> &soln_at_q,
131  const std::array<dealii::Tensor<1,dim,FadFadType>,nstate> &soln_grad_at_q) const override
132  {
133  return evaluate_volume_integrand<>(physics, phys_coord, soln_at_q, soln_grad_at_q);
134  }
135 
136 };
137 
138 
139 template <int dim, int nspecies, int nstate>
141 {
142  dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
143  solution_no_ghost.reinit(dg.locally_owned_dofs, MPI_COMM_WORLD);
144  dealii::VectorTools::interpolate(dg.dof_handler, *physics.manufactured_solution_function, solution_no_ghost);
145  dg.solution = solution_no_ghost;
146 }
147 
148 int main(int argc, char *argv[])
149 {
150 
151  const int dim = PHILIP_DIM;
152  const int nspecies = 1;
153  const int nstate = 1;
154  int fail_bool = false;
155 
156  // Initializing MPI
157  dealii::Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
158  const int this_mpi_process = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
159  dealii::ConditionalOStream pcout(std::cout, this_mpi_process==0);
160 
161  // Initializing parameter handling
162  dealii::ParameterHandler parameter_handler;
164  PHiLiP::Parameters::AllParameters all_parameters;
165  all_parameters.parse_parameters(parameter_handler);
166 
167  // polynomial order and mesh size
168  const unsigned poly_degree = 1;
169 
170  // creating the grid
171  std::shared_ptr<Triangulation> grid = std::make_shared<Triangulation>(
172 #if PHILIP_DIM!=1
173  MPI_COMM_WORLD,
174 #endif
175  typename dealii::Triangulation<dim>::MeshSmoothing(
176  dealii::Triangulation<dim>::smoothing_on_refinement |
177  dealii::Triangulation<dim>::smoothing_on_coarsening));
178 
179  const unsigned int n_refinements = 2;
180  double left = 0.0;
181  double right = 2.0;
182  const bool colorize = true;
183 
184  dealii::GridGenerator::hyper_cube(*grid, left, right, colorize);
185  grid->refine_global(n_refinements);
186  const double random_factor = 0.2;
187  const bool keep_boundary = false;
188  if (random_factor > 0.0) dealii::GridTools::distort_random (random_factor, *grid, keep_boundary);
189 
190  pcout << "Grid generated and refined" << std::endl;
191 
192  // creating the dg
193  std::shared_ptr < PHiLiP::DGBase<dim, nspecies, double> > dg = PHiLiP::DGFactory<dim,nspecies,double>::create_discontinuous_galerkin(&all_parameters, poly_degree, grid);
194  pcout << "dg created" << std::endl;
195 
196  dg->allocate_system();
197  pcout << "dg allocated" << std::endl;
198 
199  const int n_refine = 2;
200  for (int i=0; i<n_refine;i++) {
201  dg->high_order_grid->prepare_for_coarsening_and_refinement();
202  grid->prepare_coarsening_and_refinement();
203  unsigned int icell = 0;
204  for (auto cell = grid->begin_active(); cell!=grid->end(); ++cell) {
205  icell++;
206  if (!cell->is_locally_owned()) continue;
207  if (icell < grid->n_global_active_cells()/2) {
208  cell->set_refine_flag();
209  }
210  }
211  grid->execute_coarsening_and_refinement();
212  bool mesh_out = (i==n_refine-1);
213  dg->high_order_grid->execute_coarsening_and_refinement(mesh_out);
214  }
215  dg->allocate_system ();
216 
217  // manufactured solution function
218  using FadType = Sacado::Fad::DFad<double>;
219  std::shared_ptr <PHiLiP::Physics::PhysicsBase<dim,nspecies,nstate,double>> physics_double = PHiLiP::Physics::PhysicsFactory<dim, nspecies, nstate, double>::create_Physics(&all_parameters);
220  pcout << "Physics created" << std::endl;
221 
222  // performing the interpolation for the intial conditions
223  initialize_perturbed_solution(*dg, *physics_double);
224  pcout << "solution initialized" << std::endl;
225 
226  // evaluating the derivative (using SACADO)
227  pcout << std::endl << "Starting Hessian AD... " << std::endl;
228  L2_Norm_Functional<dim,nspecies,nstate,double> functional(dg,true,false);
229  const bool compute_dIdW = false, compute_dIdX = false, compute_d2I = true;
230  double functional_value = functional.evaluate_functional(compute_dIdW, compute_dIdX, compute_d2I);
231  (void) functional_value;
232 
233  dealii::TrilinosWrappers::SparseMatrix d2IdWdW_transpose;
234  {
235  Epetra_CrsMatrix *transpose_CrsMatrix;
236  Epetra_RowMatrixTransposer epmt(const_cast<Epetra_CrsMatrix *>(&functional.d2IdWdW->trilinos_matrix()));
237  epmt.CreateTranspose(false, transpose_CrsMatrix);
238  d2IdWdW_transpose.reinit(*transpose_CrsMatrix);
239  d2IdWdW_transpose.add(-1.0,*functional.d2IdWdW);
240  }
241 
242  dealii::TrilinosWrappers::SparseMatrix d2IdXdX_transpose;
243  {
244  Epetra_CrsMatrix *transpose_CrsMatrix;
245  Epetra_RowMatrixTransposer epmt(const_cast<Epetra_CrsMatrix *>(&functional.d2IdXdX->trilinos_matrix()));
246  epmt.CreateTranspose(false, transpose_CrsMatrix);
247  d2IdXdX_transpose.reinit(*transpose_CrsMatrix);
248  d2IdXdX_transpose.add(-1.0,*functional.d2IdXdX);
249  }
250  // {
251  // dealii::FullMatrix<double> fullA(functional.d2IdWdW.m());
252  // fullA.copy_from(functional.d2IdWdW);
253  // pcout<<"d2IdWdW:"<<std::endl;
254  // if (pcout.is_active()) fullA.print_formatted(pcout.get_stream(), 3, true, 10, "0", 1., 0.);
255  // }
256 
257  // {
258  // dealii::FullMatrix<double> fullA(functional.d2IdXdX.m());
259  // fullA.copy_from(functional.d2IdXdX);
260  // pcout<<"d2IdXdX:"<<std::endl;
261  // if (pcout.is_active()) fullA.print_formatted(pcout.get_stream(), 3, true, 10, "0", 1., 0.);
262  // }
263 
264  pcout << "functional.d2IdWdW.frobenius_norm() " << functional.d2IdWdW->frobenius_norm() << std::endl;
265  pcout << "functional.d2IdXdX.frobenius_norm() " << functional.d2IdXdX->frobenius_norm() << std::endl;
266 
267  const double d2IdWdW_norm = functional.d2IdWdW->frobenius_norm();
268  const double d2IdWdW_abs_diff = d2IdWdW_transpose.frobenius_norm();
269  const double d2IdWdW_rel_diff = d2IdWdW_abs_diff / d2IdWdW_norm;
270 
271  const double d2IdXdX_norm = functional.d2IdXdX->frobenius_norm();
272  const double d2IdXdX_abs_diff = d2IdXdX_transpose.frobenius_norm();
273  const double d2IdXdX_rel_diff = d2IdXdX_abs_diff / d2IdXdX_norm;
274 
275  const double tol = 1e-11;
276  pcout << "Error: "
277  << " d2IdWdW_abs_diff: " << d2IdWdW_abs_diff
278  << " d2IdWdW_rel_diff: " << d2IdWdW_rel_diff
279  << std::endl
280  << " d2IdXdX_abs_diff: " << d2IdXdX_abs_diff
281  << " d2IdXdX_rel_diff: " << d2IdXdX_rel_diff
282  << std::endl;
283  if (d2IdWdW_abs_diff > tol && d2IdWdW_rel_diff > tol) fail_bool = true;
284  if (d2IdXdX_abs_diff > tol && d2IdXdX_rel_diff > tol) fail_bool = true;
285 
286  return fail_bool;
287 }
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > d2IdWdW
Sparse matrix for storing the functional partial second derivatives.
Definition: functional.h:124
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Base class from which Advection, Diffusion, ConvectionDiffusion, and Euler is derived.
Definition: physics.h:34
real2 evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real2 > &physics, const dealii::Point< dim, real2 > &phys_coord, const std::array< real2, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &) const
Templated volume integrand.
Functional(std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real, dealii::parallel::distributed::Triangulation< dim > >> _dg, const bool _uses_solution_values=true, const bool _uses_solution_gradient=true)
virtual real evaluate_boundary_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real > &physics, const unsigned int boundary_id, const dealii::Point< dim, real > &phys_coord, const dealii::Tensor< 1, dim, real > &normal, const std::array< real, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real >, nstate > &soln_grad_at_q) const override
Virtual function for computation of cell boundary functional term.
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::shared_ptr< DGBase< dim, nspecies, real, dealii::parallel::distributed::Triangulation< dim > > > dg
Smart pointer to DGBase.
Definition: functional.h:50
std::shared_ptr< ManufacturedSolutionFunction< dim, nspecies, real > > manufactured_solution_function
Manufactured solution function.
Definition: physics.h:71
real evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real > &physics, const dealii::Point< dim, real > &phys_coord, const std::array< real, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real >, nstate > &soln_grad_at_q) const override
Non-template functions to override the template classes.
Main parameter class that contains the various other sub-parameter classes.
virtual real evaluate_functional(const bool compute_dIdW=false, const bool compute_dIdX=false, const bool compute_d2I=false)
Evaluates the functional derivative with respect to the solution variable.
Definition: functional.cpp:794
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
Definition: dg_base.hpp:1175
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > d2IdXdX
Sparse matrix for storing the functional partial second derivatives.
Definition: functional.h:128
const bool uses_solution_values
Will evaluate solution values at quadrature points.
Definition: functional.h:314
dealii::IndexSet locally_owned_dofs
Locally own degrees of freedom.
Definition: dg_base.hpp:398
const bool uses_solution_gradient
Will evaluate solution gradient at quadrature points.
Definition: functional.h:315
static std::shared_ptr< DGBase< dim, nspecies, real, MeshType > > create_discontinuous_galerkin(const Parameters::AllParameters *const parameters_input, const unsigned int degree, const unsigned int max_degree_input, const unsigned int grid_degree_input, const std::shared_ptr< Triangulation > triangulation_input)
Creates a derived object DG, but returns it as DGBase.
Definition: dg_factory.cpp:11
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
Definition: dg_base.hpp:409
L2_Norm_Functional(std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real >> dg_input, const bool uses_solution_values=true, const bool uses_solution_gradient=false)
Constructor.
void parse_parameters(dealii::ParameterHandler &prm)
Retrieve parameters from dealii::ParameterHandler.
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
Definition: functional.h:317
Sacado::Fad::DFad< real > FadType
Sacado AD type for first derivatives.
static std::shared_ptr< PhysicsBase< dim, nspecies, nstate, real > > create_Physics(const Parameters::AllParameters *const parameters_input, std::shared_ptr< ModelBase< dim, nspecies, nstate, real > > model_input=nullptr)
Factory to return the correct physics given input file.
real2 evaluate_boundary_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real2 > &physics, const unsigned int, const dealii::Point< dim, real2 > &phys_coord, const dealii::Tensor< 1, dim, real2 > &, const std::array< real2, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &) const
Virtual function for computation of cell boundary functional term.
FadFadType evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, FadFadType > &physics, const dealii::Point< dim, FadFadType > &phys_coord, const std::array< FadFadType, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, FadFadType >, nstate > &soln_grad_at_q) const override
Non-template functions to override the template classes.
Functional base class.
Definition: functional.h:43
static void declare_parameters(dealii::ParameterHandler &prm)
Declare parameters that can be set as inputs and set up the default options.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
virtual FadFadType evaluate_boundary_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, FadFadType > &physics, const unsigned int boundary_id, const dealii::Point< dim, FadFadType > &phys_coord, const dealii::Tensor< 1, dim, FadFadType > &normal, const std::array< FadFadType, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, FadFadType >, nstate > &soln_grad_at_q) const override
Virtual function for Sacado computation of cell boundary functional term and derivatives.