PRISMS-PF  v2.1
initialConditions.cc
Go to the documentation of this file.
1 //methods to apply initial conditions
2 
3 #include "../../include/matrixFreePDE.h"
4 #include "../../include/initialConditions.h"
5 #include "../../include/IntegrationTools/PField.hh"
6 #include "../../include/OrderParameterRemapper.h"
7 
8 
9 template <int dim>
10 class InitialConditionPField : public Function<dim>
11 {
12 public:
13  unsigned int index;
14  Vector<double> values;
15  typedef PRISMS::PField<double*, double, dim> ScalarField;
17 
18  InitialConditionPField (const unsigned int _index, ScalarField &_inputField) : Function<dim>(1), index(_index), inputField(_inputField) {}
19 
20  double value (const Point<dim> &p, const unsigned int component = 0) const
21  {
22  double scalar_IC;
23 
24  double coord[dim];
25  for (unsigned int i = 0; i < dim; i++){
26  coord[i] = p(i);
27  }
28 
29  scalar_IC = inputField(coord);
30 
31  return scalar_IC;
32  }
33 };
34 
35 
36 //methods to apply initial conditions
37 template <int dim, int degree>
39 
40  if (userInputs.load_grain_structure){
41  // Create the dummy field
42  vectorType grain_index_field;
43 
44  // Clear the order parameter fields
45  unsigned int op_list_index = 0;
46  for (unsigned int var_index=0; var_index < userInputs.number_of_variables; var_index++){
47  if (op_list_index < userInputs.variables_for_remapping.size()){
48  if (var_index == userInputs.variables_for_remapping.at(op_list_index)){
49  *solutionSet[var_index] = 0.0;
50  op_list_index++;
51  }
52  }
53  }
54 
55  simplified_grain_representations.clear();
56 
57  // Get the index of one of the scalar fields
58  unsigned int scalar_field_index = 0;
59  for (unsigned int var=0; var<userInputs.number_of_variables; var++){
60  if (userInputs.var_type.at(var) == SCALAR){
61  scalar_field_index = var;
62  break;
63  }
64  }
65 
66  matrixFreeObject.initialize_dof_vector (grain_index_field, scalar_field_index);
67 
68  // Declare the PField types and containers
69  typedef PRISMS::PField<double*, double, dim> ScalarField;
70  typedef PRISMS::Body<double*, dim> Body;
71  Body body;
72 
73  // Create the filename of the the file to be loaded
74 
75  // Load the data from the file using a PField
76  std::string filename = userInputs.grain_structure_filename;
77  filename += ".vtk";
78 
79  body.read_vtk(filename);
80  ScalarField &id_field = body.find_scalar_field(userInputs.grain_structure_variable_name);
81 
82  pcout << "Applying PField initial condition...\n";
83 
84  VectorTools::interpolate (*dofHandlersSet[scalar_field_index], InitialConditionPField<dim>(0,id_field), grain_index_field);
85 
86  grain_index_field.update_ghost_values();
87 
88  // Get the max and min grain ids
89  unsigned int max_id = (unsigned int)grain_index_field.linfty_norm();
90  unsigned int min_id = 0;
91 
92  // Now locate all of the grains and create simplified representations of them
93  QGaussLobatto<dim> quadrature2 (degree+1);
94  FloodFiller<dim, degree> flood_filler(*FESet.at(scalar_field_index), quadrature2);
95 
96  pcout << "Locating the grains...\n";
97  std::vector<GrainSet<dim>> grain_sets;
98  for (unsigned int id=min_id; id<max_id+1; id++){
99  pcout << "Locating grain " << id << "...\n";
100 
101  std::vector<GrainSet<dim>> grain_sets_single_id;
102 
103  flood_filler.calcGrainSets(*FESet.at(scalar_field_index), *dofHandlersSet_nonconst.at(scalar_field_index), &grain_index_field, (double)id - userInputs.order_parameter_threshold, (double)id + userInputs.order_parameter_threshold, 0, grain_sets_single_id);
104 
105  for (unsigned int g=0; g<grain_sets_single_id.size(); g++){
106  grain_sets_single_id.at(g).setGrainIndex(id);
107  }
108 
109  grain_sets.insert(grain_sets.end(), grain_sets_single_id.begin(), grain_sets_single_id.end());
110  }
111 
112  pcout << "Generating simplified representations of the grains...\n";
113  for (unsigned int g=0; g<grain_sets.size(); g++){
114  SimplifiedGrainRepresentation<dim> simplified_grain_representation(grain_sets.at(g));
115 
116  if (dim == 2){
117  pcout << "Grain: " << simplified_grain_representation.getGrainId() << " " << simplified_grain_representation.getOrderParameterId() << " Center: " << simplified_grain_representation.getCenter()(0) << " " << simplified_grain_representation.getCenter()(1) << " Radius: " << simplified_grain_representation.getRadius() << std::endl;
118  }
119  else {
120  pcout << "Grain: " << simplified_grain_representation.getGrainId() << " " << simplified_grain_representation.getOrderParameterId() << " Center: " << simplified_grain_representation.getCenter()(0) << " " << simplified_grain_representation.getCenter()(1) << " " << simplified_grain_representation.getCenter()(2) << " Radius: " << simplified_grain_representation.getRadius() << std::endl;
121  }
122 
123  simplified_grain_representations.push_back(simplified_grain_representation);
124  }
125 
126  // Delete grains with very small radii that correspond to a single interfacial element
127  for (unsigned int g=0; g<simplified_grain_representations.size(); g++){
128  if (simplified_grain_representations.at(g).getRadius() < userInputs.min_radius_for_loading_grains){
129  simplified_grain_representations.erase(simplified_grain_representations.begin()+g);
130  g--;
131  }
132  }
133 
134  pcout << "Reassigning the grains to new order parameters...\n";
135  SimplifiedGrainManipulator<dim> simplified_grain_manipulator;
136  simplified_grain_manipulator.reassignGrains(simplified_grain_representations, userInputs.buffer_between_grains, userInputs.variables_for_remapping);
137 
138  pcout << "After reassignment: " << std::endl;
139  for (unsigned int g=0; g<simplified_grain_representations.size(); g++){
140  if (dim == 2){
141  pcout << "Grain: " << simplified_grain_representations.at(g).getGrainId() << " " << simplified_grain_representations.at(g).getOrderParameterId() << " Center: " << simplified_grain_representations.at(g).getCenter()(0) << " " << simplified_grain_representations.at(g).getCenter()(1) << std::endl;
142  }
143  else {
144  pcout << "Grain: " << simplified_grain_representations.at(g).getGrainId() << " " << simplified_grain_representations.at(g).getOrderParameterId() << " Center: " << simplified_grain_representations.at(g).getCenter()(0) << " " << simplified_grain_representations.at(g).getCenter()(1) << " " << simplified_grain_representations.at(g).getCenter()(2) << std::endl;
145  }
146 
147  }
148 
149  pcout << "Placing the grains in their new order parameters...\n";
150  OrderParameterRemapper<dim> order_parameter_remapper;
151  order_parameter_remapper.remap_from_index_field(simplified_grain_representations, &grain_index_field, solutionSet, *dofHandlersSet_nonconst.at(scalar_field_index), FESet.at(scalar_field_index)->dofs_per_cell, userInputs.buffer_between_grains);
152 
153  // Smooth the order parameters
154  double dt_for_smoothing = dealii::GridTools::minimal_cell_diameter(triangulation)/1000.0;
155 
156  op_list_index = 0;
157  for(unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
158  if (op_list_index < userInputs.variables_for_remapping.size()){
159  if ( fieldIndex == userInputs.variables_for_remapping.at(op_list_index)){
160 
161  for (unsigned int cycle=0; cycle<userInputs.num_grain_smoothing_cycles; cycle++){
162  computeLaplaceRHS(fieldIndex);
163 
164  unsigned int invM_size = invM.local_size();
165  for (unsigned int dof=0; dof<solutionSet[fieldIndex]->local_size(); ++dof){
166  solutionSet[fieldIndex]->local_element(dof)=solutionSet[fieldIndex]->local_element(dof)-
167  invM.local_element(dof%invM_size)*residualSet[fieldIndex]->local_element(dof)*dt_for_smoothing;
168  }
169 
170  solutionSet[fieldIndex]->update_ghost_values();
171  }
172 
173  op_list_index++;
174  }
175  }
176  }
177 
178  }
179 
180  unsigned int op_list_index = 0;
181  for (unsigned int var_index=0; var_index < userInputs.number_of_variables; var_index++){
182 
183  bool is_remapped_op = false;
184  if (op_list_index < userInputs.variables_for_remapping.size()){
185  if (var_index == userInputs.variables_for_remapping.at(op_list_index)){
186  is_remapped_op = true;
187  op_list_index++;
188  }
189  }
190 
191 
192  if (!is_remapped_op || !userInputs.load_grain_structure){
193 
194  if (userInputs.load_ICs[var_index] == false){
195  pcout << "Applying non-PField initial condition...\n";
196 
197  if (userInputs.var_type[var_index] == SCALAR){
198  VectorTools::interpolate (*dofHandlersSet[var_index], InitialCondition<dim,degree>(var_index,userInputs,this), *solutionSet[var_index]);
199  }
200  else {
201  VectorTools::interpolate (*dofHandlersSet[var_index], InitialConditionVector<dim,degree>(var_index,userInputs,this), *solutionSet[var_index]);
202  }
203  }
204 
205  else {
206  // Declare the PField types and containers
207  typedef PRISMS::PField<double*, double, dim> ScalarField;
208  typedef PRISMS::Body<double*, dim> Body;
209  Body body;
210 
211  // Create the filename of the the file to be loaded
212  std::string filename;
213  if (userInputs.load_parallel_file[var_index] == false){
214  filename = userInputs.load_file_name[var_index] + ".vtk";
215  }
216  else {
217  int proc_num = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
218  std::ostringstream conversion;
219  conversion << proc_num;
220  filename = userInputs.load_file_name[var_index] + "." + conversion.str() + ".vtk";
221  }
222 
223  // Load the data from the file using a PField
224  body.read_vtk(filename);
225  ScalarField &conc = body.find_scalar_field(userInputs.load_field_name[var_index]);
226 
227  if (userInputs.var_type[var_index] == SCALAR){
228  pcout << "Applying PField initial condition...\n";
229  VectorTools::interpolate (*dofHandlersSet[var_index], InitialConditionPField<dim>(var_index,conc), *solutionSet[var_index]);
230  }
231  else {
232  std::cout << "PRISMS-PF Error: Cannot load vector fields. Loading initial conditions from file is currently limited to scalar fields" << std::endl;
233  }
234 
235  }
236 
237  pcout << "Application of initial conditions for field number " << var_index << " complete \n";
238  }
239  }
240 }
241 
242 
243 
244 
245 // =================================================================================
246 
247 // I don't think vector fields are implemented in PFields yet
248 //template <int dim>
249 //class InitialConditionPFieldVec : public Function<dim>
250 //{
251 //public:
252 // unsigned int index;
253 // Vector<double> values;
254 // typedef PRISMS::PField<double*, double, 2> ScalarField2D;
255 // ScalarField2D &inputField;
256 //
257 // InitialConditionPFieldVec (const unsigned int _index, ScalarField2D &_inputField) : Function<dim>(1), index(_index), inputField(_inputField) {}
258 //
259 // void vector_value (const Point<dim> &p,Vector<double> &vector_IC) const
260 // {
261 // double coord[dim];
262 // for (unsigned int i = 0; i < dim; i++){
263 // coord[i] = p(i);
264 // }
265 //
266 // vector_IC = inputField(coord);
267 // }
268 //};
269 
270 #include "../../include/matrixFreePDE_template_instantiations.h"
PRISMS::PField< double *, double, dim > ScalarField
void calcGrainSets(dealii::FESystem< dim > &fe, dealii::DoFHandler< dim > &dof_handler, vectorType *solution_field, double threshold_lower, double threshold_upper, unsigned int order_parameter_index, std::vector< GrainSet< dim >> &grain_sets)
Definition: FloodFiller.cc:5
void remap_from_index_field(std::vector< SimplifiedGrainRepresentation< dim >> &grain_representations, const vectorType *grain_index_field, std::vector< vectorType *> &solution_fields, dealii::DoFHandler< dim > &dof_handler, unsigned int dofs_per_cell, double buffer)
double value(const Point< dim > &p, const unsigned int component=0) const
void reassignGrains(std::vector< SimplifiedGrainRepresentation< dim >> &grain_representations, double buffer_distance, std::vector< unsigned int > order_parameter_id_list)
InitialConditionPField(const unsigned int _index, ScalarField &_inputField)
void applyInitialConditions()
dealii::parallel::distributed::Vector< double > vectorType
Definition: FloodFiller.h:15