PSCF v1.3
cpu/WaveList.tpp
1#ifndef PRDC_CPU_WAVE_LIST_TPP
2#define PRDC_CPU_WAVE_LIST_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field
6*
7* Copyright 2015 - 2025, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "WaveList.h"
12
13#include <prdc/cpu/FFT.h>
14#include <prdc/crystal/UnitCell.h>
15#include <prdc/crystal/shiftToMinimum.h>
16#include <prdc/crystal/hasVariableAngle.h>
17
18#include <pscf/mesh/MeshIterator.h>
19#include <pscf/mesh/Mesh.h>
20
21namespace Pscf {
22namespace Prdc {
23namespace Cpu {
24
25 /*
26 * Constructor.
27 */
28 template <int D>
30 : kSize_(0),
31 isAllocated_(false),
32 hasMinImages_(false),
33 hasKSq_(false),
34 hasdKSq_(false),
35 unitCellPtr_(nullptr),
36 meshPtr_(nullptr)
37 { isRealField_ = isRealField; }
38
39 /*
40 * Destructor.
41 */
42 template <int D>
45
46 /*
47 * Allocate memory used by WaveList.
48 */
49 template <int D>
50 void WaveList<D>::allocate(Mesh<D> const & m, UnitCell<D> const & c)
51 {
52 UTIL_CHECK(m.size() > 0);
53 UTIL_CHECK(c.nParameter() > 0);
54 UTIL_CHECK(!isAllocated_);
55
56 // Create permanent associations with mesh and unit cell
57 unitCellPtr_ = &c;
58 meshPtr_ = &m;
59
60 // Local copies of properties
61 int nParams = unitCell().nParameter();
62 IntVec<D> const & meshDimensions = mesh().dimensions();
63
64 // Compute kMeshDimensions_ and kSize_
65 if (isRealField_) {
66 FFT<D>::computeKMesh(meshDimensions, kMeshDimensions_, kSize_);
67 } else {
68 kMeshDimensions_ = meshDimensions;
69 kSize_ = mesh().size();
70 }
71
72 // Allocate memory
73 minImages_.allocate(kSize_);
74 kSq_.allocate(kMeshDimensions_);
75 dKSq_.allocate(nParams);
76 for (int i = 0; i < nParams; i++) {
77 dKSq_[i].allocate(kMeshDimensions_);
78 }
79
80 // Allocate and set up implicitInverse_ array if isRealField_ == true
81 // (only depends on mesh dimensions, only used for real fields)
82 if (isRealField_) {
83 implicitInverse_.allocate(kSize_);
84
85 MeshIterator<D> kItr(kMeshDimensions_);
86 int rank;
87
88 for (kItr.begin(); !kItr.atEnd(); ++kItr) {
89 rank = kItr.rank();
90 implicitInverse_[rank] =
91 FFT<D>::hasImplicitInverse(kItr.position(), meshDimensions);
92 }
93 }
94
96 isAllocated_ = true;
97 }
98
99 /*
100 * Clear all data that depends on unit cell parameters.
101 */
102 template <int D>
104 {
105 hasKSq_ = false;
106 hasdKSq_ = false;
107 if (hasVariableAngle<D>(unitCell().lattice())) {
108 hasMinImages_ = false;
109 }
110 }
111
112 /*
113 * Compute minimum image vectors for all wavevectors.
114 */
115 template <int D>
117 {
118 if (hasMinImages_) return; // min images already calculated
119
120 // Precondition
121 UTIL_CHECK(isAllocated_);
122 UTIL_CHECK(unitCell().lattice() != UnitCell<D>::Null);
123 UTIL_CHECK(unitCell().isInitialized());
124 UTIL_CHECK(minImages_.capacity() == kSize_);
125
126 MeshIterator<D> kItr(kMeshDimensions_);
127 int rank;
128 for (kItr.begin(); !kItr.atEnd(); ++kItr) {
129 rank = kItr.rank();
130 minImages_[rank] = shiftToMinimum(kItr.position(),
131 mesh().dimensions(), unitCell());
132 kSq_[rank] = unitCell().ksq(minImages_[rank]);
133 }
134
135 hasMinImages_ = true;
136 hasKSq_ = true;
137 }
138
139 /*
140 * Compute array of value of |k|^2
141 */
142 template <int D>
144 {
145 // If kSq_ is valid, return immediately without recomputing
146 if (hasKSq_) return;
147
148 // If necessary, compute minimum images.
149 if (!hasMinImages_) {
150 computeMinimumImages(); // computes both min images and kSq
151 return;
152 }
153
154 // Preconditions
155 UTIL_CHECK(isAllocated_);
156 UTIL_CHECK(unitCell().nParameter() > 0);
157 UTIL_CHECK(unitCell().lattice() != UnitCell<D>::Null);
158 UTIL_CHECK(unitCell().isInitialized());
159
160 // Compute kSq_
161 MeshIterator<D> kItr(kMeshDimensions_);
162 int rank;
163 for (kItr.begin(); !kItr.atEnd(); ++kItr) {
164 rank = kItr.rank();
165 kSq_[rank] = unitCell().ksq(minImages_[rank]);
166 }
167
168 hasKSq_ = true;
169 }
170
171 /*
172 * Compute derivatives of |k|^2 w/ respect to unit cell parameters.
173 */
174 template <int D>
176 {
177 if (hasdKSq_) return; // dKSq already calculated
178
179 // Compute minimum images if needed
180 if (!hasMinImages_) {
182 }
183
184 // Preconditions
185 UTIL_CHECK(isAllocated_);
186 UTIL_CHECK(unitCell().nParameter() > 0);
187 UTIL_CHECK(unitCell().lattice() != UnitCell<D>::Null);
188 UTIL_CHECK(unitCell().isInitialized());
189
190 MeshIterator<D> kItr(kMeshDimensions_);
191 int i, rank;
192 for (i = 0 ; i < unitCell().nParameter(); ++i) {
193 RField<D>& dksq = dKSq_[i];
194 for (kItr.begin(); !kItr.atEnd(); ++kItr) {
195 rank = kItr.rank();
196 dksq[rank] = unitCell().dksq(minImages_[rank], i);
197 if (isRealField_) {
198 if (implicitInverse_[rank]) {
199 dksq[rank] *= 2.0;
200 }
201 }
202 }
203 }
204
205 hasdKSq_ = true;
206 }
207
208}
209}
210}
211#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Iterator over points in a Mesh<D>.
int rank() const
Get the rank of current element.
void begin()
Set iterator to the first point in the mesh.
bool atEnd() const
Is this the end (i.e., one past the last point)?
IntVec< D > position() const
Get current position in the grid, as integer vector.
Description of a regular grid of points in a periodic domain.
Definition Mesh.h:61
int size() const
Get total number of grid points.
Definition Mesh.h:229
static void computeKMesh(IntVec< D > const &rMeshDimensions, IntVec< D > &kMeshDimensions, int &kSize)
Compute dimensions and size of k-space mesh for DFT of real data.
Definition cpu/FFT.tpp:262
static bool hasImplicitInverse(IntVec< D > const &wavevector, IntVec< D > const &meshDimensions)
Does this wavevector have implicit inverse in DFT or real data?
Definition cpu/FFT.h:271
Field of real double precision values on an FFT mesh.
Definition cpu/RField.h:29
void clearUnitCellData()
Clear all internal data that depends on lattice parameters.
void computedKSq()
Compute derivatives of |k|^2 w/ respect to unit cell parameters.
WaveList(bool isRealField=true)
Constructor.
void computeMinimumImages()
Compute minimum images of wavevectors.
void allocate(Mesh< D > const &m, UnitCell< D > const &c)
Allocate memory and set association with a Mesh and UnitCell object.
void computeKSq()
Compute sq.
bool isRealField() const
Does this WaveList correspond to real-valued fields?
int nParameter() const
Get the number of parameters in the unit cell.
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
Fields and FFTs for periodic boundary conditions (CPU)
Definition CField.cpp:12
Periodic fields and crystallography.
Definition CField.cpp:11
bool hasVariableAngle(typename UnitCell< D >::LatticeSystem lattice)
Return true if lattice type has variable angle parameters.
PSCF package top-level namespace.
Definition param_pc.dox:1