PSCF v1.3.3
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/Block.h>
11#include <r1d/solvers/Polymer.h>
12#include <r1d/solvers/Solvent.h>
13#include <pscf/inter/Interaction.h>
14#include <pscf/floryHuggins/Clump.h>
15
16#include <util/format/Str.h>
17#include <util/format/Int.h>
18#include <util/format/Dbl.h>
19
20#include <string>
21
22namespace Pscf {
23namespace R1d
24{
25
26 using namespace Util;
27
28 /*
29 * Default constructor.
30 */
34
35 /*
36 * Constructor.
37 */
41
42 /*
43 * Destructor.
44 */
47
48 /*
49 * Compute properties of a homogeneous reference system.
50 *
51 * mode == 0 : Composition equals spatial average composition
52 * mode == 1: Chemical potential equal to that of system,
53 * composition guess given at last grid point.
54 * mode == 2: Chemical potential equal to that of system,
55 * composition guess given at first grid point.
56 */
58 {
59 int np = mixture().nPolymer();
60 int ns = mixture().nSolvent();
61 if (!p_.isAllocated()) {
62 p_.allocate(np+ns);
63 }
64 UTIL_CHECK(p_.capacity() == homogeneous().nMolecule());
65
66 if (mode == 0) {
67
68 for (int i = 0; i < np; ++i) {
69 p_[i] = mixture().polymer(i).phi();
70 }
72 double xi = 0.0;
74
75 } else
76 if (mode == 1 || mode == 2) {
77
78 if (!m_.isAllocated()) {
79 m_.allocate(np+ns);
80 }
81 UTIL_CHECK(m_.capacity() == homogeneous().nMolecule());
82 for (int i = 0; i < np; ++i) {
83 m_[i] = mixture().polymer(i).mu();
84 }
85 int ix; // Grid index from which we obtain guess of composition
86 if (mode == 1) {
87 ix = domain().nx() - 1;
88 } else
89 if (mode == 2) {
90 ix = 0;
91 }
92
93 // Compute array p_
94 // Define: p_[i] = volume fraction of all blocks of polymer i
95 for (int i = 0; i < np; ++i) {
96 p_[i] = 0.0;
97 int nb = mixture().polymer(i).nBlock();
98 for (int j = 0; j < nb; ++j) {
99 p_[i] += mixture().polymer(i).block(j).cField()[ix];
100 }
101 }
102
103 double xi = 0.0;
104 homogeneous().computePhi(interaction(), m_, p_, xi);
105
106 } else {
107 UTIL_THROW("Unknown mode in computeHomogeneous");
108 }
109
110 // Compute Helmholtz free energy and pressure
112 }
113
114 /*
115 * Output properties of homogeneous system and free energy difference.
116 *
117 * Mode 0: Outputs fHomo (Helmholtz) and difference df
118 * Mode 1 or 2: Outputs Helhmoltz, pressure and difference dp
119 */
120 void HomogeneousComparison::output(int mode, std::ostream& out)
121 {
122 if (mode == 0) {
123
124 // Output free energies
125 double fHomo = homogeneous().fHelmholtz();
126 double df = system().fHelmholtz() - fHomo;
127 out << std::endl;
128 out << "f (homo) = " << Dbl(fHomo, 18, 11)
129 << " [per monomer volume]" << std::endl;
130 out << "delta f = " << Dbl(df, 18, 11)
131 << " [per monomer volume]" << std::endl;
132
133 // Output species-specific properties
134 out << std::endl;
135 out << "Species:" << std::endl;
136 out << " i"
137 << " mu(homo) "
138 << " phi(homo) "
139 << std::endl;
140 for (int i = 0; i < homogeneous().nMolecule(); ++i) {
141 out << Int(i,5)
142 << " " << Dbl(homogeneous().mu(i), 18, 11)
143 << " " << Dbl(homogeneous().phi(i), 18, 11)
144 << std::endl;
145 }
146 out << std::endl;
147
148 } else
149 if (mode == 1 || mode == 2) {
150
151 // Output free energies
152 double fHomo = homogeneous().fHelmholtz();
153 double pHomo = homogeneous().pressure();
154 double pEx = system().pressure() - pHomo;
155 double fEx = system().fHelmholtz() - fHomo;
156 double V = domain().volume()/mixture().vMonomer();
157 double PhiExTot = -1.0*pEx*V;
158 double fExTot = fEx*V;
159 out << std::endl;
160 out << "f (homo) = " << Dbl(fHomo, 18, 11)
161 << " [per monomer volume]" << std::endl;
162 out << "p (homo) = " << Dbl(pHomo, 18, 11)
163 << " [per monomer volume]" << std::endl;
164 out << "delta f = " << Dbl(fEx, 18, 11)
165 << " [per monomer volume]" << std::endl;
166 out << "delta p = " << Dbl(pEx, 18, 11)
167 << " [per monomer volume]" << std::endl;
168 out << "Phi (ex) = " << Dbl(PhiExTot, 18, 11)
169 << " [total]" << std::endl;
170 out << "F (ex) = " << Dbl(fExTot, 18, 11)
171 << " [total]" << std::endl;
172 out << "V(tot)/v = " << Dbl(V, 18, 11) << std::endl;
173
174 // Output species specific properties
175 double dV;
176 out << std::endl;
177 out << "Species:" << std::endl;
178 out << " i"
179 << " mu "
180 << " phi(homo) "
181 << " deltaV "
182 << std::endl;
183 for (int i = 0; i < homogeneous().nMolecule(); ++i) {
184 dV = mixture().polymer(i).phi() - homogeneous().phi(i);
185 dV *= V;
186 out << Int(i,5)
187 << " " << Dbl(homogeneous().mu(i), 18, 11)
188 << " " << Dbl(homogeneous().phi(i), 18, 11)
189 << " " << Dbl(dV, 18, 11)
190 << std::endl;
191 }
192 out << std::endl;
193
194 }
195
196 }
197
198} // namespace R1d
199} // namespace Pscf
double phi(int id) const
Return molecular volume fraction for one species.
void setComposition(DArray< double > const &phi)
Set system composition.
double fHelmholtz() const
Return Helmholtz free energy per monomer / kT.
void computeMu(Interaction const &interaction, double xi=0.0)
Compute chemical potential from preset composition.
int nMolecule() const
Get number of molecule species (polymer + solvent).
void computeFreeEnergy(Interaction const &interaction)
Compute Helmholtz free energy and pressure.
void computePhi(Interaction const &interaction, DArray< double > const &mu, DArray< double > const &phi, double &xi)
Compute composition from chemical potentials.
double pressure() const
Return pressure in units of kT / monomer volume.
int nPolymer() const
Get number of polymer species.
int nSolvent() const
Get number of solvent (point particle) species.
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
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)
Output comparison to a homogeneous reference system.
void compute(int mode)
Compute properties of a homogeneous reference system.
FloryHuggins::Mixture const & homogeneous() const
Get homogeneous mixture by const reference.
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.
Definition r1d/System.h:65
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
Definition r1d/System.h:674
double pressure() const
Get precomputed pressure x monomer volume kT.
Definition r1d/System.h:680
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.