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