AutoPas  3.0.0
Loading...
Searching...
No Matches
HCPGenerator.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <array>
10#include <cmath>
11
13
18
27inline size_t getNumberOfParticles(const std::array<double, 3> &boxMin, const std::array<double, 3> &boxMax,
28 const double spacing = 1.0, const bool centeredAlignment = false) {
29 if (spacing <= 0.0) {
30 return 0;
31 }
32
33 const double spacingRow = spacing * sqrt(3. / 4.);
34 const double spacingLayer = spacing * sqrt(2. / 3.);
35 const double xOffset = spacing * 1. / 2.;
36 const double yOffset = spacing * sqrt(1. / 12.);
37
38 std::array<double, 3> offset = {0.0, 0.0, 0.0};
39 if (centeredAlignment) {
40 offset = {spacing / 4.0, yOffset, spacingLayer / 2.0};
41 }
42
43 auto countSteps = [](const double start, const double stop, const double step) -> size_t {
44 if (stop <= start or step <= 0.0) {
45 return 0;
46 }
47 const auto count = static_cast<size_t>(std::ceil((stop - start) / step));
48 return count;
49 };
50
51 const size_t numLayersZ = countSteps(boxMin[2] + offset[2], boxMax[2], spacingLayer);
52 if (numLayersZ == 0) {
53 return 0;
54 }
55 const size_t numEvenLayers = (numLayersZ + 1) / 2;
56 const size_t numOddLayers = numLayersZ / 2;
57
58 const double startYEven = boxMin[1] + offset[1];
59 const size_t nyEvenLayer = countSteps(startYEven, boxMax[1], spacingRow);
60
61 const double startYOdd = boxMin[1] + yOffset + offset[1];
62 const size_t nyOddLayer = countSteps(startYOdd, boxMax[1], spacingRow);
63
64 const double startXEvenRow = boxMin[0] + offset[0];
65 const size_t nxEvenRow = countSteps(startXEvenRow, boxMax[0], spacing);
66
67 const double startXOddRow = boxMin[0] + xOffset + offset[0];
68 const size_t nxOddRow = countSteps(startXOddRow, boxMax[0], spacing);
69
70 const size_t nyEvenLayerEvenRows = (nyEvenLayer + 1) / 2;
71 const size_t nyEvenLayerOddRows = nyEvenLayer / 2;
72 const size_t particlesPerEvenLayer = nyEvenLayerEvenRows * nxEvenRow + nyEvenLayerOddRows * nxOddRow;
73
74 const size_t nyOddLayerOddRows = (nyOddLayer + 1) / 2;
75 const size_t nyOddLayerEvenRows = nyOddLayer / 2;
76 const size_t particlesPerOddLayer = nyOddLayerOddRows * nxOddRow + nyOddLayerEvenRows * nxEvenRow;
77
78 return numEvenLayers * particlesPerEvenLayer + numOddLayers * particlesPerOddLayer;
79}
80
92template <class Container>
93void fillWithParticles(Container &container, const std::array<double, 3> &boxMin, const std::array<double, 3> &boxMax,
94 const typename autopas::utils::ParticleTypeTrait<Container>::value &defaultParticle =
96 const double spacing = 1., const bool centeredAlignment = false) {
97 // Spacing in y direction when only moving 60° on the unit circle. Or the height in an equilateral triangle.
98 const double spacingRow = spacing * sqrt(3. / 4.);
99 // Spacing in z direction. Height in an equilateral tetrahedron.
100 const double spacingLayer = spacing * sqrt(2. / 3.);
101 // Shorter part of the bisectrix when split at the intersection of all bisectrices.
102 const double xOffset = spacing * 1. / 2.;
103 // Shorter part of the bisectrix when split at the intersection of all bisectrices.
104 const double yOffset = spacing * sqrt(1. / 12.);
105
106 // The packing alternates between odd and even layers and rows
107 bool evenLayer = true;
108
109 // centered offset
110 std::array<double, 3> offset = {0.0, 0.0, 0.0};
111 if (centeredAlignment) {
112 offset = {spacing / 4.0, yOffset, spacingLayer / 2.0};
113 }
114
115 size_t id = defaultParticle.getID();
116 for (double z = boxMin[2] + offset[2]; z < boxMax[2]; z += spacingLayer) {
117 const double startY = (evenLayer ? boxMin[1] : boxMin[1] + yOffset) + offset[1];
118 bool evenRow = evenLayer; // To ensure layers are alternating as for hexagonal close packed.
119 for (double y = startY; y < boxMax[1]; y += spacingRow) {
120 const double startX = (evenRow ? boxMin[0] : boxMin[0] + xOffset) + offset[0];
121 for (double x = startX; x < boxMax[0]; x += spacing) {
122 auto p = defaultParticle;
123 p.setR({x, y, z});
124 p.setID(id++);
125 container.addParticle(p);
126 }
127 evenRow = not evenRow;
128 }
129 evenLayer = not evenLayer;
130 }
131};
132}; // namespace autopas::generators::HCPGenerator
Generator for an hexagonally closest packed particle grid.
Definition: HCPGenerator.h:17
size_t getNumberOfParticles(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, const double spacing=1.0, const bool centeredAlignment=false)
Calculates the number of particles generated in an HCP lattice within [boxMin, boxMax) in O(1) time.
Definition: HCPGenerator.h:27
void fillWithParticles(Container &container, const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, const typename autopas::utils::ParticleTypeTrait< Container >::value &defaultParticle=typename autopas::utils::ParticleTypeTrait< Container >::value(), const double spacing=1., const bool centeredAlignment=false)
Fills any container (also AutoPas object) with hexagonally closest packed particles.
Definition: HCPGenerator.h:93
typename Container::ParticleType value
The Particle Type.
Definition: ParticleTypeTrait.h:24