PSCF v1.3
UnitCell2.cpp
1/*
2* PSCF - Polymer Self-Consistent Field
3*
4* Copyright 2015 - 2025, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include "UnitCell.h"
9#include <util/math/Constants.h>
10
11namespace Pscf {
12namespace Prdc {
13
14 using namespace Util;
15
16 // Member functions of UnitCell<2>
17
18 /*
19 * Constructor.
20 */
22 : lattice_(Null)
23 {}
24
25 /*
26 * Read the lattice system and set nParameter.
27 */
29 {
30 UTIL_CHECK(lattice_ != UnitCell<2>::Null);
31 if (lattice_ == UnitCell<2>::Square) {
32 nParameter_ = 1;
33 } else
34 if (lattice_ == UnitCell<2>::Hexagonal) {
35 nParameter_ = 1;
36 } else
37 if (lattice_ == UnitCell<2>::Rectangular) {
38 nParameter_ = 2;
39 } else
40 if (lattice_ == UnitCell<2>::Rhombic) {
41 nParameter_ = 2;
42 } else
43 if (lattice_ == UnitCell<2>::Oblique) {
44 nParameter_ = 3;
45 } else {
46 UTIL_THROW("Invalid lattice system value");
47 }
48 }
49
50 /*
51 * Set the Bravais and reciprocal lattice vectors.
52 */
53 void UnitCell<2>::setBasis()
54 {
55 UTIL_CHECK(lattice_ != UnitCell<2>::Null);
56 UTIL_CHECK(nParameter_ > 0);
57
58 double twoPi = 2.0*Constants::Pi;
59 int i;
60 if (lattice_ == UnitCell<2>::Square) {
61 UTIL_CHECK(nParameter_ == 1);
62 for (i=0; i < 2; ++i) {
63 rBasis_[i][i] = parameters_[0];
64 kBasis_[i][i] = twoPi/parameters_[0];
65 drBasis_[0](i,i) = 1.0;
66 }
67 } else
68 if (lattice_ == UnitCell<2>::Rectangular) {
69 UTIL_CHECK(nParameter_ == 2);
70 for (i=0; i < 2; ++i) {
71 rBasis_[i][i] = parameters_[i];
72 kBasis_[i][i] = twoPi/parameters_[i];
73 drBasis_[i](i,i) = 1.0;
74 }
75 } else
76 if (lattice_ == UnitCell<2>::Hexagonal) {
77 UTIL_CHECK(nParameter_ == 1);
78 double a = parameters_[0];
79 double rt3 = sqrt(3.0);
80
81 rBasis_[0][0] = a;
82 rBasis_[0][1] = 0.0;
83 rBasis_[1][0] = -0.5*a;
84 rBasis_[1][1] = 0.5*rt3*a;
85
86 drBasis_[0](0, 0) = 1.0;
87 drBasis_[0](0, 1) = 0.0;
88 drBasis_[0](1, 0) = -0.5;
89 drBasis_[0](1, 1) = 0.5*rt3;
90
91 kBasis_[0][0] = twoPi/a;
92 kBasis_[0][1] = twoPi/(rt3*a);
93 kBasis_[1][0] = 0.0;
94 kBasis_[1][1] = twoPi/(0.5*rt3*a);
95 } else
96 if (lattice_ == UnitCell<2>::Rhombic) {
97 UTIL_CHECK(nParameter_ == 2);
98 double a = parameters_[0];
99 double gamma = parameters_[1];
100 // gamma is the angle between the two Bravais basis vectors
101
102 double cg = cos(gamma);
103 double sg = sin(gamma);
104
105
106 rBasis_[0][0] = a;
107 rBasis_[0][1] = 0.0;
108 rBasis_[1][0] = cg*a;
109 rBasis_[1][1] = sg*a;
110
111 drBasis_[0](0, 0) = 1.0;
112 drBasis_[0](0, 1) = 0.0;
113 drBasis_[0](1, 0) = cg;
114 drBasis_[0](1, 1) = sg;
115 drBasis_[1](1, 0) = -sg*a;
116 drBasis_[1](1, 1) = cg*a;
117
118 kBasis_[0][0] = twoPi/a;
119 kBasis_[0][1] = -twoPi*cg/(sg*a);
120 kBasis_[1][0] = 0.0;
121 kBasis_[1][1] = twoPi/(a*sg);
122
123 } else
124 if (lattice_ == UnitCell<2>::Oblique) {
125 UTIL_CHECK(nParameter_ == 3);
126 double a = parameters_[0];
127 double b = parameters_[1];
128 double gamma = parameters_[2];
129 // gamma is the angle between the two Bravais basis vectors
130
131 double cg = cos(gamma);
132 double sg = sin(gamma);
133
134 rBasis_[0][0] = a;
135 rBasis_[0][1] = 0.0;
136 rBasis_[1][0] = cg*b;
137 rBasis_[1][1] = sg*b;
138
139 drBasis_[0](0, 0) = 1.0;
140 drBasis_[0](0, 1) = 0.0;
141 drBasis_[1](1, 0) = cg;
142 drBasis_[1](1, 1) = sg;
143 drBasis_[1](1, 0) = -sg*b;
144 drBasis_[1](1, 1) = cg*b;
145
146 kBasis_[0][0] = twoPi/a;
147 kBasis_[0][1] = -twoPi*cg/(sg*a);
148 kBasis_[1][0] = 0.0;
149 kBasis_[1][1] = twoPi/(b*sg);
150
151 } else {
152 UTIL_THROW("Unimplemented 2D lattice type");
153 }
154 }
155
156 /*
157 * Assignment operator.
158 */
160 {
161 if (lattice_ != UnitCell<2>::Null) {
162 UTIL_CHECK(other.lattice_ == lattice_);
163 }
164 isInitialized_ = false;
165 lattice_ = other.lattice_;
166 setNParameter();
168 for (int i = 0; i < nParameter_; ++i) {
169 parameters_[i] = other.parameters_[i];
170 }
171 setLattice();
172 return *this;
173 }
174
175 /*
176 * Set state of the unit cell (lattice system and parameters)
177 */
179 {
181 if (lattice_ != UnitCell<2>::Null) {
182 UTIL_CHECK(lattice == lattice_);
183 }
184 isInitialized_ = false;
185 lattice_ = lattice;
186 setNParameter();
187 }
188
189 /*
190 * Set state of the unit cell (lattice system and parameters)
191 */
194 {
195 set(lattice);
197 for (int i = 0; i < nParameter_; ++i) {
198 parameters_[i] = parameters[i];
199 }
200 setLattice();
201 }
202
203 /*
204 * Get the generalized 2D volume (area) of the unit cell.
205 */
206 double UnitCell<2>::volume() const
207 {
208 double a = 0.0;
209 a += rBasis_[0][0]*rBasis_[1][1];
210 a -= rBasis_[0][1]*rBasis_[1][0];
211 return a;
212 }
213
214 // UnitCell<2>::LatticeSystem stream IO operators
215
216 /*
217 * Extract a UnitCell<2>::LatticeSystem from an istream as a string.
218 */
219 std::istream& operator >> (std::istream& in,
221 {
222
223 std::string buffer;
224 in >> buffer;
225 if (buffer == "Square" || buffer == "square") {
226 lattice = UnitCell<2>::Square;
227 } else
228 if (buffer == "Rectangular" || buffer == "rectangular") {
229 lattice = UnitCell<2>::Rectangular;
230 } else
231 if (buffer == "Rhombic" || buffer == "rhombic") {
232 lattice = UnitCell<2>::Rhombic;
233 } else
234 if (buffer == "Hexagonal" || buffer == "hexagonal") {
235 lattice = UnitCell<2>::Hexagonal;
236 } else
237 if (buffer == "Oblique" || buffer == "oblique") {
238 lattice = UnitCell<2>::Oblique;
239 } else {
240 UTIL_THROW("Invalid UnitCell<2>::LatticeSystem value input");
241 }
242 return in;
243 }
244
245 /*
246 * Insert a UnitCell<2>::LatticeSystem to an ostream as a string.
247 */
248 std::ostream& operator << (std::ostream& out,
250 {
251 if (lattice == UnitCell<2>::Square) {
252 out << "square";
253 } else
254 if (lattice == UnitCell<2>::Rectangular) {
255 out << "rectangular";
256 } else
257 if (lattice == UnitCell<2>::Rhombic) {
258 out << "rhombic";
259 } else
260 if (lattice == UnitCell<2>::Hexagonal) {
261 out << "hexagonal";
262 } else
263 if (lattice == UnitCell<2>::Oblique) {
264 out << "oblique";
265 } else
266 if (lattice == UnitCell<2>::Null) {
267 out << "Null";
268 } else {
269 UTIL_THROW("This should never happen");
270 }
271 return out;
272 }
273
274}
275}
bool isInitialized_
Has this unit cell been fully initialized?
FArray< RealVec< D >, D > rBasis_
Array of Bravais lattice basis vectors.
FSArray< double, 6 > parameters() const
Get the parameters of this unit cell.
FArray< double, 6 > parameters_
Parameters used to describe the unit cell.
void setLattice()
Compute all protected data, given latticeSystem and parameters.
int nParameter_
Number of parameters required to specify unit cell.
void set(UnitCell< 2 >::LatticeSystem lattice)
Set the lattice system, but not unit cell parameters.
LatticeSystem lattice() const
Return lattice system enumeration value.
Definition UnitCell.h:306
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
static const double Pi
Trigonometric constant Pi.
Definition Constants.h:35
A fixed capacity (static) contiguous array with a variable logical size.
Definition FSArray.h:38
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
Periodic fields and crystallography.
Definition CField.cpp:11
PSCF package top-level namespace.
Definition param_pc.dox:1
std::istream & operator>>(std::istream &in, Pair< Data > &pair)
Input a Pair from an istream.
Definition Pair.h:44
std::ostream & operator<<(std::ostream &out, const Pair< Data > &pair)
Output a Pair to an ostream, without line breaks.
Definition Pair.h:57