PSCF v1.1
SpaceGroup.tpp
1#ifndef PSCF_SPACE_GROUP_TPP
2#define PSCF_SPACE_GROUP_TPP
3
4/*
5* Simpatico - Simulation Package for Polymeric and Molecular Liquids
6*
7* Copyright 2016 - 2022, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include <pscf/crystal/SpaceGroup.h>
12#include <pscf/crystal/groupFile.h>
13
14namespace Pscf
15{
16
17 using namespace Util;
18
19 /*
20 * Find inversion center, if any.
21 */
22 template <int D>
23 bool
25 typename SpaceSymmetry<D>::Translation& center)
26 const
27 {
28 bool isInversion = false;
29 int i, j, k;
30 for (i = 0; i < size(); ++i) {
31 isInversion = true;
32 for (j = 0; j < D; ++j) {
33 for (k = 0; k < D; ++k) {
34 if (j == k) {
35 if ((*this)[i].R(j,k) != -1) isInversion = false;
36 } else {
37 if ((*this)[i].R(j,k) != 0) isInversion = false;
38 }
39 }
40 }
41 if (isInversion) {
42 for (int j = 0; j < D; ++j) {
43 center[j] = (*this)[i].t(j)/2;
44 }
45 return true;
46 }
47 }
48 return false;
49 }
50
51 template <int D>
53 typename SpaceSymmetry<D>::Translation const & origin)
54 {
55 for (int i = 0; i < size(); ++i) {
56 (*this)[i].shiftOrigin(origin);
57 }
58 }
59
60 /*
61 * Check if a mesh is compatible with this space group.
62 */
63 template <int D>
65 const
66 {
67
68 // ---------------------------------------------------------------
69 // Check compatibility of mesh dimensions & translations
70 // ---------------------------------------------------------------
71
72 // Identify required divisor of mesh dimension in each direction
73 int numerator, denominator;
74 IntVec<D> divisors;
75 for (int i = 0; i < D; ++i) {
76 // Find maximum denominator
77 divisors[i] = 1;
78 for (int j = 0; j < size(); ++j) {
79 numerator = (*this)[j].t(i).num();
80 denominator = (*this)[j].t(i).den();
81 if (numerator != 0) {
82 UTIL_CHECK(denominator > 0);
83 if (denominator > divisors[i]) {
84 divisors[i] = denominator;
85 }
86 }
87 }
88 // Make sure each divisor is a multiple of all denominators
89 for (int j = 0; j < size(); ++j) {
90 numerator = (*this)[j].t(i).num();
91 denominator = (*this)[j].t(i).den();
92 if (numerator != 0) {
93 if (denominator < divisors[i]) {
94 if (divisors[i]%denominator != 0) {
95 divisors[i] = divisors[i]*denominator;
96 }
97 }
98 }
99 }
100 }
101
102 // Check that mesh dimensions are multiples of required divisor
103 for (int i = 1; i < D; ++i) {
104 if (dimensions[i]%divisors[i] != 0) {
105 Log::file()
106 << "\n"
107 << "Mesh dimensions incompatible with the space group:\n"
108 << " dimensions[" << i << "] = " << dimensions[i] << "\n"
109 << " This dimension must be a multiple of " << divisors[i]
110 << "\n\n";
111 UTIL_THROW("Error: Mesh not incompatible with space group");
112 }
113 }
114
115 // ---------------------------------------------------------------
116 // Check compatibility of mesh dimensions & point group operations
117 // ---------------------------------------------------------------
118
119 // Identify pairs of directions that are related by point group ops
120 FMatrix<bool, D, D> areRelated;
121 for (int i = 0; i < D; ++i) {
122 for (int j = 0; j < D; ++j) {
123 areRelated(i, j) = false;
124 }
125 areRelated(i, i) = true;
126 }
127 for (int k = 0; k < size(); ++k) {
128 for (int i = 0; i < D; ++i) {
129 for (int j = 0; j < D; ++j) {
130 if (i != j) {
131 if ( (*this)[k].R(i,j) != 0) {
132 areRelated(i, j) = true;
133 areRelated(j, i) = true;
134 }
135 }
136 }
137 }
138 }
139
140 // Check if mesh dimensions are equal for related directions
141 for (int i = 0; i < D; ++i) {
142 for (int j = 0; j < i; ++j) {
143 if (areRelated(i,j) && (dimensions[i] != dimensions[j])) {
144 Log::file()
145 << "\n"
146 << "Mesh dimensions incompatible with the space group - \n"
147 << "Unequal dimensions for related directions:\n"
148 << " dimensions[" << i << "] = " << dimensions[i] << "\n"
149 << " dimensions[" << j << "] = " << dimensions[j]
150 << "\n\n";
151 UTIL_THROW("Error: Mesh not incompatible with space group");
152 }
153 }
154 }
155
156 }
157
158 /*
159 * Read a group from file
160 */
161 template <int D>
162 void readGroup(std::string groupName, SpaceGroup<D>& group)
163 {
164 if (groupName == "I") {
165 // Create identity group by default
166 group.makeCompleteGroup();
167 } else {
168 bool foundFile = false;
169 {
170 // Search first in this directory
171 std::ifstream in;
172 in.open(groupName);
173 if (in.is_open()) {
174 in >> group;
175 UTIL_CHECK(group.isValid());
176 foundFile = true;
177 }
178 }
179 if (!foundFile) {
180 // Search in the data directory containing standard space groups
181 std::string fileName = makeGroupFileName(D, groupName);
182 std::ifstream in;
183 in.open(fileName);
184 if (in.is_open()) {
185 in >> group;
186 UTIL_CHECK(group.isValid());
187 } else {
188 Log::file() << "\nFailed to open group file: "
189 << fileName << "\n";
190 Log::file() << "\n Error: Unknown space group\n";
191 UTIL_THROW("Unknown space group");
192 }
193 }
194 }
195 }
196
197 /*
198 * Open an output file and write group to file.
199 */
200 template <int D>
201 void writeGroup(std::string filename, SpaceGroup<D> const & group)
202 {
203 std::ofstream out;
204 out.open(filename);
205 out << group;
206 }
207
208}
209#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition: IntVec.h:27
Crystallographic space group.
Definition: SpaceGroup.h:30
bool hasInversionCenter(typename SpaceSymmetry< D >::Translation &center) const
Determines if this space group has an inversion center.
Definition: SpaceGroup.tpp:24
void checkMeshDimensions(IntVec< D > const &dimensions) const
Check if input mesh dimensions are compatible with space group.
Definition: SpaceGroup.tpp:64
void shiftOrigin(typename SpaceSymmetry< D >::Translation const &origin)
Shift the origin of space used in the coordinate system.
Definition: SpaceGroup.tpp:52
void makeCompleteGroup()
Generate a complete group from the current elements.
Fixed Size Matrix.
Definition: FMatrix.h:29
static std::ostream & file()
Get log ostream by reference.
Definition: Log.cpp:57
#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:51
std::string makeGroupFileName(int D, std::string groupName)
Generates the file name from a group name.
Definition: groupFile.cpp:25
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1