PSCF v1.3.2
rpc/fts/compressor/AmCompressor.tpp
1#ifndef RPC_AM_COMPRESSOR_TPP
2#define RPC_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 "AmCompressor.h"
12#include <rpc/system/System.h>
13#include <rpc/solvers/Mixture.h>
14#include <rpc/field/Domain.h>
15#include <util/global.h>
16
17namespace Pscf {
18namespace Rpc {
19
20 using namespace Util;
21
22 // Public member functions
23
24 /*
25 * Constructor.
26 */
27 template <int D>
29 : Compressor<D>(system),
30 isAllocated_(false)
31 { ParamComposite::setClassName("AmCompressor"); }
32
33 /*
34 * Destructor.
35 */
36 template <int D>
39
40 /*
41 * Read parameters from file.
42 */
43 template <int D>
44 void AmCompressor<D>::readParameters(std::istream& in)
45 {
46 // Default values
47 AmTmpl::maxItr_ = 100;
49 AmTmpl::errorType_ = "rms";
50 bool useLambdaRamp = false;
51
54 AmTmpl::readMixingParameters(in, useLambdaRamp);
55 }
56
57 /*
58 * Initialize just before entry to iterative loop.
59 */
60 template <int D>
61 void AmCompressor<D>::setup(bool isContinuation)
62 {
63 // Allocate memory required by AM algorithm if not done earlier.
64 AmTmpl::setup(isContinuation);
65
66 const int nMonomer = system().mixture().nMonomer();
67 const int meshSize = system().domain().mesh().size();
68 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
69
70 // Allocate memory required by compressor if not done earlier.
71 if (!isAllocated_){
72 w0_.allocate(nMonomer);
73 wFieldTmp_.allocate(nMonomer);
74 for (int i = 0; i < nMonomer; ++i) {
75 w0_[i].allocate(dimensions);
76 wFieldTmp_[i].allocate(dimensions);
77 }
78 isAllocated_ = true;
79 }
80
81 // Store value of initial guess chemical potential fields
82 for (int i = 0; i < nMonomer; ++i) {
83 for (int j = 0; j< meshSize; ++j){
84 w0_[i][j] = system().w().rgrid(i)[j];
85 }
86 }
87 }
88
89 /*
90 * Main function - identify partial saddle-point state.
91 */
92 template <int D>
94 {
95 int solve = AmTmpl::solve();
96 return solve;
97 }
98
99 /*
100 * Output timer information, if requested.
101 */
102 template<int D>
103 void AmCompressor<D>::outputTimers(std::ostream& out) const
104 {
105 out << "\n";
106 out << "AmCompressor time contributions:\n";
108 }
109
110 /*
111 * Clear timers and MDE counter.
112 */
113 template<int D>
119
120 // Private virtual functions that interact with parent system
121
122 /*
123 * Does the system have an initial field guess?
124 */
125 template <int D>
126 bool AmCompressor<D>::hasInitialGuess()
127 { return system().w().hasData(); }
128
129 /*
130 * Compute and return the number of elements in a field vector.
131 */
132 template <int D>
133 int AmCompressor<D>::nElements()
134 { return system().domain().mesh().size(); }
135
136 /*
137 * Get the current field from the system.
138 */
139 template <int D>
140 void AmCompressor<D>::getCurrent(DArray<double>& curr)
141 {
142 // Straighten out fields into linear arrays
143 const int meshSize = system().domain().mesh().size();
144 const DArray< RField<D> > * currSys = &system().w().rgrid();
145
146 /*
147 * The field that we are adjusting is the Langrange multiplier
148 * field. The current value is the difference between w and w0_
149 * for the first monomer type, but any monomer type would give
150 * the same answer.
151 */
152 for (int i = 0; i < meshSize; i++){
153 curr[i] = (*currSys)[0][i] - w0_[0][i];
154 }
155
156 }
157
158 /*
159 * Perform the main system computation (solve the MDE).
160 */
161 template <int D>
162 void AmCompressor<D>::evaluate()
163 {
164 system().compute();
166 }
167
168 /*
169 * Compute the residual vector for the current system state.
170 */
171 template <int D>
172 void AmCompressor<D>::getResidual(DArray<double>& resid)
173 {
174 const int n = nElements();
175 const int nMonomer = system().mixture().nMonomer();
176 const int meshSize = system().domain().mesh().size();
177
178 // Initialize residuals
179 for (int i = 0 ; i < n; ++i) {
180 resid[i] = -1.0;
181 }
182
183 // Compute SCF residual vector elements
184 for (int j = 0; j < nMonomer; ++j) {
185 for (int k = 0; k < meshSize; ++k) {
186 resid[k] += system().c().rgrid(j)[k];
187 }
188 }
189
190 }
191
192 /*
193 * Update the current system field coordinates.
194 */
195 template <int D>
196 void AmCompressor<D>::update(DArray<double>& newGuess)
197 {
198 // Convert back to field format
199 const int nMonomer = system().mixture().nMonomer();
200 const int meshSize = system().domain().mesh().size();
201
202 // New field is the w0_ + newGuess for the pressure field
203 for (int i = 0; i < nMonomer; i++){
204 for (int k = 0; k < meshSize; k++){
205 wFieldTmp_[i][k] = w0_[i][k] + newGuess[k];
206 }
207 }
208 system().w().setRGrid(wFieldTmp_);
209 }
210
211 /*
212 * Do-nothing output function.
213 */
214 template<int D>
215 void AmCompressor<D>::outputToLog()
216 {}
217
218}
219}
220#endif
void readMixingParameters(std::istream &in, bool useLambdaRamp=true)
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
int compress() override
Compress to obtain partial saddle point w+.
void outputTimers(std::ostream &out) const override
Return compressor times contributions.
AmCompressor(System< D > &system)
Constructor.
void setup(bool isContinuation) override
Initialize just before entry to iterative loop.
void readParameters(std::istream &in) override
Read all parameters and initialize.
void clearTimers() override
Clear all timers (reset accumulated time to zero).
Base class for iterators that impose incompressibility.
int mdeCounter_
Count how many times MDE has been solved.
Main class, representing a complete physical system.
Dynamically allocatable contiguous array template.
Definition DArray.h:32
void setClassName(const char *className)
Set class name string.
File containing preprocessor macros for error handling.
Real periodic fields, SCFT and PS-FTS (CPU).
Definition param_pc.dox:2
PSCF package top-level namespace.