www.mooseframework.org
DiscreteNucleationInserter.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "libmesh/parallel_algebra.h"
12 
13 #include "libmesh/quadrature.h"
14 
16 
17 template <>
18 InputParameters
20 {
21  InputParameters params = validParams<DiscreteNucleationInserterBase>();
22  params.addClassDescription("Manages the list of currently active nucleation sites and adds new "
23  "sites according to a given probability function.");
24  params.addRequiredParam<MaterialPropertyName>(
25  "probability", "Probability density for inserting a discrete nucleus");
26  params.addRequiredParam<Real>("hold_time", "Time to keep each nucleus active");
27  return params;
28 }
29 
30 DiscreteNucleationInserter::DiscreteNucleationInserter(const InputParameters & parameters)
31  : DiscreteNucleationInserterBase(parameters),
32  _probability(getMaterialProperty<Real>("probability")),
33  _hold_time(getParam<Real>("hold_time")),
34  _local_nucleus_list(declareRestartableData("local_nucleus_list", NucleusList(0)))
35 {
36 }
37 
38 void
40 {
41  // clear insertion and deletion counter
42  _changes_made = {0, 0};
43 
44  // expire entries from the local nucleus list (if the current time step converged)
45  if (_fe_problem.converged())
46  {
47  unsigned int i = 0;
48  while (i < _local_nucleus_list.size())
49  {
50  if (_local_nucleus_list[i].first <= _fe_problem.time())
51  {
52  // remove entry (by replacing with last element and shrinking size by one)
54  _local_nucleus_list.pop_back();
55  _changes_made.second++;
56  }
57  else
58  ++i;
59  }
60  }
61 
62  // we reassemble this list at every time step
63  _global_nucleus_list.clear();
64 
65  // clear total nucleation rate
66  _nucleation_rate = 0.0;
67 }
68 
69 void
71 {
72  // check each qp for potential nucleation
73  // TODO: we might as well place the nuclei at random positions within the element...
74  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
75  {
76  const Real rate = _probability[qp] * _JxW[qp] * _coord[qp];
77  _nucleation_rate += rate;
78 
79  const Real random = getRandomReal();
80 
81  // We check the random number against the inverse of the zero probability.
82  // for performance reasons we do a quick check against the linearized form of
83  // that probability, which is always strictly larger than the actual probability.
84  // The expression below should short circuit and the expensive exponential
85  // should rarely get evaluated
86  if (random < rate * _fe_problem.dt() && random < (1.0 - std::exp(-rate * _fe_problem.dt())))
87  {
88  _local_nucleus_list.push_back(NucleusLocation(_fe_problem.time() + _hold_time, _q_point[qp]));
89  _changes_made.first++;
90  }
91  }
92 }
93 
94 void
96 {
97  // combine _local_nucleus_list entries from all threads on the current process
98  const DiscreteNucleationInserter & uo = static_cast<const DiscreteNucleationInserter &>(y);
99  _global_nucleus_list.insert(
100  _global_nucleus_list.end(), uo._local_nucleus_list.begin(), uo._local_nucleus_list.end());
101 
102  // sum up insertion and deletion counts
103  _changes_made.first += uo._changes_made.first;
104  _changes_made.second += uo._changes_made.second;
105 
106  // integrate total nucleation rate
108 }
109 
110 void
112 {
113  // add the _local_nucleus_list of thread zero
114  _global_nucleus_list.insert(
116 
122  std::vector<Real> comm_buffer(_global_nucleus_list.size() * 4);
123  for (unsigned i = 0; i < _global_nucleus_list.size(); ++i)
124  {
125  comm_buffer[i * 4 + 0] = _global_nucleus_list[i].first;
126  comm_buffer[i * 4 + 1] = _global_nucleus_list[i].second(0);
127  comm_buffer[i * 4 + 2] = _global_nucleus_list[i].second(1);
128  comm_buffer[i * 4 + 3] = _global_nucleus_list[i].second(2);
129  }
130 
131  // combine _global_nucleus_lists from all MPI ranks
132  _communicator.allgather(comm_buffer);
133 
134  // unpack the gathered _global_nucleus_list
135  unsigned int n = comm_buffer.size() / 4;
136  mooseAssert(comm_buffer.size() % 4 == 0,
137  "Communication buffer has an unexpected size (not divisible by 4)");
138  _global_nucleus_list.resize(n);
139  for (unsigned i = 0; i < n; ++i)
140  {
141  _global_nucleus_list[i].first = comm_buffer[i * 4 + 0];
142  _global_nucleus_list[i].second(0) = comm_buffer[i * 4 + 1];
143  _global_nucleus_list[i].second(1) = comm_buffer[i * 4 + 2];
144  _global_nucleus_list[i].second(2) = comm_buffer[i * 4 + 3];
145  }
146 
147  // get the global number of changes (i.e. changes to _global_nucleus_list)
148  gatherSum(_changes_made.first);
149  gatherSum(_changes_made.second);
150 
151  // gather the total nucleation rate
152  gatherSum(_nucleation_rate);
153 
154  _update_required = _changes_made.first > 0 || _changes_made.second > 0;
155 }
validParams< DiscreteNucleationInserterBase >
InputParameters validParams< DiscreteNucleationInserterBase >()
Definition: DiscreteNucleationInserterBase.C:14
DiscreteNucleationInserter::_hold_time
Real _hold_time
Duration of time each nucleus is kept active after insertion.
Definition: DiscreteNucleationInserter.h:42
validParams< DiscreteNucleationInserter >
InputParameters validParams< DiscreteNucleationInserter >()
Definition: DiscreteNucleationInserter.C:19
DiscreteNucleationInserter
This UserObject manages the insertion and expiration of nuclei in the simulation domain it manages a ...
Definition: DiscreteNucleationInserter.h:25
registerMooseObject
registerMooseObject("PhaseFieldApp", DiscreteNucleationInserter)
DiscreteNucleationInserter::threadJoin
virtual void threadJoin(const UserObject &y)
Definition: DiscreteNucleationInserter.C:95
DiscreteNucleationInserterBase
This UserObject manages the insertion and expiration of nuclei in the simulation domain it manages a ...
Definition: DiscreteNucleationInserterBase.h:25
DiscreteNucleationInserter::_nucleation_rate
Real _nucleation_rate
total nucleation rate
Definition: DiscreteNucleationInserter.h:48
DiscreteNucleationInserter::execute
virtual void execute()
Definition: DiscreteNucleationInserter.C:70
DiscreteNucleationInserter.h
DiscreteNucleationInserter::initialize
virtual void initialize()
Definition: DiscreteNucleationInserter.C:39
DiscreteNucleationInserterBase::_global_nucleus_list
NucleusList & _global_nucleus_list
the global list of all nuclei over all processors
Definition: DiscreteNucleationInserterBase.h:47
DiscreteNucleationInserterBase::NucleusList
std::vector< NucleusLocation > NucleusList
Every MPI task should keep a full list of nuclei (in case they cross domains with their finite radii)
Definition: DiscreteNucleationInserterBase.h:34
DiscreteNucleationInserterBase::_update_required
bool _update_required
is a map update required
Definition: DiscreteNucleationInserterBase.h:53
DiscreteNucleationInserter::DiscreteNucleationInserter
DiscreteNucleationInserter(const InputParameters &parameters)
Definition: DiscreteNucleationInserter.C:30
DiscreteNucleationInserter::_local_nucleus_list
NucleusList & _local_nucleus_list
the local nucleus list of nuclei centered in the domain of the current processor
Definition: DiscreteNucleationInserter.h:45
DiscreteNucleationInserter::_probability
const MaterialProperty< Real > & _probability
Nucleation rate density (should be a material property implementing nucleation theory)
Definition: DiscreteNucleationInserter.h:39
DiscreteNucleationInserterBase::NucleusLocation
std::pair< Real, Point > NucleusLocation
A nucleus has an expiration time and a location.
Definition: DiscreteNucleationInserterBase.h:31
DiscreteNucleationInserter::finalize
virtual void finalize()
Definition: DiscreteNucleationInserter.C:111
DiscreteNucleationInserterBase::_changes_made
NucleusChanges _changes_made
count the number of nucleus insertions and deletions
Definition: DiscreteNucleationInserterBase.h:50