[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
set_initial_condition.cpp
1 #include "set_initial_condition.h"
2 #include "parameters/parameters_flow_solver.h"
3 #include "limiter/bound_preserving_limiter_factory.hpp"
4 
5 #include <deal.II/numerics/vector_tools.h>
6 #include <string>
7 #include <stdlib.h>
8 #include <sstream>
9 #include <iostream>
10 #include <fstream>
11 // #include <deal.II/lac/affine_constraints.h>
12 
13 namespace PHiLiP{
14 
15 template<int dim, int nspecies, int nstate, typename real>
17  std::shared_ptr< InitialConditionFunction<dim,nspecies,nstate,double> > initial_condition_function_input,
18  std::shared_ptr< PHiLiP::DGBase<dim, nspecies, real> > dg_input,
19  const Parameters::AllParameters *const parameters_input)
20 {
21  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
22 
23  // Set initial condition depending on the method
24  using ApplyInitialConditionMethodEnum = Parameters::FlowSolverParam::ApplyInitialConditionMethod;
25  const ApplyInitialConditionMethodEnum apply_initial_condition_method = parameters_input->flow_solver_param.apply_initial_condition_method;
26 
27  pcout << "Initializing solution by " << std::flush;
28  if(apply_initial_condition_method == ApplyInitialConditionMethodEnum::interpolate_initial_condition_function) {
29  pcout << "interpolating the initial condition function... " << std::flush;
30  // for non-curvilinear
31  SetInitialCondition<dim,nspecies,nstate,real>::interpolate_initial_condition(initial_condition_function_input, dg_input);
32  } else if(apply_initial_condition_method == ApplyInitialConditionMethodEnum::project_initial_condition_function) {
33  pcout << "projecting the initial condition function... " << std::flush;
34  // for curvilinear
35  SetInitialCondition<dim,nspecies,nstate,real>::project_initial_condition(initial_condition_function_input, dg_input);
36  } else if(apply_initial_condition_method == ApplyInitialConditionMethodEnum::read_values_from_file_and_project) {
37  const std::string input_filename_prefix = parameters_input->flow_solver_param.input_flow_setup_filename_prefix;
38  pcout << "reading values from file prefix " << input_filename_prefix << " and projecting... " << std::flush;
40  }
41  pcout << "done." << std::endl;
42 }
43 
44 template<int dim, int nspecies, int nstate, typename real>
46  std::shared_ptr< InitialConditionFunction<dim,nspecies,nstate,double> > &initial_condition_function,
47  std::shared_ptr < PHiLiP::DGBase<dim,nspecies,real> > &dg)
48 {
49  dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
50  solution_no_ghost.reinit(dg->locally_owned_dofs, MPI_COMM_WORLD);
51  dealii::VectorTools::interpolate(dg->dof_handler,*initial_condition_function,solution_no_ghost);
52  dg->solution = solution_no_ghost;
53  // Limit the solution so the interpolation doesn't return nonphysical values
54  using limiter_enum = Parameters::LimiterParam::LimiterType;
55  if (dg->all_parameters->limiter_param.use_tvb_limiter || dg->all_parameters->limiter_param.bound_preserving_limiter == limiter_enum::positivity_preservingWang2012) {
56  std::unique_ptr<BoundPreservingLimiter<dim,nspecies,real>> limiter = BoundPreservingLimiterFactory<dim, nspecies, dim+nspecies+1, real>::create_limiter(dg->all_parameters);
57  limiter->limit(dg->solution,
58  dg->dof_handler,
59  dg->fe_collection,
60  dg->volume_quadrature_collection,
61  dg->high_order_grid->fe_system.tensor_degree(),
62  dg->max_degree,
63  dg->oneD_fe_collection_1state,
64  dg->oneD_quadrature_collection,
65  dg->all_parameters->ode_solver_param.initial_time_step);
66  }
67 }
68 
69 template<int dim, int nspecies, int nstate, typename real>
71  std::shared_ptr< InitialConditionFunction<dim,nspecies,nstate,double> > &initial_condition_function,
72  std::shared_ptr < PHiLiP::DGBase<dim,nspecies,real> > &dg)
73 {
74  // Commented since this has not yet been tested
75  // dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
76  // solution_no_ghost.reinit(dg->locally_owned_dofs, MPI_COMM_WORLD);
77  // dealii::AffineConstraints affine_constraints(dof_handler.locally_owned_dofs());
78  // dealii::VectorTools::project(*(dg->high_order_grid->mapping_fe_field),dg->dof_handler,affine_constraints,dg->volume_quadrature_collection,*initial_condition_function,solution_no_ghost);
79  // dg->solution = solution_no_ghost;
80 
81  //Note that for curvilinear, can't use dealii interpolate since it doesn't project at the correct order.
82  //Thus we interpolate it directly.
83  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
84  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
85  dealii::hp::FEValues<dim,dim> fe_values_collection(mapping_collection, dg->fe_collection, dg->volume_quadrature_collection,
86  dealii::update_quadrature_points);
87  const unsigned int max_dofs_per_cell = dg->dof_handler.get_fe_collection().max_dofs_per_cell();
88  std::vector<dealii::types::global_dof_index> current_dofs_indices(max_dofs_per_cell);
89  OPERATOR::vol_projection_operator<dim,2*dim> vol_projection(1, dg->max_degree, dg->max_grid_degree);
90  vol_projection.build_1D_volume_operator(dg->oneD_fe_collection_1state[dg->max_degree], dg->oneD_quadrature_collection[dg->max_degree]);
91  for (auto current_cell = dg->dof_handler.begin_active(); current_cell!=dg->dof_handler.end(); ++current_cell) {
92  if (!current_cell->is_locally_owned()) continue;
93 
94  const int i_fele = current_cell->active_fe_index();
95  const int i_quad = i_fele;
96  const int i_mapp = 0;
97  fe_values_collection.reinit (current_cell, i_quad, i_mapp, i_fele);
98  const dealii::FEValues<dim,dim> &fe_values = fe_values_collection.get_present_fe_values();
99  const unsigned int poly_degree = i_fele;
100  const unsigned int n_quad_pts = dg->volume_quadrature_collection[poly_degree].size();
101  const unsigned int n_dofs_cell = dg->fe_collection[poly_degree].dofs_per_cell;
102  const unsigned int n_shape_fns = n_dofs_cell/nstate;
103  current_dofs_indices.resize(n_dofs_cell);
104  current_cell->get_dof_indices (current_dofs_indices);
105  for(int istate=0; istate<nstate; istate++){
106  std::vector<double> exact_value(n_quad_pts);
107  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
108  const dealii::Point<dim> qpoint = (fe_values.quadrature_point(iquad));
109  exact_value[iquad] = initial_condition_function->value(qpoint, istate);
110  }
111  std::vector<double> sol(n_shape_fns);
112  vol_projection.matrix_vector_mult_1D(exact_value, sol, vol_projection.oneD_vol_operator);
113  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
114  dg->solution[current_dofs_indices[ishape+istate*n_shape_fns]] = sol[ishape];
115  }
116  }
117  }
118 }
119 
120 std::string get_padded_mpi_rank_string(const int mpi_rank_input) {
121  // returns the mpi rank as a string with appropriate padding
122  std::string mpi_rank_string = std::to_string(mpi_rank_input);
123  const unsigned int length_of_mpi_rank_with_padding = 5;
124  const int number_of_zeros = length_of_mpi_rank_with_padding - mpi_rank_string.length();
125  mpi_rank_string.insert(0, number_of_zeros, '0');
126 
127  return mpi_rank_string;
128 }
129 
130 template<int dim, int nspecies, int nstate, typename real>
132  std::shared_ptr < PHiLiP::DGBase<dim,nspecies,real> > &dg,
133  const std::string input_filename_prefix)
134 {
135  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
136 
137  // (1) Get filename based on MPI rank
138  //-------------------------------------------------------------
139  const int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
140  // -- Get padded mpi rank string
141  const std::string mpi_rank_string = get_padded_mpi_rank_string(mpi_rank);
142  // -- Assemble filename string
143  const std::string filename_without_extension = input_filename_prefix + std::string("-") + mpi_rank_string;
144  const std::string filename = filename_without_extension + std::string(".dat");
145  //-------------------------------------------------------------
146 
147  // (2) Read file
148  //-------------------------------------------------------------
149  std::string line;
150  std::string::size_type sz1;
151 
152  std::ifstream FILE (filename);
153  std::getline(FILE, line); // read first line: DOFs
154 
155  // check that the file is not empty
156  if (line.empty()) {
157  pcout << "ERROR: Trying to read empty file named " << filename << std::endl;
158  std::abort();
159  } else {
160  const unsigned int number_of_degrees_of_freedom_per_state_DG = dg->dof_handler.n_dofs()/nstate;
161  const unsigned int number_of_degrees_of_freedom_per_state_file = std::stoi(line);
162  if(number_of_degrees_of_freedom_per_state_file != number_of_degrees_of_freedom_per_state_DG) {
163  pcout << "ERROR: Cannot read initial condition. "
164  << "Number of degrees of freedom per state do not match expected by DG in file: "
165  << filename << "\n Aborting..." << std::endl;
166  std::abort();
167  }
168  }
169 
170  std::getline(FILE, line); // read first line of data
171 
172  // check that there indeed is data to be read
173  if (line.empty()) {
174  pcout << "Error: File has no data to be read" << std::endl;
175  std::abort();
176  }
177 
178  // Commented since this has not yet been tested
179  // dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
180  // solution_no_ghost.reinit(dg->locally_owned_dofs, MPI_COMM_WORLD);
181  // dealii::AffineConstraints affine_constraints(dof_handler.locally_owned_dofs());
182  // dealii::VectorTools::project(*(dg->high_order_grid->mapping_fe_field),dg->dof_handler,affine_constraints,dg->volume_quadrature_collection,*initial_condition_function,solution_no_ghost);
183  // dg->solution = solution_no_ghost;
184 
185  //Note that for curvilinear, can't use dealii interpolate since it doesn't project at the correct order.
186  //Thus we interpolate it directly.
187  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
188  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
189  dealii::hp::FEValues<dim,dim> fe_values_collection(mapping_collection, dg->fe_collection, dg->volume_quadrature_collection,
190  dealii::update_quadrature_points);
191  const unsigned int max_dofs_per_cell = dg->dof_handler.get_fe_collection().max_dofs_per_cell();
192  std::vector<dealii::types::global_dof_index> current_dofs_indices(max_dofs_per_cell);
193  OPERATOR::vol_projection_operator<dim,2*dim> vol_projection(1, dg->max_degree, dg->max_grid_degree);
194  vol_projection.build_1D_volume_operator(dg->oneD_fe_collection_1state[dg->max_degree], dg->oneD_quadrature_collection[dg->max_degree]);
195  for (auto current_cell = dg->dof_handler.begin_active(); current_cell!=dg->dof_handler.end(); ++current_cell) {
196  if (!current_cell->is_locally_owned()) continue;
197 
198  const int i_fele = current_cell->active_fe_index();
199  const int i_quad = i_fele;
200  const int i_mapp = 0;
201  fe_values_collection.reinit (current_cell, i_quad, i_mapp, i_fele);
202  const dealii::FEValues<dim,dim> &fe_values = fe_values_collection.get_present_fe_values();
203  const unsigned int poly_degree = i_fele;
204  const unsigned int n_quad_pts = dg->volume_quadrature_collection[poly_degree].size();
205  const unsigned int n_dofs_cell = dg->fe_collection[poly_degree].dofs_per_cell;
206  const unsigned int n_shape_fns = n_dofs_cell/nstate;
207  current_dofs_indices.resize(n_dofs_cell);
208  current_cell->get_dof_indices (current_dofs_indices);
209  for(int istate=0; istate<nstate; istate++){
210  std::vector<double> exact_value(n_quad_pts);
211  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
212  const dealii::Point<dim> qpoint = (fe_values.quadrature_point(iquad));
213 
214  // -- get point
215  dealii::Point<dim> current_point_read_from_file;
216  std::string dummy_line = line;
217  current_point_read_from_file[0] = std::stod(dummy_line,&sz1);
218  for(int i=1; i<dim; ++i) {
219  dummy_line = dummy_line.substr(sz1);
220  sz1 = 0;
221  current_point_read_from_file[i] = std::stod(dummy_line,&sz1);
222  }
223  if(qpoint.distance(current_point_read_from_file) > 1.0e-14) {
224  pcout << "ERROR: Distance between points is " << qpoint.distance(current_point_read_from_file)
225  << ".\n Aborting..." << std::endl;
226  std::abort();
227  }
228 
229  // -- get state
230  dummy_line = dummy_line.substr(sz1); sz1 = 0;
231  const int current_state_read_from_file = (int) std::stod(dummy_line,&sz1);
232  if(istate != current_state_read_from_file) {
233  pcout << "ERROR: Expecting to read state " << istate << " but reading state "
234  << current_state_read_from_file << ".\n Aborting..." << std::endl;
235  std::abort();
236  }
237  // -- get initial condition value
238  dummy_line = dummy_line.substr(sz1); sz1 = 0;
239  const double initial_condition_value = std::stod(dummy_line,&sz1);
240 
241  exact_value[iquad] = initial_condition_value; // store value for projection
242 
243  std::getline(FILE, line); // read next line
244  }
245  std::vector<double> sol(n_shape_fns);
246  vol_projection.matrix_vector_mult_1D(exact_value, sol, vol_projection.oneD_vol_operator);
247  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
248  dg->solution[current_dofs_indices[ishape+istate*n_shape_fns]] = sol[ishape];
249  }
250  }
251  }
252  if(!line.empty()) {
253  pcout << "ERROR: Line is not empty:\n" << line << std::endl;
254  pcout << "Aborting..." << std::endl;
255  }
256 }
257 
258 #if PHILIP_SPECIES==1
259  // Define a sequence of indices representing the range [1, 6]
260  #define POSSIBLE_NSTATE (1)(2)(3)(4)(5)(6)
261 
262  // Define a macro to instantiate SetIC Functions for a specific nstate
263  #define INSTANTIATE_SET_IC(r, data, nstate) \
264  template class SetInitialCondition<PHILIP_DIM, PHILIP_SPECIES, nstate, double>;
265  BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_SET_IC, _, POSSIBLE_NSTATE)
266 #else
268 #endif
269 }//end of namespace PHILIP
LimiterType
Limiter type to be applied on the solution.
FlowSolverParam flow_solver_param
Contains the parameters for simulation cases (flow solver test)
void matrix_vector_mult_1D(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the matrix vector operation using the 1D operator in each direction.
Definition: operators.cpp:402
static void interpolate_initial_condition(std::shared_ptr< InitialConditionFunction< dim, nspecies, nstate, double > > &initial_condition_function, std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real > > &dg)
Interpolates the initial condition function onto the dg solution.
Class for setting/applying the initial condition.
Files for the baseline physics.
Definition: ADTypes.hpp:10
static std::unique_ptr< BoundPreservingLimiter< dim, nspecies, real > > create_limiter(const Parameters::AllParameters *const parameters_input)
Recursively templated function that calls select_limiter when nstate is equal to one specified in prm...
Main parameter class that contains the various other sub-parameter classes.
static void set_initial_condition(std::shared_ptr< InitialConditionFunction< dim, nspecies, nstate, double > > initial_condition_function_input, std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real > > dg_input, const Parameters::AllParameters *const parameters_input)
Applies the given initial condition function to the given dg object.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
Definition: operators.h:380
Initial condition function used to initialize a particular flow setup/case.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1873
ApplyInitialConditionMethod
Selects the method for applying the initial condition.
static void project_initial_condition(std::shared_ptr< InitialConditionFunction< dim, nspecies, nstate, double > > &initial_condition_function, std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real > > &dg)
Projects the initial condition function physical value onto the dg solution modal coefficients...
static void read_values_from_file_and_project(std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real > > &dg, const std::string input_filename_prefix)
Reads values from file and projects.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
ApplyInitialConditionMethod apply_initial_condition_method
Selected ApplyInitialConditionMethod from the input file.
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:723