PSCF v1.4.0
FhInteraction.cpp
1/*
2* PSCF - Polymer Self-Consistent Field
3*
4* Copyright 2015 - 2025, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include "FhInteraction.h"
9#include <pscf/interaction/Interaction.h>
10#include <pscf/math/LuSolver.h>
11
12namespace Pscf {
13
14 using namespace Util;
15
16 /*
17 * Constructor.
18 */
20 : nMonomer_(0)
21 { setClassName("FhInteraction"); }
22
23 /*
24 * Copy constructor.
25 */
27 : nMonomer_(0)
28 {
29 setClassName("FhInteraction");
30 if (other.nMonomer() > 0) {
31 setNMonomer(other.nMonomer());
32 setChi(other.chi());
33 }
34 }
35
36 /*
37 * Constructor, copy from from Pscf::Interaction
38 */
40 : nMonomer_(0)
41 {
42 UTIL_CHECK(other.nMonomer() > 0);
43 setClassName("FhInteraction");
44 setNMonomer(other.nMonomer());
45 setChi(other.chi());
46 }
47
48 /*
49 * Destructor.
50 */
53
54 /*
55 * Assignment from FhInteraction
56 */
59 {
60 if (this != &other) {
61 if (other.nMonomer() == 0) {
62 UTIL_CHECK(nMonomer_ == 0);
63 } else {
64 if (nMonomer_ == 0) {
65 setNMonomer(other.nMonomer());
66 }
67 UTIL_CHECK(nMonomer_ == other.nMonomer());
68 setChi(other.chi());
69 }
70 }
71 return *this;
72 }
73
74 /*
75 * Assignment from Interaction
76 */
78 {
79 UTIL_CHECK(other.nMonomer() > 0);
80 if (nMonomer_ == 0) {
81 setNMonomer(other.nMonomer());
82 }
83 UTIL_CHECK(nMonomer_ == other.nMonomer());
84 setChi(other.chi());
85 return *this;
86 }
87
88 /*
89 * Set the number of monomer types.
90 */
92 {
93 UTIL_CHECK(nMonomer_ == 0);
95 nMonomer_ = nMonomer;
96 chi_.allocate(nMonomer, nMonomer);
97 chiInverse_.allocate(nMonomer, nMonomer);
98 setChiZero();
99 }
100
101 /*
102 * Read chi matrix from file.
103 */
104 void FhInteraction::readParameters(std::istream& in)
105 {
106 UTIL_CHECK(nMonomer() > 0);
107 readDSymmMatrix(in, "chi", chi_, nMonomer());
108
109 // Compute relevant AM iterator quantities.
110 updateMembers();
111 }
112
113 void FhInteraction::updateMembers()
114 {
115 UTIL_CHECK(chi_.isAllocated());
116 UTIL_CHECK(chiInverse_.isAllocated());
117
118 if (nMonomer() == 2) {
119 double det = chi_(0,0)*chi_(1, 1) - chi_(0,1)*chi_(1,0);
120 double norm = chi_(0,0)*chi_(0, 0) + chi_(1,1)*chi_(1,1)
121 + 2.0*chi_(0,1)*chi_(1,0);
122 if (fabs(det/norm) < 1.0E-8) {
123 UTIL_THROW("Singular chi matrix");
124 }
125 chiInverse_(0,1) = -chi_(0,1)/det;
126 chiInverse_(1,0) = -chi_(1,0)/det;
127 chiInverse_(1,1) = chi_(0,0)/det;
128 chiInverse_(0,0) = chi_(1,1)/det;
129
130 } else {
131 LuSolver solver;
132 solver.allocate(nMonomer());
133 solver.computeLU(chi_);
134 solver.inverse(chiInverse_);
135 }
136
137 }
138
139 /*
140 * Set values for all chi parameters.
141 */
143 {
144 UTIL_CHECK(nMonomer_ > 0);
145 UTIL_CHECK(other.capacity1() == nMonomer_);
146 UTIL_CHECK(other.capacity2() == nMonomer_);
147 double value1, value2, diff;
148 int i, j;
149 for (i = 0; i < nMonomer_; ++i) {
150 chi_(i, i) = other(i, i);
151 }
152 if (nMonomer_ > 1) {
153 for (i = 0; i < nMonomer_; ++i) {
154 for (j = 0; j < i; ++j) {
155 value1 = other(i, j);
156 value2 = other(j, i);
157 diff = std::abs( value1 - value2 );
158 if (diff > 1.0E-10) {
159 Log::file() << "Diff = " << diff << "\n";
160 Log::file() << " i, j = " << i << " " << j << "\n";
161 Log::file() << "chi(i,j) = " << value1 << "\n";
162 Log::file() << "chi(j,i) = " << value2 << "\n";
163 UTIL_THROW("Error: Asymmetric chi matrix");
164 }
165 chi_(i, j) = value1;
166 chi_(j, i) = value1;
167 }
168 }
169 }
170 updateMembers();
171 }
172
173 /*
174 * Set a single chi parameter.
175 */
176 void FhInteraction::setChi(int i, int j, double chi)
177 {
178 UTIL_CHECK(nMonomer_ > 0);
179 UTIL_CHECK(i >= 0);
180 UTIL_CHECK(i < nMonomer_);
181 UTIL_CHECK(j >= 0);
182 UTIL_CHECK(j < nMonomer_);
183 chi_(i,j) = chi;
184 if (i != j) {
185 chi_(j,i) = chi;
186 }
187
188 // Compute relevant AM iterator quantities.
189 updateMembers();
190 }
191
192 /*
193 * Set all elements of the chi matrix to zero.
194 */
195 void FhInteraction::setChiZero()
196 {
197 UTIL_CHECK(nMonomer_ > 0);
198 int i, j;
199 for (i = 0; i < nMonomer_; i++) {
200 for (j = 0; j < nMonomer_; j++) {
201 chi_(i, j) = 0.0;
202 chiInverse_(i, j) = 0.0;
203 }
204 }
205 }
206
207 /*
208 * Compute and return excess Helmholtz free energy per monomer.
209 */
211 {
212 int i, j;
213 double sum = 0.0;
214 for (i = 0; i < nMonomer(); ++i) {
215 for (j = 0; j < nMonomer(); ++j) {
216 sum += chi_(i, j)* c[i]*c[j];
217 }
218 }
219 return 0.5*sum;
220 }
221
222 /*
223 * Compute chemical potential from monomer concentrations
224 */
225 void
227 Array<double>& w) const
228 {
229 int i, j;
230 for (i = 0; i < nMonomer(); ++i) {
231 w[i] = 0.0;
232 for (j = 0; j < nMonomer(); ++j) {
233 w[i] += chi_(i, j)* c[j];
234 }
235 }
236 }
237
238 /*
239 * Compute concentrations and xi from chemical potentials.
240 */
241 void
243 Array<double>& c, double& xi)
244 const
245 {
246 double sum1 = 0.0;
247 double sum2 = 0.0;
248 int i, j;
249 for (i = 0; i < nMonomer(); ++i) {
250 for (j = 0; j < nMonomer(); ++j) {
251 sum1 += chiInverse_(i, j)*w[j];
252 sum2 += chiInverse_(i, j);
253 }
254 }
255 xi = (sum1 - 1.0)/sum2;
256 for (i = 0; i < nMonomer(); ++i) {
257 c[i] = 0;
258 for (j = 0; j < nMonomer(); ++j) {
259 c[i] += chiInverse_(i, j)*( w[j] - xi );
260 }
261 }
262 }
263
264 /*
265 * Compute Langrange multiplier from chemical potentials.
266 */
267 void
269 const
270 {
271 double sum1 = 0.0;
272 double sum2 = 0.0;
273 int i, j;
274 for (i = 0; i < nMonomer(); ++i) {
275 for (j = 0; j < nMonomer(); ++j) {
276 sum1 += chiInverse_(i, j)*w[j];
277 sum2 += chiInverse_(i, j);
278 }
279 }
280 xi = (sum1 - 1.0)/sum2;
281 }
282
283 /*
284 * Return dWdC = chi matrix.
285 */
286 void
288 Matrix<double>& dWdC) const
289 {
290 int i, j;
291 for (i = 0; i < nMonomer(); ++i) {
292 for (j = 0; j < nMonomer(); ++j) {
293 dWdC(i, j) = chi_(i, j);
294 }
295 }
296 }
297
298} // namespace Pscf
Flory-Huggins interaction model.
void setNMonomer(int nMonomer)
Set the number of monomer types.
virtual void computeC(Array< double > const &w, Array< double > &c, double &xi) const
Compute concentration from chemical potential fields.
virtual void computeW(Array< double > const &c, Array< double > &w) const
Compute chemical potential from concentration.
virtual void computeXi(Array< double > const &w, double &xi) const
Compute Langrange multiplier xi from chemical potential fields.
FhInteraction & operator=(FhInteraction const &other)
Assignment.
virtual void readParameters(std::istream &in)
Read chi parameters.
int nMonomer() const
Get number of monomer types.
FhInteraction()
Constructor.
Matrix< double > const & chi() const
Return the chi matrix by const reference.
virtual void computeDwDc(Array< double > const &c, Matrix< double > &dWdC) const
Compute second derivatives of free energy.
virtual double fHelmholtz(Array< double > const &c) const
Compute excess Helmholtz free energy per monomer.
virtual ~FhInteraction()
Destructor.
void setChi(Matrix< double > const &chi)
Assign values for all elements of the chi matrix.
Interaction model for complex Langevin FTS.
Definition Interaction.h:24
DMatrix< double > const & chi() const
Return the chi matrix by const reference.
int nMonomer() const
Get number of monomer types.
Array container class template.
Definition Array.h:40
bool isAllocated() const
Return true if the DMatrix has been allocated, false otherwise.
Definition DMatrix.h:202
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
Two-dimensional array container template (abstract).
Definition Matrix.h:32
int capacity2() const
Get number of columns (range of the second array index).
Definition Matrix.h:143
int capacity1() const
Get number of rows (range of the first array index).
Definition Matrix.h:136
DSymmMatrixParam< Type > & readDSymmMatrix(std::istream &in, const char *label, DMatrix< Type > &matrix, int n)
Add and read a required symmetrix DMatrix.
void setClassName(const char *className)
Set class name string.
#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:49
PSCF package top-level namespace.