1#ifndef PRDC_SCFT_THERMO_TMPL_TPP
2#define PRDC_SCFT_THERMO_TMPL_TPP
11#include "ScftThermoTmpl.h"
13#include <prdc/crystal/Basis.h>
14#include <prdc/crystal/UnitCell.h>
15#include <pscf/chem/PolymerSpecies.h>
16#include <pscf/chem/SolventSpecies.h>
17#include <pscf/mesh/Mesh.h>
18#include <util/format/Int.h>
19#include <util/format/Dbl.h>
31 template <
int D,
class ST>
45 template <
int D,
class ST>
52 template <
int D,
class ST>
76 for (
int i = 0; i < np; ++i) {
77 polymerPtr = &
mixture().polymerSpecies(i);
78 phi = polymerPtr->
phi();
79 mu = polymerPtr->
mu();
81 length = polymerPtr->
length();
83 length = (double) polymerPtr->
nBead();
86 fIdeal_ += phi*( mu - 1.0 ) / length;
96 for (
int i = 0; i < ns; ++i) {
97 solventPtr = &
mixture().solventSpecies(i);
98 phi = solventPtr->
phi();
99 mu = solventPtr->
mu();
100 size = solventPtr->
size();
102 fIdeal_ += phi*( mu - 1.0 )/size;
117 const double phiTot =
mask().phiTot();
121 if (
w().isSymmetric()) {
125 const int nBasis =
domain().basis().nBasis();
126 for (
int i = 0; i < nm; ++i) {
127 for (
int k = 0; k < nBasis; ++k) {
128 temp -=
w().basis(i)[k] *
c().basis(i)[k];
133 const int meshSize =
domain().mesh().size();
134 for (
int i = 0; i < nm; ++i) {
137 temp /= double(meshSize);
141 fHelmholtz_ += fIdeal_;
145 if (
w().isSymmetric() &&
h().isSymmetric()) {
149 const int nBasis =
domain().basis().nBasis();
150 for (
int i = 0; i < nm; ++i) {
151 for (
int k = 0; k < nBasis; ++k) {
152 fExt_ +=
h().basis(i)[k] *
c().basis(i)[k];
157 const int meshSize =
domain().mesh().size();
158 for (
int i = 0; i < nm; ++i) {
161 fExt_ /= double(meshSize);
164 fHelmholtz_ += fExt_;
168 if (
w().isSymmetric()) {
171 const int nBasis =
domain().basis().nBasis();
173 for (
int i = 0; i < nm; ++i) {
174 for (
int j = i; j < nm; ++j) {
176 if (std::abs(chi) > 1.0E-9) {
178 for (
int k = 0; k < nBasis; ++k) {
179 temp +=
c().basis(i)[k] *
c().basis(j)[k];
182 fInter_ += 0.5*chi*temp;
191 const int meshSize =
domain().mesh().size();
193 for (
int i = 0; i < nm; ++i) {
194 for (
int j = i; j < nm; ++j) {
196 if (std::abs(chi) > 1.0E-9) {
199 fInter_ += 0.5*chi*temp;
206 fInter_ /= double(meshSize);
209 fHelmholtz_ += fInter_;
212 pressure_ = -fHelmholtz_;
218 for (
int i = 0; i < np; ++i) {
219 polymerPtr = &
mixture().polymerSpecies(i);
220 phi = polymerPtr->
phi();
221 mu = polymerPtr->
mu();
223 length = polymerPtr->
length();
225 length = (double) polymerPtr->
nBead();
228 pressure_ += mu * phi / length;
237 for (
int i = 0; i < ns; ++i) {
238 solventPtr = &
mixture().solventSpecies(i);
239 phi = solventPtr->
phi();
240 mu = solventPtr->
mu();
241 size = solventPtr->
size();
243 pressure_ += mu * phi / size;
254 template <
int D,
class ST>
256 { hasData_ =
false; }
261 template <
int D,
class ST>
269 out <<
"fHelmholtz " <<
Dbl(
fHelmholtz(), 18, 11) << std::endl;
270 out <<
"pressure " <<
Dbl(
pressure(), 18, 11) << std::endl;
272 out <<
"fIdeal " <<
Dbl(fIdeal_, 18, 11) << std::endl;
273 out <<
"fInter " <<
Dbl(fInter_, 18, 11) << std::endl;
275 out <<
"fExt " <<
Dbl(fExt_, 18, 11) << std::endl;
283 out <<
"polymers:" << std::endl;
288 for (
int i = 0; i < np; ++i) {
290 <<
" " <<
Dbl(
mixture().polymer(i).phi(),18, 11)
291 <<
" " <<
Dbl(
mixture().polymer(i).mu(), 18, 11)
298 out <<
"solvents:" << std::endl;
303 for (
int i = 0; i < ns; ++i) {
305 <<
" " <<
Dbl(
mixture().solvent(i).phi(),18, 11)
306 <<
" " <<
Dbl(
mixture().solvent(i).mu(), 18, 11)
312 out <<
"cellParams:" << std::endl;
313 for (
int i = 0; i <
domain().unitCell().nParameter(); ++i) {
316 <<
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).
void write(std::ostream &out)
Write SCFT thermodynamic properties to a file.
MaskT const & mask() const
Get the mask.
double pressure() const
Get the precomputed pressure times monomer volume / kT.
WFieldsT const & w() const
Get the chemical potential (w) field container.
void compute()
Compute SCFT free energy density and pressure for current fields.
CFieldsT const & c() const
Get the concentration (c) field container.
virtual double innerProduct(RFieldT const &A, RFieldT const &B) const
Inner product of two fields.
typename Base::SystemT SystemT
Parent System type name alias.
SystemT const & system() const
Get the associated System.
void clear()
Clear all thermodynamic data.
virtual ~ScftThermoTmpl()
Destructor.
double fHelmholtz() const
Get total Helmholtz free energy per monomer / kT.
bool hasData() const
Have free energies and pressure been computed?
InteractionT const & interaction() const
Get the Interaction.
WFieldsT const & h() const
Get the external potential (h) field container.
MixtureT const & mixture() const
Get the Mixture.
ScftThermoTmpl(SystemT const &system)
Constructor.
DomainT const & domain() const
Get the Domain.
SystemConstRefTmpl()
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.