1#ifndef PRDC_SCFT_REAL_TPP
2#define PRDC_SCFT_REAL_TPP
13#include <pscf/mesh/Mesh.h>
14#include <pscf/chem/PolymerSpecies.h>
15#include <pscf/chem/SolventSpecies.h>
16#include <util/format/Int.h>
17#include <util/format/Dbl.h>
29 template <
int D,
class ST>
43 template <
int D,
class ST>
50 template <
int D,
class ST>
74 for (
int i = 0; i < np; ++i) {
75 polymerPtr = &
mixture().polymerSpecies(i);
76 phi = polymerPtr->
phi();
77 mu = polymerPtr->
mu();
79 length = polymerPtr->
length();
81 length = (double) polymerPtr->
nBead();
84 fIdeal_ += phi*( mu - 1.0 ) / length;
94 for (
int i = 0; i < ns; ++i) {
95 solventPtr = &
mixture().solventSpecies(i);
96 phi = solventPtr->
phi();
97 mu = solventPtr->
mu();
98 size = solventPtr->
size();
100 fIdeal_ += phi*( mu - 1.0 )/size;
115 const double phiTot =
mask().phiTot();
119 if (
w().isSymmetric()) {
123 const int nBasis =
domain().basis().nBasis();
124 for (
int i = 0; i < nm; ++i) {
125 for (
int k = 0; k < nBasis; ++k) {
126 temp -=
w().basis(i)[k] *
c().basis(i)[k];
131 const int meshSize =
domain().mesh().size();
132 for (
int i = 0; i < nm; ++i) {
135 for (
int k = 0; k < meshSize; ++k) {
136 temp -=
w().rgrid(i)[k] *
c().rgrid(i)[k];
140 temp /= double(meshSize);
144 fHelmholtz_ += fIdeal_;
148 if (
w().isSymmetric() &&
h().isSymmetric()) {
152 const int nBasis =
domain().basis().nBasis();
153 for (
int i = 0; i < nm; ++i) {
154 for (
int k = 0; k < nBasis; ++k) {
155 fExt_ +=
h().basis(i)[k] *
c().basis(i)[k];
160 const int meshSize =
domain().mesh().size();
161 for (
int i = 0; i < nm; ++i) {
164 for (
int k = 0; k < meshSize; ++k) {
165 fExt_ +=
h().rgrid(i)[k] *
c().rgrid(i)[k];
169 fExt_ /= double(meshSize);
172 fHelmholtz_ += fExt_;
176 if (
w().isSymmetric()) {
179 const int nBasis =
domain().basis().nBasis();
181 for (
int i = 0; i < nm; ++i) {
182 for (
int j = i; j < nm; ++j) {
184 if (std::abs(chi) > 1.0E-9) {
186 for (
int k = 0; k < nBasis; ++k) {
187 temp +=
c().basis(i)[k] *
c().basis(j)[k];
190 fInter_ += 0.5*chi*temp;
199 const int meshSize =
domain().mesh().size();
201 for (
int i = 0; i < nm; ++i) {
202 for (
int j = i; j < nm; ++j) {
204 if (std::abs(chi) > 1.0E-9) {
208 for (
int k = 0; k < meshSize; ++k) {
209 temp +=
c().rgrid(i)[k] *
c().rgrid(j)[k];
213 fInter_ += 0.5*chi*temp;
220 fInter_ /= double(meshSize);
223 fHelmholtz_ += fInter_;
226 pressure_ = -fHelmholtz_;
232 for (
int i = 0; i < np; ++i) {
233 polymerPtr = &
mixture().polymerSpecies(i);
234 phi = polymerPtr->
phi();
235 mu = polymerPtr->
mu();
237 length = polymerPtr->
length();
239 length = (double) polymerPtr->
nBead();
242 pressure_ += mu * phi / length;
251 for (
int i = 0; i < ns; ++i) {
252 solventPtr = &
mixture().solventSpecies(i);
253 phi = solventPtr->
phi();
254 mu = solventPtr->
mu();
255 size = solventPtr->
size();
257 pressure_ += mu * phi / size;
268 template <
int D,
class ST>
270 { hasData_ =
false; }
275 template <
int D,
class ST>
283 out <<
"fHelmholtz " <<
Dbl(
fHelmholtz(), 18, 11) << std::endl;
284 out <<
"pressure " <<
Dbl(
pressure(), 18, 11) << std::endl;
286 out <<
"fIdeal " <<
Dbl(fIdeal_, 18, 11) << std::endl;
287 out <<
"fInter " <<
Dbl(fInter_, 18, 11) << std::endl;
289 out <<
"fExt " <<
Dbl(fExt_, 18, 11) << std::endl;
297 out <<
"polymers:" << std::endl;
302 for (
int i = 0; i < np; ++i) {
304 <<
" " <<
Dbl(
mixture().polymer(i).phi(),18, 11)
305 <<
" " <<
Dbl(
mixture().polymer(i).mu(), 18, 11)
312 out <<
"solvents:" << std::endl;
317 for (
int i = 0; i < ns; ++i) {
319 <<
" " <<
Dbl(
mixture().solvent(i).phi(),18, 11)
320 <<
" " <<
Dbl(
mixture().solvent(i).mu(), 18, 11)
326 out <<
"cellParams:" << std::endl;
327 for (
int i = 0; i <
domain().unitCell().nParameter(); ++i) {
330 <<
Dbl(
domain().unitCell().parameter(i), 18, 11)
Descriptor for a linear or acyclic branched block polymer.
int nBead() const
Total number of beads in the polymer (bead model).
double length() const
Sum of the lengths of all blocks in the polymer (thread model).
virtual ~ScftReal()
Destructor.
typename Base::SystemT SystemT
Parent System type name alias.
DomainT const & domain() const
Get the Domain.
virtual double innerProduct(FieldT const &A, FieldT const &B) const
Inner product of two fields.
double fHelmholtz() const
Get total Helmholtz free energy per monomer / kT.
SystemT const & system() const
Get the associated System.
void clear()
Clear all thermodynamic data.
bool hasData() const
Have free energies and pressure been computed?
MaskT const & mask() const
Get the mask.
ScftReal(SystemT const &system)
Constructor.
void write(std::ostream &out)
Write SCFT thermodynamic properties to a file.
WFieldContainerT const & w() const
Get the chemical potential (w) field container.
MixtureT const & mixture() const
Get the Mixture.
WFieldContainerT const & h() const
Get the external potential (h) field container.
double pressure() const
Get the precomputed pressure times monomer volume / kT.
CFieldContainerT const & c() const
Get the concentration (c) field container.
InteractionT const & interaction() const
Get the Interaction.
void compute()
Compute SCFT free energy density and pressure for current fields.
SystemConstRefReal()
Default constructor.
Descriptor for a solvent species.
double size() const
Get the size (number of monomers) in this solvent.
double phi() const
Get the overall volume fraction for this species.
double mu() const
Get the chemical potential for this species (units kT=1).
Wrapper for a double precision number, for formatted ostream output.
Wrapper for an int, for formatted ostream output.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
bool isThread()
Is the thread model in use ?
Fields and FFTs for periodic boundary conditions (CPU)
Periodic fields and crystallography.
PSCF package top-level namespace.