PSCF v1.3.2
rpg/fts/compressor/LrAmCompressor.tpp
1#ifndef RPG_LR_AM_COMPRESSOR_TPP
2#define RPG_LR_AM_COMPRESSOR_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 "LrAmCompressor.h"
12#include <rpg/system/System.h>
13#include <prdc/cuda/FFT.h>
14#include <prdc/cuda/resources.h>
15#include <pscf/mesh/MeshIterator.h>
16#include <util/global.h>
17
18namespace Pscf {
19namespace Rpg {
20
21 using namespace Util;
22
23 /*
24 * Constructor.
25 */
26 template <int D>
28 : Compressor<D>(system),
29 intra_(system),
30 isIntraCalculated_(false),
31 isAllocated_(false)
32 { ParamComposite::setClassName("LrAmCompressor"); }
33
34 /*
35 * Destructor.
36 */
37 template <int D>
40
41 /*
42 * Read parameters from file.
43 */
44 template <int D>
45 void LrAmCompressor<D>::readParameters(std::istream& in)
46 {
47 // Default values
48 Base::maxItr_ = 100;
50 Base::errorType_ = "rms";
51
52 // Call base class read methods
55 }
56
57 /*
58 * Initialize just before entry to iterative loop.
59 */
60 template <int D>
61 void LrAmCompressor<D>::setup(bool isContinuation)
62 {
63 const int nMonomer = system().mixture().nMonomer();
64 const int meshSize = system().domain().mesh().size();
65 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
66
67 // Allocate memory required by AM algorithm if not done earlier.
68 Base::setup(isContinuation);
69
70 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
71
72 // Compute Fourier space kMeshDimensions_
73 for (int i = 0; i < D; ++i) {
74 if (i < D - 1) {
75 kMeshDimensions_[i] = dimensions[i];
76 } else {
77 kMeshDimensions_[i] = dimensions[i]/2 + 1;
78 }
79 }
80
81 // Compute number of points in k-space grid
82 kSize_ = 1;
83 for (int i = 0; i < D; ++i) {
84 kSize_ *= kMeshDimensions_[i];
85 }
86
87 // Allocate memory required by compressor if not done earlier.
88 if (!isAllocated_) {
89 w0_.allocate(nMonomer);
90 wFieldTmp_.allocate(nMonomer);
91 resid_.allocate(dimensions);
92 residK_.allocate(dimensions);
93 intraCorrelationK_.allocate(kMeshDimensions_);
94 for (int i = 0; i < nMonomer; ++i) {
95 w0_[i].allocate(dimensions);
96 wFieldTmp_[i].allocate(dimensions);
97 }
98
99 isAllocated_ = true;
100 }
101
102 // Compute intraCorrelation
103 if (!isIntraCalculated_){
104 intra_.computeIntraCorrelations(intraCorrelationK_);
105 isIntraCalculated_ = true;
106 }
107
108 // Store value of initial guess chemical potential fields
109 for (int i = 0; i < nMonomer; ++i) {
110 VecOp::eqV(w0_[i], system().w().rgrid(i));
111 }
112
113 }
114
115 /*
116 * Main function - iteratively adjust the pressure field.
117 */
118 template <int D>
120 {
121 int solve = Base::solve();
122 return solve;
123 }
124
125 // Protected virtual function for AM algorithm operation
126
127 template <int D>
128 void
129 LrAmCompressor<D>::addCorrection(
130 VectorT& fieldTrial,
131 VectorT const & resTrial)
132 {
133 int n = fieldTrial.capacity();
134 const double vMonomer = system().mixture().vMonomer();
135
136 // Convert resTrial to RField<D> type
137 VecOp::eqV(resid_, resTrial);
138
139 // Convert residual to Fourier Space
140 system().domain().fft().forwardTransform(resid_, residK_);
141
142 // Combine with Linear response factor to update second step
143 VecOp::divEqVc(residK_, intraCorrelationK_, vMonomer);
144
145 // Convert back to real space (destroys residK_)
146 system().domain().fft().inverseTransformUnsafe(residK_, resid_);
147
148 // fieldTrial += resid_
149 VecOp::addEqVc(fieldTrial, resid_, 1.0);
150 }
151
152 // Private virtual functions that interact with parent System
153
154 /*
155 * Get the number of elements in a field vector.
156 */
157 template <int D>
158 int LrAmCompressor<D>::nElements()
159 { return system().domain().mesh().size(); }
160
161 /*
162 * Does the system have an initial field guess?
163 */
164 template <int D>
165 bool LrAmCompressor<D>::hasInitialGuess()
166 { return system().w().hasData(); }
167
168 /*
169 * Get the current field from the system.
170 */
171 template <int D>
172 void LrAmCompressor<D>::getCurrent(VectorT& curr)
173 {
174 /*
175 * The field that we are adjusting is the Langrange multiplier field
176 * with number of grid pts components.The current value is the difference
177 * between w and w0_ for the first monomer (any monomer should give the
178 * same answer)
179 */
180 VecOp::subVV(curr, system().w().rgrid(0), w0_[0]);
181 }
182
183 /*
184 * Perform the main system computation (solve the MDE).
185 */
186 template <int D>
187 void LrAmCompressor<D>::evaluate()
188 {
189 system().compute();
191 }
192
193 /*
194 * Compute the residual vector for the current system state.
195 */
196 template <int D>
197 void LrAmCompressor<D>::getResidual(VectorT& resid)
198 {
199 const int nMonomer = system().mixture().nMonomer();
200
201 // Initialize resid to c field of species 0 minus 1
202 VecOp::subVS(resid, system().c().rgrid(0), 1.0);
203
204 // Add other c fields to get SCF residual vector elements
205 for (int i = 1; i < nMonomer; i++) {
206 VecOp::addEqV(resid, system().c().rgrid(i));
207 }
208 }
209
210 /*
211 * Update the system state to reflect new state vector.
212 */
213 template <int D>
214 void LrAmCompressor<D>::update(VectorT& newGuess)
215 {
216 // Convert back to field format
217 const int nMonomer = system().mixture().nMonomer();
218
219 // New field is w0_[i] + newGuess for the Lagrange multiplier field
220 for (int i = 0; i < nMonomer; i++) {
221 VecOp::addVV(wFieldTmp_[i], w0_[i], newGuess);
222 }
223
224 // Set system r grid
225 system().w().setRGrid(wFieldTmp_);
226 }
227
228 /*
229 * Do-nothing output function.
230 */
231 template<int D>
232 void LrAmCompressor<D>::outputToLog()
233 {}
234
235 /*
236 * Output timer results.
237 */
238 template<int D>
239 void LrAmCompressor<D>::outputTimers(std::ostream& out) const
240 {
241 out << "\n";
242 out << "LrAmCompressor time contributions:\n";
244 }
245
246 /*
247 * Clear timers and MDE counter.
248 */
249 template<int D>
255
256 // Private virtual functions for vector math
257
258 /*
259 * Vector assignment, a = b.
260 */
261 template <int D>
262 void LrAmCompressor<D>::setEqual(VectorT& a,
263 VectorT const & b)
264 {
265 UTIL_CHECK(b.capacity() == a.capacity());
266 VecOp::eqV(a, b);
267 }
268
269 /*
270 * Compute and return inner product of two vectors.
271 */
272 template <int D>
273 double LrAmCompressor<D>::dotProduct(VectorT const & a,
274 VectorT const & b)
275 {
276 UTIL_CHECK(a.capacity() == b.capacity());
277 return Reduce::innerProduct(a, b);
278 }
279
280 /*
281 * Compute and return maximum element of a vector.
282 */
283 template <int D>
284 double LrAmCompressor<D>::maxAbs(VectorT const & a)
285 { return Reduce::maxAbs(a); }
286
287 /*
288 * Compute the vector difference a = b - c
289 */
290 template <int D>
291 void LrAmCompressor<D>::subVV(VectorT& a,
292 VectorT const & b,
293 VectorT const & c)
294 { VecOp::subVV(a, b, c); }
295
296 /*
297 * Compute a += b*c for vectors a and b, scalar c
298 */
299 template <int D>
300 void LrAmCompressor<D>::addEqVc(VectorT& a,
301 VectorT const & b,
302 double c)
303 { VecOp::addEqVc(a, b, c); }
304
305}
306}
307#endif
virtual void setup(bool isContinuation)
void outputTimers(std::ostream &out) const
virtual void readParameters(std::istream &in)
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
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
Base class for iterators that impose incompressibility.
int mdeCounter_
Count how many times MDE has been solved.
void outputTimers(std::ostream &out) const
Return compressor times contributions.
void readParameters(std::istream &in)
Read all parameters and initialize.
int compress()
Compress to obtain partial saddle point w+.
void clearTimers()
Clear all timers (reset accumulated time to zero).
void setup(bool isContinuation)
Initialize just before entry to iterative loop.
LrAmCompressor(System< D > &system)
Constructor.
Main class, representing a complete physical system.
void setClassName(const char *className)
Set class name string.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
double maxAbs(Array< double > const &in)
Get maximum absolute magnitude of array elements .
Definition Reduce.cpp:34
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute inner product of two real arrays .
Definition Reduce.cpp:94
void subVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector subtraction, a[i] = b[i] - c[i].
Definition VecOp.cpp:81
void addEqV(Array< double > &a, Array< double > const &b)
Vector addition in-place, a[i] += b[i].
Definition VecOp.cpp:199
void eqV(Array< double > &a, Array< double > const &b)
Vector assignment, a[i] = b[i].
Definition VecOp.cpp:23
void addVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector addition, a[i] = b[i] + c[i].
Definition VecOp.cpp:50
void subVS(Array< double > &a, Array< double > const &b, double c)
Vector subtraction, a[i] = b[i] - c.
Definition VecOp.cpp:96
void divEqVc(DeviceArray< cudaComplex > &a, DeviceArray< cudaReal > const &b, cudaReal const c)
Vector division in-place w/ coeff., a[i] /= (b[i] * c), kernel wrapper.
Definition VecOpMisc.cu:377
void addEqVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c)
Vector addition in-place w/ coefficient, a[i] += b[i] * c, kernel wrapper.
Definition VecOpMisc.cu:343
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.