SPH
InitialConditionJobs.cpp
Go to the documentation of this file.
2 #include "gravity/IGravity.h"
5 #include "physics/Eos.h"
6 #include "physics/Functions.h"
7 #include "post/Analysis.h"
8 #include "quantities/Quantity.h"
9 #include "run/IRun.h"
10 #include "run/SpecialEntries.h"
11 #include "sph/Materials.h"
13 #include "sph/initial/Initial.h"
14 #include "sph/initial/Stellar.h"
16 #include "system/Factory.h"
17 #include "system/Settings.impl.h"
18 #include "system/Statistics.h"
19 #include "thread/Scheduler.h"
20 
22 
23 // ----------------------------------------------------------------------------------------------------------
24 // MonolithicBodyIc
25 // ----------------------------------------------------------------------------------------------------------
26 
27 MonolithicBodyIc::MonolithicBodyIc(const std::string& name, const BodySettings& overrides)
28  : IParticleJob(name)
29  , MaterialProvider(overrides) {
31 }
32 
35  if (slotUsage.shape) {
36  map.insert("shape", JobType::GEOMETRY);
37  }
38  if (slotUsage.material) {
39  map.insert("material", JobType::MATERIAL);
40  }
41 
42  return map;
43 }
44 
46  VirtualSettings::Category& particleCat = settings.addCategory("Particles");
47  particleCat.connect<int>("Particle count", body, BodySettingsId::PARTICLE_COUNT);
48  particleCat.connect<EnumWrapper>("Distribution", body, BodySettingsId::INITIAL_DISTRIBUTION);
49  particleCat.connect<Float>("Radius multiplier", body, BodySettingsId::SMOOTHING_LENGTH_ETA);
50  particleCat.connect<bool>("Exact distance", body, BodySettingsId::DISTRIBUTE_MODE_SPH5);
51  particleCat.connect<bool>("Center particles", body, BodySettingsId::CENTER_PARTICLES);
52 }
53 
55  VirtualSettings connector;
56  addGenericCategory(connector, instName);
57  this->addParticleCategory(connector);
58 
59  VirtualSettings::Category& shapeCat = connector.addCategory("Shape");
60  shapeCat.connect<bool>("Custom shape", "useShapeSlot", slotUsage.shape)
61  .setTooltip(
62  "If true, a user-specified geometry input is used instead of shape parameters of the node.");
63  shapeCat.connect<EnumWrapper>("Shape type", body, BodySettingsId::BODY_SHAPE_TYPE).setEnabler([this] {
64  return !slotUsage.shape;
65  });
66  shapeCat.connect<Float>("Radius [km]", body, BodySettingsId::BODY_RADIUS)
67  .setEnabler([this] {
69  return !slotUsage.shape && (domain == DomainEnum::SPHERICAL || domain == DomainEnum::CYLINDER);
70  })
71  .setUnits(1.e3_f);
72  shapeCat.connect<Float>("Height [km]", body, BodySettingsId::BODY_HEIGHT)
73  .setEnabler([this] {
75  return !slotUsage.shape && domain == DomainEnum::CYLINDER;
76  })
77  .setUnits(1.e3_f);
78  shapeCat.connect<Vector>("Dimensions [km]", body, BodySettingsId::BODY_DIMENSIONS)
79  .setEnabler([this] {
81  return !slotUsage.shape && (domain == DomainEnum::BLOCK || domain == DomainEnum::ELLIPSOIDAL);
82  })
83  .setUnits(1.e3_f);
84 
85  VirtualSettings::Category& materialCat = connector.addCategory("Material");
86  materialCat.connect<bool>("Custom material", "useMaterialSlot", slotUsage.material)
87  .setTooltip(
88  "If true, a user-specified material input is used instead of material parameters of the node.");
89  this->addMaterialEntries(materialCat, [this] { return !slotUsage.material; });
90 
91  auto diehlEnabler = [this] {
94  };
95  VirtualSettings::Category& diehlCat = connector.addCategory("Diehl's distribution");
96  diehlCat.connect<int>("Iteration count", body, BodySettingsId::DIEHL_ITERATION_COUNT)
97  .setEnabler(diehlEnabler);
98  diehlCat.connect<Float>("Strength", body, BodySettingsId::DIEHL_STRENGTH).setEnabler(diehlEnabler);
99 
100  VirtualSettings::Category& dynamicsCat = connector.addCategory("Dynamics");
101  dynamicsCat.connect<Float>("Spin rate [rev/day]", body, BodySettingsId::BODY_SPIN_RATE);
102 
103  VirtualSettings::Category& visCat = connector.addCategory("Visualization");
104  visCat.connect<Path>("Texture path", body, BodySettingsId::VISUALIZATION_TEXTURE)
106  .setFileFormats({
107  { "JPEG image", "jpg" },
108  { "PNG image", "png" },
109  { "TIFF image", "tif" },
110  });
111 
112  return connector;
113 }
114 
116 private:
117  IRunCallbacks& callbacks;
118 
119 public:
120  explicit IcProgressCallback(IRunCallbacks& callbacks)
121  : callbacks(callbacks) {}
122 
123  bool operator()(const Float progress) const {
124  Statistics stats;
125  stats.set(StatisticsId::RELATIVE_PROGRESS, progress);
126  callbacks.onTimeStep(Storage(), stats);
127  return false;
128  }
129 };
130 
132  IRunCallbacks& callbacks;
133  int iterCnt;
134 
135 public:
136  DiehlReporter(IRunCallbacks& callbacks, const int iterCnt)
137  : callbacks(callbacks)
138  , iterCnt(iterCnt) {}
139 
140  bool operator()(const Size i, const ArrayView<const Vector> positions) const {
141  Storage storage;
142  Array<Vector> r;
143  r.pushAll(positions.begin(), positions.end());
144  storage.insert<Vector>(QuantityId::POSITION, OrderEnum::FIRST, std::move(r));
145  Statistics stats;
146  stats.set(StatisticsId::INDEX, int(i));
147  stats.set(StatisticsId::RELATIVE_PROGRESS, Float(i) / iterCnt);
148 
149  if (i == 0) {
150  callbacks.onSetUp(storage, stats);
151  }
152  callbacks.onTimeStep(storage, stats);
153  return !callbacks.shouldAbortRun();
154  }
155 };
156 
157 void MonolithicBodyIc::evaluate(const RunSettings& global, IRunCallbacks& callbacks) {
158  SharedPtr<IDomain> domain = slotUsage.shape ? this->getInput<IDomain>("shape") : Factory::getDomain(body);
160  slotUsage.material ? this->getInput<IMaterial>("material") : Factory::getMaterial(body);
161 
162  // override the material texture
163  std::string texturePath = body.get<std::string>(BodySettingsId::VISUALIZATION_TEXTURE);
164  material->setParam(BodySettingsId::VISUALIZATION_TEXTURE, std::move(texturePath));
165 
167  AutoPtr<IDistribution> distribution;
168  if (distType == DistributionEnum::DIEHL_ET_AL) {
169  DiehlParams diehl;
172  diehl.onIteration = DiehlReporter(callbacks, diehl.numOfIters);
173 
174  distribution = makeAuto<DiehlDistribution>(diehl);
175  } else {
176  distribution = Factory::getDistribution(body, IcProgressCallback(callbacks));
177  }
178 
181  material->setParam(
183 
184  // use defaults where no global parameters are provided
185  RunSettings settings;
186  settings.addEntries(global);
187  InitialConditions ic(settings);
188 
189  result = makeShared<ParticleData>();
190 
191  BodyView view = ic.addMonolithicBody(result->storage, *domain, material, *distribution);
192  const Float spinRate = body.get<Float>(BodySettingsId::BODY_SPIN_RATE) * 2._f * PI / (3600._f * 24._f);
193 
194  view.addRotation(Vector(0._f, 0._f, spinRate), domain->getCenter());
195 }
196 
197 static JobRegistrar sRegisterMonolithic(
198  "create monolithic body",
199  "body",
200  "initial conditions",
201  [](const std::string& name) { return makeAuto<MonolithicBodyIc>(name); },
202  "Creates a single monolithic homogeneous body.");
203 
204 // ----------------------------------------------------------------------------------------------------------
205 // DifferentiatedBodyIc
206 // ----------------------------------------------------------------------------------------------------------
207 
209  : IParticleJob(name) {}
210 
212  VirtualSettings connector;
213  addGenericCategory(connector, instName);
214  VirtualSettings::Category& layersCat = connector.addCategory("Layers");
215  layersCat.connect("Layer count", "layer_cnt", layerCnt);
216  VirtualSettings::Category& particleCat = connector.addCategory("Particles");
217  particleCat.connect<int>("Particle count", mainBody, BodySettingsId::PARTICLE_COUNT);
218  particleCat.connect<Float>("Radius multiplier", mainBody, BodySettingsId::SMOOTHING_LENGTH_ETA);
219  particleCat.connect<EnumWrapper>("Distribution", mainBody, BodySettingsId::INITIAL_DISTRIBUTION);
220 
221  return connector;
222 }
223 
226  mantle.domain = this->getInput<IDomain>("base shape");
227  mantle.material = this->getInput<IMaterial>("base material");
228  mantle.material->setParam(
232  const Float eta = mainBody.get<Float>(BodySettingsId::SMOOTHING_LENGTH_ETA);
234 
236  for (int i = layerCnt - 1; i >= 0; --i) {
237  InitialConditions::BodySetup& layer = layers.emplaceBack();
238  layer.domain = this->getInput<IDomain>("shape " + std::to_string(i + 1));
239  layer.material = this->getInput<IMaterial>("material " + std::to_string(i + 1));
241  }
242 
243  result = makeShared<ParticleData>();
244  InitialConditions ic(global);
245  ic.addHeterogeneousBody(result->storage, mantle, std::move(layers));
246 }
247 
248 static JobRegistrar sRegisterDifferentiated(
249  "create differentiated body",
250  "body",
251  "initial conditions",
252  [](const std::string& name) { return makeAuto<DifferentiatedBodyIc>(name); },
253  "Creates a body consisting of multiple different materials. The base shape/material describes the "
254  "global shape of body and material of a particles not assigned to any layer. The indexed layers than "
255  "assign a specific material to a subset of particles.");
256 
257 // ----------------------------------------------------------------------------------------------------------
258 // SingleParticleIc
259 // ----------------------------------------------------------------------------------------------------------
260 
262  VirtualSettings connector;
263  addGenericCategory(connector, instName);
264  VirtualSettings::Category& particleCat = connector.addCategory("Particle");
265  particleCat.connect("Mass [M_sun]", "mass", mass).setUnits(Constants::M_sun);
266  particleCat.connect("Radius [R_sun]", "radius", radius).setUnits(Constants::R_sun);
267  particleCat.connect("Position [R_sun]", "r0", r0).setUnits(Constants::R_sun);
268  particleCat.connect("Velocity [R_sun/yr]", "v0", v0).setUnits(Constants::R_sun / Constants::year);
269  particleCat.connect("Flag", "flag", flag);
270 
271  return connector;
272 }
273 
275  result = makeShared<ParticleData>();
276  BodySettings body;
281 
282  Vector pos = r0;
283  pos[H] = radius;
284  v0[H] = 0._f;
289 }
290 
291 static JobRegistrar sRegisterSingleParticle(
292  "create single particle",
293  "particle",
294  "initial conditions",
295  [](const std::string& name) { return makeAuto<SingleParticleIc>(name); },
296  "Creates a single particle with given mass, providing a convenient central potential for simulations of "
297  "circumplanetary (circumstelar, circumbinary) disk.");
298 
299 // ----------------------------------------------------------------------------------------------------------
300 // ImpactorIc
301 // ----------------------------------------------------------------------------------------------------------
302 
303 void ImpactorIc::addParticleCategory(VirtualSettings& settings) {
304  VirtualSettings::Category& particleCat = settings.addCategory("Particles");
305  particleCat.connect<int>("Min particle count", body, BodySettingsId::MIN_PARTICLE_COUNT);
306  particleCat.connect<EnumWrapper>("Distribution", body, BodySettingsId::INITIAL_DISTRIBUTION);
307  particleCat.connect<Float>("Radius multiplier", body, BodySettingsId::SMOOTHING_LENGTH_ETA);
308  particleCat.connect<bool>("Exact distance", body, BodySettingsId::DISTRIBUTE_MODE_SPH5);
309 }
310 
311 static Float getTargetDensity(const Storage& storage) {
312  ArrayView<const Float> m, rho;
314 
315  Float volume = 0._f;
316  for (Size i = 0; i < m.size(); ++i) {
317  volume += m[i] / rho[i];
318  }
319 
320  SPH_ASSERT(volume > 0._f, volume);
321  return m.size() / volume;
322 }
323 
324 void ImpactorIc::evaluate(const RunSettings& global, IRunCallbacks& callbacks) {
325  SharedPtr<IDomain> domain = slotUsage.shape ? this->getInput<IDomain>("shape") : Factory::getDomain(body);
326  SharedPtr<ParticleData> target = this->getInput<ParticleData>("target");
327 
328  const Size minParticleCnt = body.get<int>(BodySettingsId::MIN_PARTICLE_COUNT);
329  const Size particleCnt = Size(getTargetDensity(target->storage) * domain->getVolume());
330  body.set(BodySettingsId::PARTICLE_COUNT, max<int>(particleCnt, minParticleCnt));
331 
332  MonolithicBodyIc::evaluate(global, callbacks);
333 }
334 
335 static JobRegistrar sRegisterImpactorBody(
336  "create impactor",
337  "impactor",
338  "initial conditions",
339  [](const std::string& name) { return makeAuto<ImpactorIc>(name); },
340  "Creates a monolithic body with automatic particle count. The number of particles is assigned "
341  "to match the particle concentration (number density) of a target body.");
342 
343 // ----------------------------------------------------------------------------------------------------------
344 // EquilibriumIc
345 // ----------------------------------------------------------------------------------------------------------
346 
347 enum class EquilSolveEnum {
348  SPHERICAL,
349  PRECISE,
350 };
351 
352 static RegisterEnum<EquilSolveEnum> sSolverType({
354  "spherical",
355  "Computes equilibrium assuming spherically symmetric configuration." },
356  { EquilSolveEnum::PRECISE, "precise", "Computes equilibrium by solving a least-squares problem." },
357 });
358 
359 EquilibriumIc::EquilibriumIc(const std::string& name)
360  : IParticleJob(name)
361  , solver(EquilSolveEnum::SPHERICAL) {
362  boundaryThreshold = 40;
363 }
364 
366  VirtualSettings connector;
367  addGenericCategory(connector, instName);
368 
369  VirtualSettings::Category& solverCat = connector.addCategory("Solution");
370  solverCat.connect("Solver", "solver", solver);
371  solverCat.connect("Boundary threshold", "threshold", boundaryThreshold).setEnabler([&] {
372  return EquilSolveEnum(solver) == EquilSolveEnum::PRECISE;
373  });
374 
375  return connector;
376 }
377 
379 
381 static Array<MassShell> getMassInRadius(const Storage& storage, const Vector& r0) {
384 
385  Array<MassShell> table(r.size());
386  for (Size i = 0; i < r.size(); ++i) {
387  table[i] = makeTuple(i, getLength(r[i] - r0), m[i]);
388  }
389 
390  // sort by radius
391  std::sort(table.begin(), table.end(), [](const MassShell& s1, const MassShell& s2) {
392  return s1.get<1>() < s2.get<1>();
393  });
394 
395  // integrate masses
396  for (Size i = 1; i < r.size(); ++i) {
397  table[i].get<2>() += table[i - 1].get<2>();
398  }
399 
400  return table;
401 }
402 
403 static Array<Float> integratePressure(const Storage& storage, const Vector& r0) {
404  Array<MassShell> massInRadius = getMassInRadius(storage, r0);
406  Array<Float> p(massInRadius.size());
407  Float p0 = 0._f; // ad hoc, will be corrected afterwards
408  p.fill(p0);
409  for (Size k = 1; k < massInRadius.size(); ++k) {
410  const Size i = massInRadius[k].get<0>();
411  const Float r = massInRadius[k].get<1>();
412  const Float dr = r - massInRadius[k - 1].get<1>();
413  SPH_ASSERT(dr >= 0._f);
414  const Float M = massInRadius[k].get<2>();
415 
416  p[i] = p0 - Constants::gravity * M * rho[i] / sqr(r) * dr;
417  p0 = p[i];
418  }
419 
420  // subtract the surface pressure, so that the surface pressure is 0
421  for (Size i = 0; i < p.size(); ++i) {
422  p[i] -= p0;
423  }
424 
425  return p;
426 }
427 
428 static void solveSpherical(Storage& storage) {
431  const Vector r0 = Post::getCenterOfMass(m, r);
432  Sphere boundingSphere(r0, 0._f);
433  for (Size i = 0; i < r.size(); ++i) {
434  boundingSphere = Sphere(r0, max(boundingSphere.radius(), getLength(r[i] - r0)));
435  }
436 
440  Array<Float> solution = integratePressure(storage, r0);
441 
442  for (Size matId = 0; matId < storage.getMaterialCnt(); ++matId) {
443  MaterialView mat = storage.getMaterial(matId);
444  RawPtr<EosMaterial> eosMat = dynamicCast<EosMaterial>(addressOf(mat.material()));
445  SPH_ASSERT(eosMat);
446  for (Size i : mat.sequence()) {
447  p[i] = solution[i];
448  u[i] = eosMat->getEos().getInternalEnergy(rho[i], p[i]);
449  }
450  }
451 }
452 
453 void EquilibriumIc::evaluate(const RunSettings& global, IRunCallbacks& UNUSED(callbacks)) {
454  result = this->getInput<ParticleData>("particles");
455  Storage& storage = result->storage;
456 
457  switch (EquilSolveEnum(solver)) {
459  solveSpherical(storage);
460  break;
462 #ifdef SPH_USE_EIGEN
463  RunSettings settings;
464  settings.addEntries(global);
465  SharedPtr<IScheduler> scheduler = Factory::getScheduler(settings);
467  EquilibriumEnergySolver solver(*scheduler, settings, std::move(gravity), boundaryThreshold);
468  Statistics stats;
469  Outcome result = solver.solve(storage, stats);
470  if (!result) {
471  throw InvalidSetup("Cannot find equilibrium solution: " + result.error());
472  }
473 #else
474  MARK_USED(global);
475  MARK_USED(boundaryThreshold);
476  throw InvalidSetup("OpenSPH needs to be compiled with CONFIG+=use_eigen to use this option");
477 #endif
478  break;
479  }
480  default:
481  throw InvalidSetup("Unknown equilibrium solver");
482  }
483 }
484 
485 static JobRegistrar sRegisterEquilibriumIc(
486  "set equilibrium energy",
487  "equilibrium",
488  "initial conditions",
489  [](const std::string& name) { return makeAuto<EquilibriumIc>(name); },
490  "Modifies the internal energy of the input body to create a pressure gradient that balances "
491  "the gravitational acceleration. This can be used only for material with equation of state, "
492  "it further expects spherical symmetry of the input body (although homogeneity is not "
493  "required).");
494 
495 // ----------------------------------------------------------------------------------------------------------
496 // ModifyQuantityIc
497 // ----------------------------------------------------------------------------------------------------------
498 
499 enum class ChangeMode {
500  PARAMETRIC,
501  CURVE,
502 };
503 
504 static RegisterEnum<ChangeMode> sChangeMode({
505  { ChangeMode::PARAMETRIC, "parametric", "Specified by parameters" },
506  { ChangeMode::CURVE, "curve", "Curve" },
507 });
508 
510  DENSITY,
511  ENERGY,
512 };
513 
514 static RegisterEnum<ChangeableQuantityId> sChangeableQuantity({
515  { ChangeableQuantityId::DENSITY, "density", "Material density." },
516  { ChangeableQuantityId::ENERGY, "specific energy", "Initial specific energy." },
517 });
518 
519 ModifyQuantityIc::ModifyQuantityIc(const std::string& name)
520  : IParticleJob(name)
521  , mode(ChangeMode::PARAMETRIC)
522  , curve(makeAuto<CurveEntry>()) {
524 }
525 
527  VirtualSettings connector;
528  addGenericCategory(connector, instName);
529 
530  auto paramEnabler = [this] { return ChangeMode(mode) == ChangeMode::PARAMETRIC; };
531  auto curveEnabler = [this] { return ChangeMode(mode) == ChangeMode::CURVE; };
532 
533  VirtualSettings::Category& quantityCat = connector.addCategory("Modification");
534  quantityCat.connect("Quantity", "quantity", id);
535  quantityCat.connect("Mode", "mode", mode);
536  quantityCat.connect("Center value [si]", "central_value", centralValue).setEnabler(paramEnabler);
537  quantityCat.connect("Radial gradient [si/km]", "radial_grad", radialGrad)
538  .setUnits(1.e-3f)
539  .setEnabler(paramEnabler);
540  quantityCat.connect("Curve", "curve", curve).setEnabler(curveEnabler);
541 
542  return connector;
543 }
544 
546  result = this->getInput<ParticleData>("particles");
547 
550  switch (ChangeableQuantityId(id)) {
553  break;
556  break;
557  default:
559  }
560 
561  switch (ChangeMode(mode)) {
563  for (Size i = 0; i < r.size(); ++i) {
564  const Float dist = getLength(r[i]);
565  q[i] = centralValue + radialGrad * dist;
566  }
567  break;
568  case ChangeMode::CURVE: {
569  RawPtr<CurveEntry> curveEntry = dynamicCast<CurveEntry>(curve.getEntry());
570  const Curve func = curveEntry->getCurve();
571  for (Size i = 0; i < r.size(); ++i) {
572  const Float dist = getLength(r[i]);
573  q[i] = func(dist);
574  }
575  break;
576  }
577  default:
579  }
580 }
581 
582 static JobRegistrar sRegisterModifyQuantityIc(
583  "modify quantity",
584  "modifier",
585  "initial conditions",
586  [](const std::string& name) { return makeAuto<ModifyQuantityIc>(name); },
587  "Modifies given quantity of the input body, optionally specifying a radial gradient or generic radial "
588  "dependency via a user-defined curve.");
589 
590 // ----------------------------------------------------------------------------------------------------------
591 // NoiseQuantity
592 // ----------------------------------------------------------------------------------------------------------
593 
594 enum class NoiseQuantityId {
595  DENSITY,
596  VELOCITY,
597 };
598 
599 static RegisterEnum<NoiseQuantityId> sNoiseQuantity({
600  { NoiseQuantityId::DENSITY, "density", "Material density" },
601  { NoiseQuantityId::VELOCITY, "velocity", "Particle velocity" },
602 });
603 
604 const Indices GRID_DIMS(8, 8, 8);
605 
606 NoiseQuantityIc::NoiseQuantityIc(const std::string& name)
607  : IParticleJob(name) {
609 }
610 
612  VirtualSettings connector;
613  addGenericCategory(connector, instName);
614 
615  VirtualSettings::Category& quantityCat = connector.addCategory("Noise parameters");
616  quantityCat.connect("Quantity", "quantity", id);
617  quantityCat.connect("Mean [si]", "mean", mean);
618  quantityCat.connect("Magnitude [si]", "magnitude", magnitude);
619 
620  return connector;
621 }
622 
623 void NoiseQuantityIc::evaluate(const RunSettings& UNUSED(global), IRunCallbacks& callbacks) {
624  result = this->getInput<ParticleData>("particles");
625  Storage& storage = result->storage;
627 
628  switch (NoiseQuantityId(id)) {
631  this->randomize<1>(callbacks, r, [&rho](Float value, Size i, Size UNUSED(j)) { //
632  rho[i] = value;
633  });
634  break;
635  }
638  this->randomize<3>(callbacks, r, [&v](Float value, Size i, Size j) { v[i][j] = value; });
639  break;
640  }
641  default:
643  }
644 }
645 
646 template <Size Dims, typename TSetter>
647 void NoiseQuantityIc::randomize(IRunCallbacks& callbacks,
649  const TSetter& setter) const {
650  UniformRng rng;
651 
652  StaticArray<Grid<Vector>, Dims> gradients;
653  for (Size dim = 0; dim < Dims; ++dim) {
654  gradients[dim] = Grid<Vector>(GRID_DIMS);
655  for (Vector& grad : gradients[dim]) {
656  grad = sampleUnitSphere(rng);
657  }
658  }
659 
660  Box box;
661  for (Size i = 0; i < r.size(); ++i) {
662  box.extend(r[i] + Vector(r[i][H]));
663  box.extend(r[i] - Vector(r[i][H]));
664  }
665 
666  Statistics stats;
667  for (Size i = 0; i < r.size(); ++i) {
668 
669  for (Size dim = 0; dim < Dims; ++dim) {
670  const Vector pos = (r[i] - box.lower()) / box.size() * GRID_DIMS;
671  const Float value = mean + magnitude * perlin(gradients[dim], pos);
672  SPH_ASSERT(isReal(value));
673  setter(value, i, dim);
674  }
675 
676  if (i % 1000 == 0) {
678  callbacks.onTimeStep({}, stats);
679  }
680  }
681 }
682 
683 Float NoiseQuantityIc::perlin(const Grid<Vector>& gradients, const Vector& v) const {
684  const Indices v0(v);
685  const Vector dv = Vector(v) - v0;
686 
687  const Float x000 = this->dotGradient(gradients, v0 + Indices(0, 0, 0), v);
688  const Float x001 = this->dotGradient(gradients, v0 + Indices(0, 0, 1), v);
689  const Float x010 = this->dotGradient(gradients, v0 + Indices(0, 1, 0), v);
690  const Float x011 = this->dotGradient(gradients, v0 + Indices(0, 1, 1), v);
691  const Float x100 = this->dotGradient(gradients, v0 + Indices(1, 0, 0), v);
692  const Float x101 = this->dotGradient(gradients, v0 + Indices(1, 0, 1), v);
693  const Float x110 = this->dotGradient(gradients, v0 + Indices(1, 1, 0), v);
694  const Float x111 = this->dotGradient(gradients, v0 + Indices(1, 1, 1), v);
695 
696  const Float x00 = lerp(x000, x001, dv[Z]);
697  const Float x01 = lerp(x010, x011, dv[Z]);
698  const Float x10 = lerp(x100, x101, dv[Z]);
699  const Float x11 = lerp(x110, x111, dv[Z]);
700 
701  const Float x0 = lerp(x00, x01, dv[Y]);
702  const Float x1 = lerp(x10, x11, dv[Y]);
703 
704  return lerp(x0, x1, dv[X]);
705 }
706 
707 Float NoiseQuantityIc::dotGradient(const Grid<Vector>& gradients, const Indices& i, const Vector& v) const {
708  const Vector& dv = Vector(i) - v;
709  const Indices is(
711 
712  return dot(dv, gradients[is]);
713 }
714 
715 
716 static JobRegistrar sRegisterNoise(
717  "Perlin noise",
718  "noise",
719  "initial conditions",
720  [](const std::string& name) { return makeAuto<NoiseQuantityIc>(name); },
721  "Perturbs selected quantity of the input body using a noise function.");
722 
723 // ----------------------------------------------------------------------------------------------------------
724 // NBodyIc
725 // ----------------------------------------------------------------------------------------------------------
726 
727 // clang-format off
728 template <>
729 AutoPtr<NBodySettings> NBodySettings::instance(new NBodySettings{
730  { NBodySettingsId::PARTICLE_COUNT, "particles.count", 10000,
731  "Number of generated particles." },
733  "Total mass of the particles. Masses of individual particles depend on total number "
734  "of particles and on particle sizes." },
735  { NBodySettingsId::DOMAIN_RADIUS, "domain.radius", 100.e3_f,
736  "Radius of the domain where the particles are initially generated. This is not a boundary, particles "
737  "can leave the domain. " },
738  { NBodySettingsId::RADIAL_PROFILE, "radial_profile", 1.5_f,
739  "Specifies a balance between particle concentration in the center of the domain and at the boundary. "
740  "Higher values imply more dense center and fewer particles at the boundary." },
741  { NBodySettingsId::HEIGHT_SCALE, "height_scale", 1._f,
742  "Specifies the relative scale of the domain in z-direction. For 1, the domain is spherical, lower values "
743  "can be used to create a disk-like domain." },
744  { NBodySettingsId::POWER_LAW_INTERVAL, "power_law.interval", Interval(1.e3_f, 10.e3_f),
745  "Interval of sizes generated particles." },
746  { NBodySettingsId::POWER_LAW_EXPONENT, "power_law.exponent", 2._f,
747  "Exponent of the power-law, used to generate particle sizes." },
748  { NBodySettingsId::VELOCITY_MULTIPLIER, "velocity.multiplier", 1._f,
749  "Multiplier of the Keplerian velocity of particles. " },
750  { NBodySettingsId::VELOCITY_DISPERSION, "velocity.dispersion", 10._f,
751  "Specifies a random component of initial particle velocities." },
752 
753 });
754 // clang-format on
755 
756 template class Settings<NBodySettingsId>;
757 
758 NBodyIc::NBodyIc(const std::string& name, const NBodySettings& overrides)
759  : IParticleJob(name) {
760  settings.addEntries(overrides);
761 }
762 
764  VirtualSettings connector;
765  addGenericCategory(connector, instName);
766 
767  VirtualSettings::Category& particleCat = connector.addCategory("Particles");
768  particleCat.connect<int>("Particle count", settings, NBodySettingsId::PARTICLE_COUNT);
769 
770  VirtualSettings::Category& distributionCat = connector.addCategory("Distribution");
771  distributionCat.connect<Float>("Domain radius [km]", settings, NBodySettingsId::DOMAIN_RADIUS)
772  .setUnits(1.e3_f);
773  distributionCat.connect<Float>("Radial exponent", settings, NBodySettingsId::RADIAL_PROFILE);
774  distributionCat.connect<Float>("Height scale", settings, NBodySettingsId::HEIGHT_SCALE);
775  distributionCat.addEntry("min_size",
776  makeEntry(settings, NBodySettingsId::POWER_LAW_INTERVAL, "Minimal size [m]", IntervalBound::LOWER));
777  distributionCat.addEntry("max_size",
778  makeEntry(settings, NBodySettingsId::POWER_LAW_INTERVAL, "Maximal size [m]", IntervalBound::UPPER));
779 
780  distributionCat.connect<Float>("Power-law exponent", settings, NBodySettingsId::POWER_LAW_EXPONENT);
781 
782  VirtualSettings::Category& dynamicsCat = connector.addCategory("Dynamics");
783  dynamicsCat.connect<Float>("Total mass [M_earth]", settings, NBodySettingsId::TOTAL_MASS)
784  .setUnits(Constants::M_earth);
785  distributionCat.connect<Float>("Velocity multiplier", settings, NBodySettingsId::VELOCITY_MULTIPLIER);
786  distributionCat
787  .connect<Float>("Velocity dispersion [km/s]", settings, NBodySettingsId::VELOCITY_DISPERSION)
788  .setUnits(1.e3_f);
789 
790  return connector;
791 }
792 
793 static Vector sampleSphere(const Float radius, const Float exponent, IRng& rng) {
794  const Float l = rng(0);
795  const Float u = rng(1) * 2._f - 1._f;
796  const Float phi = rng(2) * 2._f * PI;
797 
798  const Float l13 = pow(l, exponent); // cbrt(l);
799  const Float rho = radius * l13 * sqrt(1._f - sqr(u));
800  const Float x = rho * cos(phi);
801  const Float y = rho * sin(phi);
802  const Float z = radius * l13 * u;
803 
804  return Vector(x, y, z);
805 }
806 
807 void NBodyIc::evaluate(const RunSettings& global, IRunCallbacks& callbacks) {
808  const Size particleCnt = settings.get<int>(NBodySettingsId::PARTICLE_COUNT);
810  const Float radialExponent = settings.get<Float>(NBodySettingsId::RADIAL_PROFILE);
811  const Float heightScale = settings.get<Float>(NBodySettingsId::HEIGHT_SCALE);
812  const Float velocityMult = settings.get<Float>(NBodySettingsId::VELOCITY_MULTIPLIER);
813  const Float velocityDispersion = settings.get<Float>(NBodySettingsId::VELOCITY_DISPERSION);
814  const Float totalMass = settings.get<Float>(NBodySettingsId::TOTAL_MASS);
815  const Interval interval = settings.get<Interval>(NBodySettingsId::POWER_LAW_INTERVAL);
816  const Float sizeExponent = settings.get<Float>(NBodySettingsId::POWER_LAW_EXPONENT);
817  const PowerLawSfd sfd{ sizeExponent, interval };
818 
819  AutoPtr<IRng> rng = Factory::getRng(global);
820  PointCloud cloud(radius / 10);
821  Size bailoutCounter = 0;
822  const Float sep = 1._f;
823  const Size reportStep = max(particleCnt / 1000, 1u);
824  do {
825  Vector v = sampleSphere(radius, radialExponent, *rng);
826  v[Z] *= heightScale;
827  v[H] = sfd(rng(3));
828 
829  // check for intersections
830  if (cloud.getClosePointsCount(v, sep * v[H]) > 0) {
831  // discard
832  bailoutCounter++;
833  continue;
834  }
835  cloud.push(v);
836  bailoutCounter = 0;
837 
838  if (cloud.size() % reportStep == reportStep - 1) {
839  Statistics stats;
840  stats.set(StatisticsId::RELATIVE_PROGRESS, Float(cloud.size()) / particleCnt);
841  callbacks.onTimeStep(Storage(), stats);
842 
843  if (callbacks.shouldAbortRun()) {
844  return;
845  }
846  }
847 
848  } while (cloud.size() < particleCnt && bailoutCounter < 1000);
849 
850  // assign masses
851  Array<Vector> positions = cloud.array();
852  Array<Float> masses(positions.size());
853 
854  Float m_sum = 0._f;
855  for (Size i = 0; i < positions.size(); ++i) {
856  masses[i] = sphereVolume(positions[i][H]);
857  m_sum += masses[i];
858  }
859 
860  // assign velocities
861  Array<Vector> velocities(positions.size());
862  for (Size i = 0; i < positions.size(); ++i) {
863  masses[i] *= totalMass / m_sum;
864  SPH_ASSERT(masses[i] > 0._f);
865 
866  const Float r0 = getLength(positions[i]);
867  const Float m0 = totalMass * sphereVolume(r0) / sphereVolume(radius);
868  const Float v_kepl = velocityMult * sqrt(Constants::gravity * m0 / r0);
869  const Vector dir = getNormalized(Vector(positions[i][Y], -positions[i][X], 0._f));
870  Vector v_random = sampleSphere(velocityDispersion, 0.333_f, *rng);
871  v_random[Z] *= heightScale;
872  velocities[i] = dir * v_kepl + v_random;
873  }
874 
875  Storage storage(makeAuto<NullMaterial>(BodySettings::getDefaults()));
876  storage.insert<Vector>(QuantityId::POSITION, OrderEnum::SECOND, std::move(positions));
877  storage.getDt<Vector>(QuantityId::POSITION) = std::move(velocities);
878  storage.insert<Float>(QuantityId::MASS, OrderEnum::ZERO, std::move(masses));
880 
881  result = makeShared<ParticleData>();
882  result->storage = std::move(storage);
883 }
884 
885 static JobRegistrar sRegisterNBodyIc(
886  "N-body ICs",
887  "initial conditions",
888  [](const std::string& name) { return makeAuto<NBodyIc>(name); },
889  "Creates a spherical or ellipsoidal cloud of particles.");
890 
891 
892 // ----------------------------------------------------------------------------------------------------------
893 // PolytropicStarICs
894 // ----------------------------------------------------------------------------------------------------------
895 
896 PolytropicStarIc::PolytropicStarIc(const std::string& name)
897  : IParticleJob(name) {}
898 
900  VirtualSettings connector;
901  addGenericCategory(connector, instName);
902 
903  VirtualSettings::Category& starCat = connector.addCategory("Star parameters");
904  starCat.connect("Particle count", "particleCnt", particleCnt);
905  starCat.connect("Distribution", "distribution", distId);
906  starCat.connect("Radius [R_sun]", "radius", radius).setUnits(Constants::R_sun);
907  starCat.connect("Mass [M_sun]", "mass", mass).setUnits(Constants::M_sun);
908  starCat.connect("Polytrope index", "polytrope_index", n);
909 
910  return connector;
911 }
912 
914  BodySettings body;
917  Storage storage = Stellar::generateIc(*distribution, particleCnt, radius, mass, n);
918 
919  result = makeShared<ParticleData>();
920  result->storage = std::move(storage);
921 }
922 
923 static JobRegistrar sRegisterPolytropeIc(
924  "polytrope ICs",
925  "star ICs",
926  "initial conditions",
927  [](const std::string& name) { return makeAuto<PolytropicStarIc>(name); },
928  "Creates a single polytropic star.");
929 
930 // ----------------------------------------------------------------------------------------------------------
931 // IsothermalSphereICs
932 // ----------------------------------------------------------------------------------------------------------
933 
935  : IParticleJob(name) {}
936 
938  VirtualSettings connector;
939  addGenericCategory(connector, instName);
940 
941  VirtualSettings::Category& sphereCat = connector.addCategory("Sphere");
942  sphereCat.connect("Particle count", "particleCnt", particleCnt);
943  sphereCat.connect("Radius [km]", "radius", radius).setUnits(1.e3_f);
944  sphereCat.connect("Central density [kg/m^3]", "density", centralDensity);
945  sphereCat.connect("Central energy [J/kg]", "energy", centralEnergy);
946  sphereCat.connect("Adiabatic index []", "gamma", gamma);
947 
948  return connector;
949 }
950 
951 void IsothermalSphereIc::evaluate(const RunSettings& global, IRunCallbacks& callbacks) {
952  BodySettings body;
953  body.set(BodySettingsId::DENSITY, centralDensity);
954  body.set(BodySettingsId::ENERGY, centralEnergy);
956  SharedPtr<IMaterial> material = makeShared<EosMaterial>(body);
957  Storage storage(material);
958  DiehlParams params;
959  Float r0 = 0.1_f * radius;
960  params.numOfIters = 50;
961  params.onIteration = DiehlReporter(callbacks, params.numOfIters);
962  params.particleDensity = [r0](const Vector& r) {
963  // does not have to be normalized
964  return 1._f / (1._f + getSqrLength(r) / sqr(r0));
965  };
966 
967  DiehlDistribution dist(params);
968  SharedPtr<IScheduler> scheduler = Factory::getScheduler(global);
969  SphericalDomain domain(Vector(0._f), radius);
970  storage.insert(QuantityId::POSITION, OrderEnum::SECOND, dist.generate(*scheduler, particleCnt, domain));
971  const Float K = (gamma - 1._f) * centralEnergy;
972  const Float M_tot = 2._f * PI * K * radius / Constants::gravity;
973  storage.insert(QuantityId::MASS, OrderEnum::ZERO, M_tot / particleCnt);
974  storage.insert(QuantityId::ENERGY, OrderEnum::FIRST, centralEnergy);
975  storage.insert(QuantityId::DENSITY, OrderEnum::FIRST, centralEnergy);
978  const Float kingRadius = sqrt(9._f * K / (4._f * PI * Constants::gravity * centralDensity));
979  for (Size i = 0; i < rho.size(); ++i) {
980  rho[i] = centralDensity / (1._f + getSqrLength(r[i]) / sqr(kingRadius));
981  }
982 
983  MaterialInitialContext context(global);
984  material->create(storage, context);
985 
986  result = makeShared<ParticleData>();
987  result->storage = std::move(storage);
988 }
989 
990 
991 static JobRegistrar sRegisterIsothermalSphereIc(
992  "isothermal sphere ICs",
993  "star ICs",
994  "initial conditions",
995  [](const std::string& name) { return makeAuto<IsothermalSphereIc>(name); },
996  "Creates a single isothermal sphere.");
997 
998 // ----------------------------------------------------------------------------------------------------------
999 // GalaxyICs
1000 // ----------------------------------------------------------------------------------------------------------
1001 
1002 extern template class Settings<GalaxySettingsId>;
1003 
1004 GalaxyIc::GalaxyIc(const std::string& name, const GalaxySettings& overrides)
1005  : IParticleJob(name) {
1006  settings.addEntries(overrides);
1007 }
1008 
1010  VirtualSettings connector;
1011  addGenericCategory(connector, instName);
1012 
1013  VirtualSettings::Category& diskCat = connector.addCategory("Disk");
1014  diskCat.connect<int>("Disk particle count", settings, GalaxySettingsId::DISK_PARTICLE_COUNT);
1015  diskCat.connect<Float>("Disk radial scale", settings, GalaxySettingsId::DISK_RADIAL_SCALE);
1016  diskCat.connect<Float>("Disk radial cutoff", settings, GalaxySettingsId::DISK_RADIAL_CUTOFF);
1017  diskCat.connect<Float>("Disk vertical scale", settings, GalaxySettingsId::DISK_VERTICAL_SCALE);
1018  diskCat.connect<Float>("Disk vertical cutoff", settings, GalaxySettingsId::DISK_VERTICAL_CUTOFF);
1019  diskCat.connect<Float>("Disk mass", settings, GalaxySettingsId::DISK_MASS);
1020  diskCat.connect<Float>("Toomre Q parameter", settings, GalaxySettingsId::DISK_TOOMRE_Q);
1021 
1022  VirtualSettings::Category& haloCat = connector.addCategory("Halo");
1023  haloCat.connect<int>("Halo particle count", settings, GalaxySettingsId::HALO_PARTICLE_COUNT);
1024  haloCat.connect<Float>("Halo scale length", settings, GalaxySettingsId::HALO_SCALE_LENGTH);
1025  haloCat.connect<Float>("Halo cutoff", settings, GalaxySettingsId::HALO_CUTOFF);
1026  haloCat.connect<Float>("Halo gamma", settings, GalaxySettingsId::HALO_GAMMA);
1027  haloCat.connect<Float>("Halo mass", settings, GalaxySettingsId::HALO_MASS);
1028 
1029  VirtualSettings::Category& bulgeCat = connector.addCategory("Bulge");
1030  bulgeCat.connect<int>("Bulge particle count", settings, GalaxySettingsId::BULGE_PARTICLE_COUNT);
1031  bulgeCat.connect<Float>("Bulge scale length", settings, GalaxySettingsId::BULGE_SCALE_LENGTH);
1032  bulgeCat.connect<Float>("Bulge cutoff", settings, GalaxySettingsId::BULGE_CUTOFF);
1033  bulgeCat.connect<Float>("Bulge mass", settings, GalaxySettingsId::BULGE_MASS);
1034 
1035  VirtualSettings::Category& particleCat = connector.addCategory("Particles");
1036  particleCat.connect<Float>("Particle radius", settings, GalaxySettingsId::PARTICLE_RADIUS);
1037 
1038  return connector;
1039 }
1040 
1042 private:
1043  IRunCallbacks& run;
1044 
1045 public:
1047  : run(run) {}
1048 
1049  struct Cancelled {};
1050 
1051  virtual void onPart(const Storage& storage, const Size partId, const Size numParts) const override {
1052  if (storage.empty()) {
1053  SPH_ASSERT(partId == 0);
1054  return;
1055  }
1056 
1057  Statistics stats;
1058  stats.set(StatisticsId::RELATIVE_PROGRESS, Float(partId) / Float(numParts));
1059  stats.set(StatisticsId::RUN_TIME, 0._f);
1060 
1061  if (partId == 1) {
1062  run.onSetUp(storage, stats);
1063  }
1064  run.onTimeStep(storage, stats);
1065 
1066  if (run.shouldAbortRun()) {
1067  throw Cancelled{};
1068  }
1069  }
1070 };
1071 
1072 void GalaxyIc::evaluate(const RunSettings& global, IRunCallbacks& callbacks) {
1073  Storage storage;
1074  try {
1075  storage = Galaxy::generateIc(global, settings, GalaxyCallbacks(callbacks));
1076  } catch (const GalaxyCallbacks::Cancelled&) {
1077  return;
1078  }
1079 
1080  result = makeShared<ParticleData>();
1081  result->storage = std::move(storage);
1082 
1085 }
1086 
1087 static JobRegistrar sRegisterGalaxyIc(
1088  "galaxy ICs",
1089  "initial conditions",
1090  [](const std::string& name) { return makeAuto<GalaxyIc>(name); },
1091  "Creates a single galaxy.");
1092 
Various function for interpretation of the results of a simulation.
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
INLINE AutoPtr< T > makeAuto(TArgs &&... args)
Definition: AutoPtr.h:124
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
const float radius
Definition: CurveDialog.cpp:18
Filling spatial domain with SPH particles.
Equations of state.
Computes quantities to get equilibrium state.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Base class for solvers of gravity.
Basic interface defining a single run.
ChangeableQuantityId
const Indices GRID_DIMS(8, 8, 8)
Generating initial conditions of SPH particles.
VirtualSettings::Category & addGenericCategory(VirtualSettings &connector, std::string &instanceName)
Adds a common settings category, used by all jobs.
Definition: Job.cpp:43
@ GEOMETRY
Job providing geometry.
@ MATERIAL
Job providing a material.
SPH-specific implementation of particle materials.
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
INLINE int positiveMod(const int i, const int n)
Returns a positive modulo value.
Definition: MathUtils.h:89
INLINE T lerp(const T v1, const T v2, const TAmount amount)
Definition: MathUtils.h:341
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE T sin(const T f)
Definition: MathUtils.h:296
INLINE T cos(const T f)
Definition: MathUtils.h:291
INLINE T sqrt(const T f)
Return a squared root of a value.
Definition: MathUtils.h:78
constexpr INLINE Float pow(const Float v)
Power for floats.
constexpr INLINE Float sphereVolume(const Float radius)
Computes a volume of a sphere given its radius.
Definition: MathUtils.h:375
constexpr Float PI
Mathematical constants.
Definition: MathUtils.h:361
#define UNUSED(x)
Definition: Object.h:37
#define MARK_USED(x)
Silences the "unused variable" warning for given variable.
Definition: Object.h:42
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ VELOCITY
Current velocities of particles, always a vector quantity.
@ ENERGY
Specific internal energy, always a scalar quantity.
@ DENSITY
Density, always a scalar quantity.
@ FLAG
ID of original body, used to implement discontinuities between bodies in SPH.
@ PRESSURE
Pressure, affected by yielding and fragmentation model, always a scalar quantity.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ ENERGY
Specific internal energy, always a scalar quantity.
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar quantity.
Holder of quantity values and their temporal derivatives.
@ SECOND
Quantity with 1st and 2nd derivative.
@ FIRST
Quantity with 1st derivative.
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
INLINE RawPtr< T > addressOf(T &ref)
Definition: RawPtr.h:82
INLINE Vector sampleUnitSphere(TRng &rng)
Generates a random position on a unit sphere.
Definition: Rng.h:166
Interface for executing tasks (potentially) asynchronously.
Additional bindings to IVirtualSettings.
INLINE AutoPtr< IVirtualEntry > makeEntry(Settings< TEnum > &settings, const TEnum id, const std::string &name, const IntervalBound bound)
Object representing a three-dimensional sphere.
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Definition: StaticArray.h:281
Statistics gathered and periodically displayed during the run.
@ RUN_TIME
Current time of the simulation in code units. Does not necessarily have to be 0 when run starts.
@ INDEX
Current number of time step, indexed from 0.
INLINE auto makeTuple(TArgs &&... args)
Creates a tuple from a pack of values, utilizing type deduction.
Definition: Tuple.h:298
INLINE Float getLength(const Vector &v)
Returns the length of the vector. Enabled only for vectors of floating-point precision.
Definition: Vector.h:579
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
BasicVector< Float > Vector
Definition: Vector.h:539
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
INLINE Vector getNormalized(const Vector &v)
Definition: Vector.h:590
@ H
Definition: Vector.h:25
@ Y
Definition: Vector.h:23
@ X
Definition: Vector.h:22
@ Z
Definition: Vector.h:24
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
INLINE TCounter size() const
Definition: ArrayView.h:101
INLINE Iterator< StorageType > begin()
Definition: ArrayView.h:55
INLINE Iterator< StorageType > end()
Definition: ArrayView.h:63
Generic dynamically allocated resizable storage.
Definition: Array.h:43
StorageType & emplaceBack(TArgs &&... args)
Constructs a new element at the end of the array in place, using the provided arguments.
Definition: Array.h:332
INLINE TCounter size() const noexcept
Definition: Array.h:193
void pushAll(const TIter first, const TIter last)
Definition: Array.h:312
Non-owning view of particles belonging to the same body.
Definition: Initial.h:20
BodyView & addRotation(const Vector &omega, const RotationOrigin origin)
Adds an angular velocity to all particles of the body.
Definition: Initial.cpp:72
Helper object defining three-dimensional interval (box).
Definition: Box.h:17
INLINE void extend(const Vector &v)
Enlarges the box to contain the vector.
Definition: Box.h:49
INLINE const Vector & lower() const
Returns lower bounds of the box.
Definition: Box.h:82
INLINE Vector size() const
Returns box dimensions.
Definition: Box.h:106
Special entry allowing to access and (de)serialize a curve.
Represents a user-defined function, defined by a set of points interpolated by either piecewise linea...
Definition: Curve.h:19
Distribution with given particle density.
Definition: Distribution.h:149
virtual Array< Vector > generate(IScheduler &scheduler, const Size n, const IDomain &domain) const override
Returns generated particle distribution.
DiehlReporter(IRunCallbacks &callbacks, const int iterCnt)
bool operator()(const Size i, const ArrayView< const Vector > positions) const
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
DifferentiatedBodyIc(const std::string &name)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
EntryControl & setEnabler(const Enabler &newEnabler)
Adds or replaces the enabler functor of the entry.
EntryControl & setUnits(const Float newMult)
Sets units in which the entry is stored.
Solver for equilibrium internal energy.
Outcome solve(Storage &storage, Statistics &stats)
EquilibriumIc(const std::string &name)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
RawPtr< IExtraEntry > getEntry() const
GalaxyCallbacks(IRunCallbacks &run)
virtual void onPart(const Storage &storage, const Size partId, const Size numParts) const override
Called when computing new part of the galaxy (particle positions or velocities).
GalaxyIc(const std::string &name, const GalaxySettings &overrides=EMPTY_SETTINGS)
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
Definition: Grid.h:16
virtual Float getVolume() const =0
Returns the total volume of the domain.
virtual Vector getCenter() const =0
Returns the center of the domain.
std::string instName
Definition: Job.h:100
INLINE IMaterial & setParam(const BodySettingsId paramIdx, TValue &&value)
Definition: IMaterial.h:130
virtual void create(Storage &storage, const MaterialInitialContext &context)=0
Create all quantities needed by the material.
Base class for all jobs providing particle data.
Definition: Job.h:242
SharedPtr< ParticleData > result
Data filled by the job when it finishes.
Definition: Job.h:245
Polymorphic holder allowing to store any RNG (type erasure).
Definition: Rng.h:90
Callbacks executed by the simulation to provide feedback to the user.
Definition: IRun.h:27
virtual bool shouldAbortRun() const =0
Returns whether current run should be aborted or not.
virtual void onSetUp(const Storage &storage, Statistics &stats)=0
Called right before the run starts, i.e. after initial conditions are set up.
virtual void onTimeStep(const Storage &storage, Statistics &stats)=0
Called every timestep.
bool operator()(const Float progress) const
IcProgressCallback(IRunCallbacks &callbacks)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
Helper object for storing three (possibly four) int or bool values.
Definition: Indices.h:16
Object for adding one or more bodies with given material into a Storage.
Definition: Initial.h:106
BodyView addMonolithicBody(Storage &storage, const BodySettings &body)
Creates a monolithic body by filling given domain with particles.
Definition: Initial.cpp:81
BodyView addHeterogeneousBody(Storage &storage, const BodySetup &environment, ArrayView< const BodySetup > bodies)
Creates particles composed of different materials.
Definition: Initial.cpp:140
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
Thrown when components of the run are mutually incompatible.
Definition: Exceptions.h:24
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
IsothermalSphereIc(const std::string &name)
void addMaterialEntries(VirtualSettings::Category &category, Function< bool()> enabler)
BodySettings body
Definition: MaterialJobs.h:9
Non-owning wrapper of a material and particles with this material.
Definition: IMaterial.h:30
INLINE IMaterial & material()
Returns the reference to the material of the particles.
Definition: IMaterial.h:43
INLINE IndexSequence sequence()
Returns iterable index sequence.
Definition: IMaterial.h:75
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
ModifyQuantityIc(const std::string &name)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
struct MonolithicBodyIc::@13 slotUsage
virtual UnorderedMap< std::string, ExtJobType > requires() const override
List of slots that need to be connected to evaluate the job.
virtual void addParticleCategory(VirtualSettings &settings)
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
MonolithicBodyIc(const std::string &name, const BodySettings &overrides=EMPTY_SETTINGS)
NBodyIc(const std::string &name, const NBodySettings &overrides=EMPTY_SETTINGS)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
NoiseQuantityIc(const std::string &name)
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
Object representing a path on a filesystem.
Definition: Path.h:17
Container of points with optimized search queries.
Definition: PointCloud.h:13
Size getClosePointsCount(const Vector &center, const Float radius) const
Returns the number of points within given distance from the center point.
Definition: PointCloud.cpp:37
Handle push(const Vector &p)
Adds a point into the cloud.
Definition: PointCloud.cpp:5
Size size() const
Returns the number of points in the cloud.
Definition: PointCloud.cpp:33
Array< Vector > array() const
Returns all points in the cloud as array.
Definition: PointCloud.cpp:23
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
PolytropicStarIc(const std::string &name)
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
Non-owning wrapper of pointer.
Definition: RawPtr.h:19
TValue get(const TEnum idx, std::enable_if_t<!std::is_enum< std::decay_t< TValue >>::value, int >=0) const
Returns a value of given type from the settings.
Definition: Settings.h:326
static const Settings & getDefaults()
\brief Returns a reference to object containing default values of all settings.
Settings & set(const TEnum idx, TValue &&value, std::enable_if_t<!std::is_enum< std::decay_t< TValue >>::value, int >=0)
Saves a value into the settings.
Definition: Settings.h:226
void addEntries(const Settings &settings)
Adds entries from different Settings object into this one, overriding current entries.
Definition: Settings.h:297
virtual void evaluate(const RunSettings &global, IRunCallbacks &UNUSED(callbacks)) override
virtual VirtualSettings getSettings() override
Returns a settings object which allows to query and modify the state of the job.
Definition: Sphere.h:18
Spherical domain, defined by the center of sphere and its radius.
Definition: Domain.h:102
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
Object holding various statistics about current run.
Definition: Statistics.h:22
Statistics & set(const StatisticsId idx, TValue &&value)
Sets new values of a statistic.
Definition: Statistics.h:52
Container storing all quantities used within the simulations.
Definition: Storage.h:230
Size getMaterialCnt() const
Return the number of materials in the storage.
Definition: Storage.cpp:437
Quantity & insert(const QuantityId key, const OrderEnum order, const TValue &defaultValue)
Creates a quantity in the storage, given its key, value type and order.
Definition: Storage.cpp:270
bool empty() const
Checks if the storage is empty, i.e. without particles.
Definition: Storage.cpp:453
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
auto getValues(const QuantityId first, const QuantityId second, const TArgs... others)
Retrieves an array of quantities from the key.
Definition: Storage.h:359
MaterialView getMaterial(const Size matIdx) const
Returns an object containing a reference to given material.
Definition: Storage.cpp:366
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
Heterogeneous container capable of storing a fixed number of values.
Definition: Tuple.h:146
Random number generator with uniform distribution.
Definition: Rng.h:16
INLINE TValue & insert(const TKey &key, const TValue &value)
Adds a new element into the map or sets new value of element with the same key.
Definition: UnorderedMap.h:51
EntryControl & connect(const std::string &name, const std::string &key, TValue &value)
Connects to given reference.
Holds a map of virtual entries, associated with a unique name.
IVirtualEntry::Value get(const std::string &key) const
Returns a value of an entry.
Category & addCategory(const std::string &name)
Creates a new category of entries.
Creating code components based on values from settings.
@ NONE
Gass or material with no stress tensor.
DistributionEnum
Definition: Settings.h:1339
@ DIEHL_ET_AL
Isotropic uniform distribution by Diehl et al. (2012)
@ NONE
No fragmentation.
@ IDEAL_GAS
Equation of state for ideal gas.
@ DIEHL_STRENGTH
Strength parameter of the Diehl's distribution.
@ RHEOLOGY_DAMAGE
Model of fragmentation used within the rheological model.
@ INITIAL_DISTRIBUTION
Initial distribution of SPH particles within the domain, see DistributionEnum for options.
@ DIEHL_ITERATION_COUNT
Number of iterations of particle repelling.
@ ENERGY
Initial specific internal energy.
@ ADIABATIC_INDEX
Adiabatic index used by some equations of state (such as ideal gas)
@ PARTICLE_COUNT
Number of SPH particles in the body.
@ DENSITY
Density at zero pressure.
@ SMOOTHING_LENGTH_ETA
Eta-factor between smoothing length and particle concentration (h = eta * n^(-1/d) )
@ EOS
Equation of state for this material, see EosEnum for options.
@ RHEOLOGY_YIELDING
Model of stress reducing used within the rheological model.
@ GRAVITY_CONSTANT
Gravitational constant. To be generalized.
DomainEnum
Definition: Settings.h:633
@ BLOCK
Block with edge sizes given by vector.
@ SPHERICAL
Sphere with given radius.
@ ELLIPSOIDAL
Axis-aligned ellipsoid.
@ CYLINDER
Cylindrical domain aligned with z axis.
constexpr Float gravity
Gravitational constant (CODATA 2014)
Definition: Constants.h:29
constexpr Float R_sun
Solar radius.
Definition: Constants.h:57
constexpr Float M_earth
Earth mass.
Definition: Constants.h:54
constexpr Float year
Number of seconds in a year.
Definition: Constants.h:47
constexpr Float M_sun
Definition: Constants.h:51
AutoPtr< IGravity > getGravity(const RunSettings &settings)
Definition: Factory.cpp:325
AutoPtr< IMaterial > getMaterial(const BodySettings &settings)
Definition: Factory.cpp:508
AutoPtr< IDistribution > getDistribution(const BodySettings &settings, Function< bool(Float)> progressCallback=nullptr)
Definition: Factory.cpp:228
AutoPtr< IDomain > getDomain(const RunSettings &settings)
Definition: Factory.cpp:416
AutoPtr< IRng > getRng(const RunSettings &settings)
Definition: Factory.cpp:621
SharedPtr< IScheduler > getScheduler(const RunSettings &settings=RunSettings::getDefaults())
Definition: Factory.cpp:178
Storage generateIc(const RunSettings &globals, const GalaxySettings &settings, const IProgressCallbacks &callbacks)
Definition: Galaxy.cpp:422
Vector getCenterOfMass(ArrayView< const Float > m, ArrayView< const Vector > r, ArrayView< const Size > idxs=nullptr)
Computes the center of mass.
Definition: Analysis.cpp:461
Storage generateIc(const IDistribution &distribution, const Size particleCnt, const Float radius, const Float mass, const Float n)
Creates a spherical polytropic star.
Definition: Stellar.cpp:67
Parameters of DiehlDistribution.
Definition: Distribution.h:108
DensityFunc particleDensity
Function specifies the particle density in space.
Definition: Distribution.h:115
Size numOfIters
Number of iterations.
Definition: Distribution.h:126
Float strength
Magnitude of a repulsive force between particles that moves them to their final locations.
Definition: Distribution.h:131
Function< bool(Size iter, ArrayView< const Vector > r)> onIteration
Optional callback executed once every iteration.
Definition: Distribution.h:143
Wrapper of an enum.
Definition: Settings.h:37
Holds data needed to create a single body in addHeterogeneousBody function.
Definition: Initial.h:154
SharedPtr< IDomain > domain
Definition: Initial.h:155
SharedPtr< IMaterial > material
Definition: Initial.h:156
Helper class, allowing to register job into the global list of jobs.
Definition: Job.h:203
Shared data used when creating all bodies in the simulation.
Definition: IMaterial.h:89
Storage storage
Holds all particle positions and other quantities.
Definition: Job.h:35
RunSettings overrides
Overrides associated with the particle state.
Definition: Job.h:43
Holds the information about a power-law size-frequency distributions.
Definition: Initial.h:73
Helper class for adding individual enums to the enum map.
Definition: EnumMap.h:175