2 #include "../../include/matrixFreePDE.h" 3 #include "../../include/parallelNucleationList.h" 4 #include "../../include/varBCs.h" 11 template <
int dim,
int degree>
14 if (userInputs.nucleation_occurs){
17 if (currentIncrement % userInputs.steps_between_nucleation_attempts == 0 || currentIncrement == 1){
18 computing_timer.enter_section(
"matrixFreePDE: nucleation");
21 for(
unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
22 constraintsDirichletSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
23 constraintsOtherSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
24 solutionSet[fieldIndex]->update_ghost_values();
27 std::vector<nucleus<dim> > new_nuclei;
29 if (currentIncrement == 1){
30 while (new_nuclei.size() == 0){
31 currentTime+=userInputs.dtValue*(double)userInputs.steps_between_nucleation_attempts;
32 currentIncrement+=userInputs.steps_between_nucleation_attempts;
34 while (userInputs.outputTimeStepList.size() > 0 && userInputs.outputTimeStepList[currentOutput] < currentIncrement){
38 while (userInputs.checkpointTimeStepList.size() > 0 && userInputs.checkpointTimeStepList[currentCheckpoint] < currentIncrement){
42 new_nuclei = getNewNuclei();
46 new_nuclei = getNewNuclei();
49 nuclei.insert(nuclei.end(),new_nuclei.begin(),new_nuclei.end());
51 if (new_nuclei.size() > 0 && userInputs.h_adaptivity ==
true){
52 refineMeshNearNuclei(new_nuclei);
55 computing_timer.exit_section(
"matrixFreePDE: nucleation");
64 template <
int dim,
int degree>
68 std::vector<nucleus<dim> > newnuclei;
71 pcout <<
"Nucleation attempt for increment " << currentIncrement << std::endl;
73 getLocalNucleiList(newnuclei);
74 pcout <<
"nucleation attempt! " << currentTime <<
" " << currentIncrement << std::endl;
78 newnuclei = new_nuclei_parallel.
buildGlobalNucleiList(userInputs.min_distance_between_nuclei, nuclei.size());
81 std::vector<unsigned int> conflict_ids;
82 safetyCheckNewNuclei(newnuclei, conflict_ids);
92 template <
int dim,
int degree>
97 unsigned int inc=currentIncrement;
100 QGaussLobatto<dim> quadrature(degree+1);
101 FEValues<dim> fe_values (*(FESet[0]), quadrature, update_values|update_quadrature_points|update_JxW_values);
102 const unsigned int num_quad_points = quadrature.size();
103 std::vector<std::vector<double> > var_values(userInputs.nucleation_need_value.size(),std::vector<double>(num_quad_points));
104 std::vector<dealii::Point<dim> > q_point_list(num_quad_points);
106 std::vector<dealii::Point<dim> > q_point_list_overlap(num_quad_points);
108 typename DoFHandler<dim>::active_cell_iterator di = dofHandlersSet_nonconst[0]->begin_active();
113 std::random_device rd;
114 std::mt19937 gen(rd());
115 std::uniform_real_distribution<> distr(0.0,1.0);
118 while (di != this->dofHandlersSet_nonconst[0]->end())
120 if (di->is_locally_owned()){
122 fe_values.reinit(di);
123 for (
unsigned int var = 0; var < userInputs.nucleation_need_value.size(); var++){
124 fe_values.get_function_values(*(solutionSet[userInputs.nucleation_need_value[var]]), var_values[var]);
126 q_point_list = fe_values.get_quadrature_points();
131 double element_volume = 0.0;
132 dealii::Point<dim> ele_center;
134 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
135 element_volume = element_volume + fe_values.JxW(q_point);
136 for (
unsigned int i=0; i<dim; i++)
137 ele_center[i]=ele_center[i]+q_point_list[q_point](i)/((double)num_quad_points);
142 for (
unsigned int var = 0; var < userInputs.nucleation_need_value.size(); var++){
143 double ele_val = 0.0;
144 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
145 ele_val = ele_val + var_values[var][q_point]*fe_values.JxW(q_point);
147 ele_val /= element_volume;
148 variable_values.
set(userInputs.nucleation_need_value[var],ele_val);
152 for (
unsigned int i = 0; i < userInputs.nucleating_variable_indices.size(); i++){
153 unsigned int variable_index = userInputs.nucleating_variable_indices.at(i);
158 double Prob=getNucleationProbability(variable_values,element_volume,ele_center,variable_index);
162 if (rand_val <= Prob){
165 std::vector<double> randvec(dim,0.0);
166 dealii::Point<dim> nuc_ele_pos;
169 std::vector<double> ele_origin(dim);
170 for (
unsigned int i=0; i<dim; i++)
171 ele_origin[i] = q_point_list[0](i);
172 std::vector<double> ele_max(dim);
173 for (
unsigned int i=0; i<dim; i++)
174 ele_max[i] = q_point_list[0](i);
175 for (
unsigned int i=0; i<dim; i++){
176 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
177 for (
unsigned int i=0; i<dim; i++){
178 if (q_point_list[q_point](i) < ele_origin[i])
179 ele_origin[i]=q_point_list[q_point](i);
180 if (q_point_list[q_point](i) > ele_max[i])
181 ele_max[i]=q_point_list[q_point](i);
187 for (
unsigned int j=0; j<dim; j++){
188 randvec[j]=distr(gen);
189 nuc_ele_pos[j]=ele_origin[j] + (ele_max[j]-ele_origin[j])*randvec[j];
193 bool insafetyzone =
true;
194 for (
unsigned int j=0; j < dim; j++){
195 bool periodic_j = (userInputs.BC_list[1].var_BC_type[2*j]==
PERIODIC);
196 bool insafetyzone_j = (periodic_j || ((nuc_ele_pos[j] > userInputs.get_no_nucleation_border_thickness(variable_index)) && (nuc_ele_pos[j] < userInputs.domain_size[j]-userInputs.get_no_nucleation_border_thickness(variable_index))));
197 insafetyzone = insafetyzone && insafetyzone_j;
203 bool anyqp_OK =
false;
204 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
206 for (
unsigned int var = 0; var < userInputs.nucleation_need_value.size(); var++){
207 for (
unsigned int op = 0; op < userInputs.nucleating_variable_indices.size(); op++){
208 if (userInputs.nucleation_need_value[var] == userInputs.nucleating_variable_indices[op]){
209 sum_op += var_values[var][q_point];
213 if (sum_op < userInputs.nucleation_order_parameter_cutoff){
229 std::cout <<
"Prospective nucleation event. Nucleus no. " << nuclei.size()+1 << std::endl;
230 std::cout <<
"Nucleus center: " << nuc_ele_pos << std::endl;
231 std::cout <<
"Nucleus order parameter: " << variable_index << std::endl;
233 temp->
index=nuclei.size();
235 temp->
semiaxes = userInputs.get_nucleus_semiaxes(variable_index);
237 temp->
seedingTime = userInputs.get_nucleus_hold_time(variable_index);
240 newnuclei.push_back(*temp);
254 template <
int dim,
int degree>
258 QGaussLobatto<dim> quadrature(degree+1);
259 FEValues<dim> fe_values (*(FESet[0]), quadrature, update_values|update_quadrature_points|update_JxW_values);
260 const unsigned int num_quad_points = quadrature.size();
261 std::vector<std::vector<double> > op_values(userInputs.nucleating_variable_indices.size(),std::vector<double>(num_quad_points));
262 std::vector<dealii::Point<dim> > q_point_list(num_quad_points);
265 for (
typename std::vector<
nucleus<dim> >::iterator thisNucleus=newnuclei.begin(); thisNucleus!=newnuclei.end(); ++thisNucleus){
269 typename DoFHandler<dim>::active_cell_iterator di = dofHandlersSet_nonconst[0]->begin_active();
270 while (di != dofHandlersSet_nonconst[0]->end())
272 if (di->is_locally_owned()){
273 fe_values.reinit(di);
274 for (
unsigned int var = 0; var < userInputs.nucleating_variable_indices.size(); var++){
275 fe_values.get_function_values(*(solutionSet[userInputs.nucleating_variable_indices[var]]), op_values[var]);
277 q_point_list = fe_values.get_quadrature_points();
280 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
282 double weighted_dist = weightedDistanceFromNucleusCenter(thisNucleus->center, userInputs.get_nucleus_freeze_semiaxes(thisNucleus->orderParameterIndex), q_point_list[q_point], thisNucleus->orderParameterIndex);
284 if (weighted_dist < 1.0){
286 for (
unsigned int num_op = 0; num_op < userInputs.nucleating_variable_indices.size(); num_op++){
287 sum_op += op_values[num_op][q_point];
291 std::cout <<
"Attempted nucleation failed due to overlap w/ existing particle!!!!!!" << std::endl;
292 conflict_ids.push_back(thisNucleus->index);
308 template <
int dim,
int degree>
312 QGaussLobatto<dim> quadrature(degree+1);
313 FEValues<dim> fe_values (*(FESet[0]), quadrature, update_values|update_quadrature_points|update_JxW_values);
314 const unsigned int num_quad_points = quadrature.size();
315 std::vector<dealii::Point<dim> > q_point_list(num_quad_points);
317 typename Triangulation<dim>::active_cell_iterator ti;
318 typename DoFHandler<dim>::active_cell_iterator di;
320 unsigned int numDoF_preremesh = totalDOFs;
322 for (
unsigned int remesh_index=0; remesh_index < (userInputs.max_refinement_level-userInputs.min_refinement_level); remesh_index++){
323 ti = triangulation.begin_active();
324 di = dofHandlersSet_nonconst[0]->begin_active();
325 while (di != dofHandlersSet_nonconst[0]->end()){
326 if (di->is_locally_owned()){
328 bool mark_refine =
false;
330 fe_values.reinit (di);
331 q_point_list = fe_values.get_quadrature_points();
334 double diag_dist = 0.0;
335 for (
unsigned int i=0; i<dim; i++){
336 diag_dist += (userInputs.domain_size[i]*userInputs.domain_size[i])/(userInputs.subdivisions[i]*userInputs.subdivisions[i]);
338 diag_dist = sqrt(diag_dist);
339 diag_dist /= 2.0*pow(2.0,ti->level());
341 for (
unsigned int q_point=0; q_point<num_quad_points; ++q_point){
342 for (
typename std::vector<
nucleus<dim> >::iterator thisNucleus=newnuclei.begin(); thisNucleus!=newnuclei.end(); ++thisNucleus){
345 double weighted_dist = weightedDistanceFromNucleusCenter(thisNucleus->center, userInputs.get_nucleus_freeze_semiaxes(thisNucleus->orderParameterIndex), q_point_list[q_point], thisNucleus->orderParameterIndex);
347 if (weighted_dist < 1.0 || thisNucleus->center.distance(q_point_list[q_point]) < diag_dist){
348 if ((
unsigned int)ti->level() < userInputs.max_refinement_level){
353 if (mark_refine)
break;
355 if (mark_refine)
break;
357 if (mark_refine) di->set_refine_flag();
367 if (totalDOFs == numDoF_preremesh)
break;
368 numDoF_preremesh = totalDOFs;
374 template <
int dim,
int degree>
376 const dealii::Point<dim,double> center,
377 const std::vector<double> semiaxes,
378 const dealii::Point<dim,double> q_point_loc,
379 const unsigned int var_index)
const 381 double weighted_dist = 0.0;
382 dealii::Tensor<1,dim,double> shortest_edist_tensor = center - q_point_loc;
383 for (
unsigned int i=0; i<dim; i++){
384 if (userInputs.BC_list[var_index].var_BC_type[2*i]==
PERIODIC){
385 shortest_edist_tensor[i] = shortest_edist_tensor[i]-round(shortest_edist_tensor[i]/userInputs.domain_size[i])*userInputs.domain_size[i];
388 shortest_edist_tensor = userInputs.get_nucleus_rotation_matrix(var_index) * shortest_edist_tensor;
389 for (
unsigned int i=0; i<dim; i++){
390 shortest_edist_tensor[i] /= semiaxes[i];
392 weighted_dist = shortest_edist_tensor.norm();
393 return weighted_dist;
398 template <
int dim,
int degree>
400 const dealii::Point<dim,double> center,
401 const std::vector<double> semiaxes,
402 const dealii::Point<dim,dealii::VectorizedArray<double> > q_point_loc,
403 const unsigned int var_index)
const 405 dealii::VectorizedArray<double> weighted_dist =
constV(0.0);
406 dealii::Tensor<1,dim,dealii::VectorizedArray<double> > shortest_edist_tensor;
407 for (
unsigned int j=0; j<dim; j++){
408 shortest_edist_tensor[j] = center(j) - q_point_loc(j);
410 if (userInputs.BC_list[var_index].var_BC_type[2*j]==
PERIODIC){
411 for (
unsigned k=0; k<q_point_loc(0).n_array_elements;k++){
412 shortest_edist_tensor[j][k] = shortest_edist_tensor[j][k]-round(shortest_edist_tensor[j][k]/userInputs.domain_size[j])*userInputs.domain_size[j];
416 shortest_edist_tensor = userInputs.get_nucleus_rotation_matrix(var_index) * shortest_edist_tensor;
417 for (
unsigned int j=0; j<dim; j++){
418 shortest_edist_tensor[j] /=
constV(semiaxes[j]);
420 weighted_dist = shortest_edist_tensor.norm_square();
421 for (
unsigned k=0; k<q_point_loc(0).n_array_elements;k++){
422 weighted_dist[k] = sqrt(weighted_dist[k]);
424 return weighted_dist;
428 #include "../../include/matrixFreePDE_template_instantiations.h" void getLocalNucleiList(std::vector< nucleus< dim > > &newnuclei) const
double weightedDistanceFromNucleusCenter(const dealii::Point< dim, double > center, const std::vector< double > semiaxes, const dealii::Point< dim, double > q_point_loc, const unsigned int var_index) const
dealii::Point< dim > center
std::vector< nucleus< dim > > getNewNuclei()
std::vector< nucleus< dim > > removeSubsetOfNuclei(std::vector< unsigned int > nuclei_to_remove, unsigned int nuclei_size)
void set(unsigned int global_variable_index, double variable_value)
std::vector< double > semiaxes
unsigned int seedingTimestep
unsigned int orderParameterIndex
std::vector< nucleus< dim > > buildGlobalNucleiList(double min_dist_between_nuclei, unsigned int old_num_nuclei)
void safetyCheckNewNuclei(std::vector< nucleus< dim > > newnuclei, std::vector< unsigned int > &conflict_ids)
void refineMeshNearNuclei(std::vector< nucleus< dim > > newnuclei)