PSCF v1.1
HomogeneousComparison.cpp
1/*
2* PSCF - Polymer Self-Consistent Field Theory
3*
4* Copyright 2016 - 2022, 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 <pscf/inter/Interaction.h>
11#include <pscf/homogeneous/Clump.h>
12
13#include <util/format/Str.h>
14#include <util/format/Int.h>
15#include <util/format/Dbl.h>
16
17#include <string>
18
19namespace Pscf {
20namespace Fd1d
21{
22
23 using namespace Util;
24
25 /*
26 * Default constructor.
27 */
29 : SystemAccess()
30 {}
31
32 /*
33 * Constructor.
34 */
36 : SystemAccess(system)
37 {}
38
39 /*
40 * Destructor.
41 */
43 {}
44
45 /*
46 * Compute properties of a homogeneous reference system.
47 *
48 * mode == 0 : Composition equals spatial average composition
49 * mode == 1: Chemical potential equal to that of system,
50 * composition guess given at last grid point.
51 * mode == 2: Chemical potential equal to that of system,
52 * composition guess given at first grid point.
53 */
55 {
56 int np = mixture().nPolymer();
57 int ns = mixture().nSolvent();
58 if (!p_.isAllocated()) {
59 p_.allocate(np+ns);
60 }
61 UTIL_CHECK(p_.capacity() == homogeneous().nMolecule());
62
63 if (mode == 0) {
64
65 for (int i = 0; i < np; ++i) {
66 p_[i] = mixture().polymer(i).phi();
67 }
69 double xi = 0.0;
71
72 } else
73 if (mode == 1 || mode == 2) {
74
75 if (!m_.isAllocated()) {
76 m_.allocate(np+ns);
77 }
78 UTIL_CHECK(m_.capacity() == homogeneous().nMolecule());
79 for (int i = 0; i < np; ++i) {
80 m_[i] = mixture().polymer(i).mu();
81 }
82 int ix; // Grid index from which we obtain guess of composition
83 if (mode == 1) {
84 ix = domain().nx() - 1;
85 } else
86 if (mode == 2) {
87 ix = 0;
88 }
89
90 // Compute array p_
91 // Define: p_[i] = volume fraction of all blocks of polymer i
92 for (int i = 0; i < np; ++i) {
93 p_[i] = 0.0;
94 int nb = mixture().polymer(i).nBlock();
95 for (int j = 0; j < nb; ++j) {
96 p_[i] += mixture().polymer(i).block(j).cField()[ix];
97 }
98 }
99
100 double xi = 0.0;
101 homogeneous().computePhi(interaction(), m_, p_, xi);
102
103 } else {
104 UTIL_THROW("Unknown mode in computeHomogeneous");
105 }
106
107 // Compute Helmholtz free energy and pressure
109 }
110
111 /*
112 * Output properties of homogeneous system and free energy difference.
113 *
114 * Mode 0: Outputs fHomo (Helmholtz) and difference df
115 * Mode 1 or 2: Outputs Helhmoltz, pressure and difference dp
116 */
117 void HomogeneousComparison::output(int mode, std::ostream& out)
118 {
119 if (mode == 0) {
120
121 // Output free energies
122 double fHomo = homogeneous().fHelmholtz();
123 double df = system().fHelmholtz() - fHomo;
124 out << std::endl;
125 out << "f (homo) = " << Dbl(fHomo, 18, 11)
126 << " [per monomer volume]" << std::endl;
127 out << "delta f = " << Dbl(df, 18, 11)
128 << " [per monomer volume]" << std::endl;
129
130 // Output species-specific properties
131 out << std::endl;
132 out << "Species:" << std::endl;
133 out << " i"
134 << " mu(homo) "
135 << " phi(homo) "
136 << std::endl;
137 for (int i = 0; i < homogeneous().nMolecule(); ++i) {
138 out << Int(i,5)
139 << " " << Dbl(homogeneous().mu(i), 18, 11)
140 << " " << Dbl(homogeneous().phi(i), 18, 11)
141 << std::endl;
142 }
143 out << std::endl;
144
145 } else
146 if (mode == 1 || mode == 2) {
147
148 // Output free energies
149 double fHomo = homogeneous().fHelmholtz();
150 double pHomo = homogeneous().pressure();
151 double pEx = system().pressure() - pHomo;
152 double fEx = system().fHelmholtz() - fHomo;
153 double V = domain().volume()/mixture().vMonomer();
154 double PhiExTot = -1.0*pEx*V;
155 double fExTot = fEx*V;
156 out << std::endl;
157 out << "f (homo) = " << Dbl(fHomo, 18, 11)
158 << " [per monomer volume]" << std::endl;
159 out << "p (homo) = " << Dbl(pHomo, 18, 11)
160 << " [per monomer volume]" << std::endl;
161 out << "delta f = " << Dbl(fEx, 18, 11)
162 << " [per monomer volume]" << std::endl;
163 out << "delta p = " << Dbl(pEx, 18, 11)
164 << " [per monomer volume]" << std::endl;
165 out << "Phi (ex) = " << Dbl(PhiExTot, 18, 11)
166 << " [total]" << std::endl;
167 out << "F (ex) = " << Dbl(fExTot, 18, 11)
168 << " [total]" << std::endl;
169 out << "V(tot)/v = " << Dbl(V, 18, 11) << std::endl;
170
171 // Output species specific properties
172 double dV;
173 out << std::endl;
174 out << "Species:" << std::endl;
175 out << " i"
176 << " mu "
177 << " phi(homo) "
178 << " delta V "
179 << std::endl;
180 for (int i = 0; i < homogeneous().nMolecule(); ++i) {
181 dV = mixture().polymer(i).phi() - homogeneous().phi(i);
182 dV *= V;
183 out << Int(i,5)
184 << " " << Dbl(homogeneous().mu(i), 18, 11)
185 << " " << Dbl(homogeneous().phi(i), 18, 11)
186 << " " << Dbl(dV, 18, 11)
187 << std::endl;
188 }
189 out << std::endl;
190
191 }
192
193 }
194
195} // namespace Fd1d
196} // namespace Pscf
int nx() const
Get number of spatial grid points, including both endpoints.
double volume() const
Get generalized volume of domain.
void compute(int mode)
Compute properties of a homogeneous reference system.
void output(int mode, std::ostream &out)
Output comparison to a homogeneous reference system.
Concise accesss to an associated System.
Definition: SystemAccess.h:28
const Interaction & interaction() const
Get interaction (i.e., excess free energy model) by reference.
Definition: SystemAccess.h:212
const Domain & domain() const
Get spatial domain (including grid info) by reference.
Definition: SystemAccess.h:194
const System & system() const
Get parent System by reference.
Definition: SystemAccess.h:158
const Mixture & mixture() const
Get Mixture by reference.
Definition: SystemAccess.h:176
const Homogeneous::Mixture & homogeneous() const
Get homogeneous mixture (for reference calculations).
Main class in SCFT simulation of one system.
Definition: fd1d/System.h:63
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
Definition: fd1d/System.h:622
double pressure() const
Get precomputed pressure x monomer volume kT.
Definition: fd1d/System.h:628
double pressure() const
Return pressure in units of kT / monomer volume.
double phi(int id) const
Return molecular volume fraction for one species.
void setComposition(DArray< double > const &phi)
Set system composition.
void computePhi(Interaction const &interaction, DArray< double > const &mu, DArray< double > const &phi, double &xi)
Compute composition from chemical potentials.
void computeFreeEnergy(Interaction const &interaction)
Compute Helmholtz free energy and pressure.
int nMolecule() const
Get number of molecule species (polymer + solvent).
void computeMu(Interaction const &interaction, double xi=0.0)
Compute chemical potential from preset composition.
double fHelmholtz() const
Return Helmholtz free energy per monomer / kT.
Polymer & polymer(int id)
Get a polymer object.
Definition: MixtureTmpl.h:220
int nSolvent() const
Get number of solvent (point particle) species.
Definition: MixtureTmpl.h:198
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
Definition: MixtureTmpl.h:248
int nPolymer() const
Get number of polymer species.
Definition: MixtureTmpl.h:194
int capacity() const
Return allocated size.
Definition: Array.h:159
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:199
bool isAllocated() const
Return true if this DArray has been allocated, false otherwise.
Definition: DArray.h:247
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:51
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1