PSCF v1.4.0
HomogeneousComparison.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 "HomogeneousComparison.h"
9
10#include <r1d/solvers/Mixture.h>
11#include <r1d/solvers/Polymer.h>
12#include <r1d/solvers/Block.h>
13#include <r1d/solvers/Solvent.h>
14
15#include <pscf/interaction/Interaction.h>
16#include <pscf/floryHuggins/FhInteraction.h>
17#include <pscf/floryHuggins/FhMixture.h>
18
19#include <util/format/Str.h>
20#include <util/format/Int.h>
21#include <util/format/Dbl.h>
22
23#include <string>
24
25namespace Pscf {
26namespace R1d
27{
28
29 using namespace Util;
30
31 /*
32 * Default constructor.
33 */
35 : SystemAccess(),
36 fhMixturePtr_(nullptr),
37 fhInteractionPtr_(nullptr),
38 hasData_(false)
39 {}
40
41 /*
42 * Constructor.
43 */
46 {
47 fhMixturePtr_ = new FhMixture();
48 fhInteractionPtr_ = new FhInteraction();
49 }
50
51 /*
52 * Destructor.
53 */
55 {
56 if (fhMixturePtr_) {
57 delete fhMixturePtr_;
58 }
59 if (fhInteractionPtr_) {
60 delete fhInteractionPtr_;
61 }
62 }
63
64 /*
65 * Compute properties of a homogeneous reference system.
66 *
67 * mode == 0 : Composition equals spatial average composition
68 * mode == 1: Chemical potential equal to that of system,
69 * composition guess given at last grid point.
70 * mode == 2: Chemical potential equal to that of system,
71 * composition guess given at first grid point.
72 */
74 {
75
76 UTIL_CHECK(fhMixturePtr_);
77 UTIL_CHECK(fhInteractionPtr_);
78 fhMixture().initialize(mixture());
79 fhInteraction() = interaction();
80
81 int np = mixture().nPolymer();
82 int ns = mixture().nSolvent();
83 int nt = np + ns;
84 UTIL_CHECK(fhMixture().nMolecule() == nt);
85 if (!p_.isAllocated()) {
86 p_.allocate(nt);
87 }
88 UTIL_CHECK(p_.capacity() == nt);
89
90 if (mode == 0) {
91
92 for (int i = 0; i < np; ++i) {
93 p_[i] = mixture().polymer(i).phi();
94 }
95 fhMixture().setComposition(p_);
96 double xi = 0.0;
97 fhMixture().computeMu( fhInteraction(), xi );
98
99 } else
100 if (mode == 1 || mode == 2) {
101
102 if (!m_.isAllocated()) {
103 m_.allocate(np+ns);
104 }
105 UTIL_CHECK(m_.capacity() == fhMixture().nMolecule());
106 for (int i = 0; i < np; ++i) {
107 m_[i] = mixture().polymer(i).mu();
108 }
109 int ix; // Grid index from which we obtain guess of composition
110 if (mode == 1) {
111 ix = domain().nx() - 1;
112 } else
113 if (mode == 2) {
114 ix = 0;
115 }
116
117 // Compute array p_
118 // Define: p_[i] = volume fraction of all blocks of polymer i
119 for (int i = 0; i < np; ++i) {
120 p_[i] = 0.0;
121 int nb = mixture().polymer(i).nBlock();
122 for (int j = 0; j < nb; ++j) {
123 p_[i] += mixture().polymer(i).block(j).cField()[ix];
124 }
125 }
126
127 double xi = 0.0;
128 fhMixture().computePhi(fhInteraction(), m_, p_, xi);
129
130 } else {
131 UTIL_THROW("Unknown mode in computeHomogeneous");
132 }
133
134 // Compute Helmholtz free energy and pressure
135 fhMixture().computeFreeEnergy(fhInteraction());
136
137 hasData_ = true;
138 }
139
140 /*
141 * Output properties of homogeneous system and free energy difference.
142 *
143 * Mode 0: Outputs fHomo (Helmholtz) and difference df
144 * Mode 1 or 2: Outputs Helhmoltz, pressure and difference dp
145 */
146 void HomogeneousComparison::output(int mode, std::ostream& out) const
147 {
148 // Precondition
149 UTIL_CHECK(hasData_);
150
151 if (mode == 0) {
152
153 // Output free energies
154 double fHomo = fhMixture().fHelmholtz();
155 double df = system().fHelmholtz() - fHomo;
156 out << std::endl;
157 out << "f (homo) = " << Dbl(fHomo, 18, 11)
158 << " [per monomer volume]" << std::endl;
159 out << "delta f = " << Dbl(df, 18, 11)
160 << " [per monomer volume]" << std::endl;
161
162 // Output species-specific properties
163 out << std::endl;
164 out << "Species:" << std::endl;
165 out << " i"
166 << " mu(homo) "
167 << " phi(homo) "
168 << std::endl;
169 for (int i = 0; i < fhMixture().nMolecule(); ++i) {
170 out << Int(i,5)
171 << " " << Dbl(fhMixture().mu(i), 18, 11)
172 << " " << Dbl(fhMixture().phi(i), 18, 11)
173 << std::endl;
174 }
175 out << std::endl;
176
177 } else
178 if (mode == 1 || mode == 2) {
179
180 // Output free energies
181 double fHomo = fhMixture().fHelmholtz();
182 double pHomo = fhMixture().pressure();
183 double pEx = system().pressure() - pHomo;
184 double fEx = system().fHelmholtz() - fHomo;
185 double V = domain().volume()/mixture().vMonomer();
186 double PhiExTot = -1.0*pEx*V;
187 double fExTot = fEx*V;
188 out << std::endl;
189 out << "f (homo) = " << Dbl(fHomo, 18, 11)
190 << " [per monomer volume]" << std::endl;
191 out << "p (homo) = " << Dbl(pHomo, 18, 11)
192 << " [per monomer volume]" << std::endl;
193 out << "delta f = " << Dbl(fEx, 18, 11)
194 << " [per monomer volume]" << std::endl;
195 out << "delta p = " << Dbl(pEx, 18, 11)
196 << " [per monomer volume]" << std::endl;
197 out << "Phi (ex) = " << Dbl(PhiExTot, 18, 11)
198 << " [total]" << std::endl;
199 out << "F (ex) = " << Dbl(fExTot, 18, 11)
200 << " [total]" << std::endl;
201 out << "V(tot)/v = " << Dbl(V, 18, 11) << std::endl;
202
203 // Output species specific properties
204 double dV;
205 out << std::endl;
206 out << "Species:" << std::endl;
207 out << " i"
208 << " mu "
209 << " phi(homo) "
210 << " deltaV "
211 << std::endl;
212 for (int i = 0; i < fhMixture().nMolecule(); ++i) {
213 dV = mixture().polymer(i).phi() - fhMixture().phi(i);
214 dV *= V;
215 out << Int(i,5)
216 << " " << Dbl(fhMixture().mu(i), 18, 11)
217 << " " << Dbl(fhMixture().phi(i), 18, 11)
218 << " " << Dbl(dV, 18, 11)
219 << std::endl;
220 }
221 out << std::endl;
222
223 }
224
225 }
226
227} // namespace R1d
228} // namespace Pscf
Flory-Huggins interaction model.
A spatially homogeneous mixture.
Definition FhMixture.h:35
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
int nSolvent() const
Get number of solvent (point particle) species.
int nPolymer() const
Get number of polymer species.
PolymerT & polymer(int id)
Get a polymer solver object by non-const reference.
int nx() const
Get number of spatial grid points, including both endpoints.
double volume() const
Get generalized volume of domain.
void output(int mode, std::ostream &out) const
Output comparison to a homogeneous reference system.
void compute(int mode)
Compute properties of a homogeneous reference system.
SystemAccess()
Default constructor.
const Domain & domain() const
Get spatial domain (including grid info) by reference.
const Interaction & interaction() const
Get interaction (i.e., excess free energy model) by reference.
const System & system() const
Get parent System by reference.
const Mixture & mixture() const
Get Mixture by reference.
Main class in SCFT simulation of one system.
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
double pressure() const
Get precomputed pressure x monomer volume kT.
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
#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
SCFT with real 1D fields.
PSCF package top-level namespace.