PSCF v1.4.0
AverageListAnalyzer.tpp
1#ifndef RP_AVERAGE_LIST_ANALYZER_TPP
2#define RP_AVERAGE_LIST_ANALYZER_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 "AverageListAnalyzer.h"
12
13#include <util/format/Int.h>
14#include <util/format/Dbl.h>
15#include <util/misc/FileMaster.h>
16#include <util/misc/ioUtil.h>
17
18namespace Pscf {
19namespace Rp {
20
21 using namespace Util;
22
23 /*
24 * Constructor.
25 */
26 template <int D, class T>
28 typename T::Simulator& simulator,
29 typename T::System& system)
30 : AnalyzerT(simulator, system),
31 nSamplePerOutput_(1),
32 nValue_(0),
33 hasAccumulators_(false)
34 { AnalyzerT::setFileMaster(system.fileMaster()); }
35
36 /*
37 * Read interval and outputFileName.
38 */
39 template <int D, class T>
41 {
42 AnalyzerT::readParameters(in);
43 nSamplePerOutput_ = 1;
44 ParamComposite::readOptional(in,"nSamplePerOutput",
45 nSamplePerOutput_);
46 UTIL_CHECK(nSamplePerOutput_ >= 0);
47 if (nSamplePerOutput() > 0) {
48 std::string fileName = AnalyzerT::outputFileName(".dat");
49 system().fileMaster().openOutputFile(fileName, outputFile_);
50 }
51 // Note: ReadParameters method of derived classes should call this,
52 // determine nValue and then call initializeAccumulators(nValue).
53 }
54
55 /*
56 * Setup before simulation.
57 */
58 template <int D, class T>
60 {
61 UTIL_CHECK(hasAccumulators_);
63 }
65 /*
66 * Compute and sample current values.
67 */
68 template <int D, class T>
70 {
71 UTIL_CHECK(hasAccumulators_);
72 if (AnalyzerT::isAtInterval(iStep)) {
73 compute();
74 updateAccumulators(iStep);
75 }
76 }
77
78 /*
79 * Output results after a simulation is completed.
80 */
81 template <int D, class T>
83 {
84 UTIL_CHECK(hasAccumulators_);
85
86 // Close data file, if any
87 if (outputFile_.is_open()) {
88 outputFile_.close();
89 }
90
91 #if 0
92 // Write parameter (*.prm) file
93 std::string filename = AnalyzerT::outputFileName(".prm");
94 system().fileMaster().openOutputFile(filename, outputFile_);
96 outputFile_.close();
97 #endif
98
99 // Write average (*.ave) and error analysis (*.aer) files
101 }
102
106 template <int D, class T>
108 {
109 UTIL_CHECK(nValue > 0);
110 UTIL_CHECK(nValue_ == 0);
111 UTIL_CHECK(nSamplePerOutput_ >= 0);
112
113 // Allocate arrays
114 accumulators_.allocate(nValue);
115 names_.allocate(nValue);
116 values_.allocate(nValue);
117 nValue_ = nValue;
118 hasAccumulators_ = true;
119
120 // Set the accumulators to compute block averages with
121 // nSamplePerOutput_ sampled values per block
122 for (int i = 0; i < nValue_; ++i) {
123 accumulators_[i].setNSamplePerBlock(nSamplePerOutput_);
124 }
125
128
129 /*
130 * Clear accumulators.
131 */
132 template <int D, class T>
134 {
135 UTIL_CHECK(hasAccumulators_);
136 UTIL_CHECK(nValue_ > 0);
137 for (int i = 0; i < nValue_; ++i) {
138 accumulators_[i].clear();
139 }
140 }
142 /*
143 * Set the name string for variable with index i.
144 */
145 template <int D, class T>
147 {
148 UTIL_CHECK(hasAccumulators_);
149 UTIL_CHECK(i >= 0 && i < nValue_);
150 names_[i] = name;
151 }
152
153 /*
154 * Update accumulators for all current values.
155 */
156 template <int D, class T>
158 {
159 UTIL_CHECK(hasAccumulators_);
160 UTIL_CHECK(accumulators_.capacity() == nValue_);
161
162 // Update accumulators.
163 for (int i = 0; i < nValue(); ++i) {
164 double data = value(i);
165 accumulators_[i].sample(data);
166 }
167
168 // Output block averages
169 if (nSamplePerOutput_ > 0) {
170 if (accumulators_[0].isBlockComplete()) {
171 UTIL_CHECK(outputFile_.is_open());
172 int interval = AnalyzerT::interval();
173 int beginStep = iStep - (nSamplePerOutput_ - 1) * interval;
174 outputFile_ << Int(beginStep);
175 for (int i = 0; i < nValue(); ++i) {
176 UTIL_CHECK(accumulators_[i].isBlockComplete());
177 double block = accumulators_[i].blockAverage();
178 outputFile_ << Dbl(block);
179 }
180 outputFile_ << "\n";
181 }
182 }
183
184 }
185
186 /*
187 * Output results to file after simulation is completed.
188 */
189 template <int D, class T>
191 {
192 UTIL_CHECK(hasAccumulators_);
193
194 // Close data (*.dat) file, if any
195 if (outputFile_.is_open()) {
196 outputFile_.close();
197 }
198
199 // Compute maximum length of name field
200 int nameWidth = 0;
201 int length;
202 for (int i = 0; i < nValue_; ++i) {
203 length = names_[i].length();
204 if (length > nameWidth) {
205 nameWidth = length;
206 }
207 }
208 nameWidth += 2;
209
210 // Write average (*.ave) file
211 std::string fileName = AnalyzerT::outputFileName(".ave");
212 system().fileMaster().openOutputFile(fileName, outputFile_);
213 double ave, err;
214 for (int i = 0; i < nValue_; ++i) {
215 ave = accumulators_[i].average();
216 err = accumulators_[i].blockingError();
217 outputFile_ << " " << std::left << std::setw(nameWidth)
218 << names_[i] << " ";
219 outputFile_ << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
220 }
221 outputFile_.close();
222
223 // Write error analysis (*.aer) file
224 fileName = AnalyzerT::outputFileName(".aer");
225 system().fileMaster().openOutputFile(fileName, outputFile_);
226 std::string line;
227 line =
228 "------------------------------------------------------------------";
229 for (int i = 0; i < nValue_; ++i) {
230 outputFile_ << line << std::endl;
231 outputFile_ << names_[i] << " :" << std::endl;
232 accumulators_[i].output(outputFile_);
233 outputFile_ << std::endl;
234 }
235 outputFile_.close();
236
237 #if 0
238 // Write data format file (*.dfm) file
239 fileName = AnalyzerT::outputFileName();
240 fileName += ".dfm";
241 system().fileMaster().openOutputFile(fileName, outputFile_);
242 outputFile_ << "Value = " << nValue() << std::endl;
243 outputFile_ << "iStep ";
244 for (int i = 0; i < nValue_; ++i) {
245 outputFile_ << names_[i] << " ";
246 }
247 outputFile_ << std::endl;
248 outputFile_.close();
249 #endif
250
251 }
252
253}
254}
255#endif
const std::string & name(int i) const
Get name associated with a variable.
void setup() override
Setup before loop.
void sample(long iStep) override
Compute sampled values and update the accumulators.
double value(int i) const
Get current value of a specific variable.
void initializeAccumulators(int nValue)
Initialize Average accumulators and set nValue.
void output() override
Write final results to file after a simulation.
std::ofstream outputFile_
Output file stream.
void clearAccumulators()
Clear internal state of all accumulators.
void setName(int i, std::string name)
Set name of variable.
int nValue() const
Get the number of variables.
AverageListAnalyzer(typename T::Simulator &simulator, typename T::System &system)
Constructor.
int nSamplePerOutput() const
Get value of nSamplePerOutput.
void readParameters(std::istream &in) override
Read interval, outputFileName and (optionally) nSamplePerOutput.
Wrapper for a double precision number, for formatted ostream output.
Definition Dbl.h:40
Wrapper for an int, for formatted ostream output.
Definition Int.h:37
virtual void writeParam(std::ostream &out) const
Write all parameters to an output stream.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
Class templates for real-valued periodic fields.
PSCF package top-level namespace.