1#ifndef RP_SCFT_THERMO_TPP
2#define RP_SCFT_THERMO_TPP
11#include "ScftThermo.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>
30 template <
int D,
class T>
44 template <
int D,
class T>
51 template <
int D,
class T>
59 int nm = mixture().nMonomer();
60 int np = mixture().nPolymer();
61 int ns = mixture().nSolvent();
75 for (
int i = 0; i < np; ++i) {
76 polymerPtr = &mixture().polymerSpecies(i);
77 phi = polymerPtr->
phi();
78 mu = polymerPtr->
mu();
80 length = polymerPtr->
length();
82 length = (double) polymerPtr->
nBead();
85 fIdeal_ += phi*( mu - 1.0 ) / length;
95 for (
int i = 0; i < ns; ++i) {
96 solventPtr = &mixture().solventSpecies(i);
97 phi = solventPtr->
phi();
98 mu = solventPtr->
mu();
99 size = solventPtr->
size();
101 fIdeal_ += phi*( mu - 1.0 )/size;
116 const double phiTot = mask().phiTot();
120 if (w().isSymmetric()) {
124 const int nBasis = domain().basis().nBasis();
125 for (
int i = 0; i < nm; ++i) {
126 for (
int k = 0; k < nBasis; ++k) {
127 temp -= w().basis(i)[k] * c().basis(i)[k];
132 const int meshSize = domain().mesh().size();
133 for (
int i = 0; i < nm; ++i) {
136 temp /= double(meshSize);
140 fHelmholtz_ += fIdeal_;
144 if (w().isSymmetric() && h().isSymmetric()) {
148 const int nBasis = domain().basis().nBasis();
149 for (
int i = 0; i < nm; ++i) {
150 for (
int k = 0; k < nBasis; ++k) {
151 fExt_ += h().basis(i)[k] * c().basis(i)[k];
156 const int meshSize = domain().mesh().size();
157 for (
int i = 0; i < nm; ++i) {
160 fExt_ /= double(meshSize);
163 fHelmholtz_ += fExt_;
167 if (w().isSymmetric()) {
170 const int nBasis = domain().basis().nBasis();
172 for (
int i = 0; i < nm; ++i) {
173 for (
int j = i; j < nm; ++j) {
174 const double chi = interaction().chi(i,j);
175 if (std::abs(chi) > 1.0E-9) {
177 for (
int k = 0; k < nBasis; ++k) {
178 temp += c().basis(i)[k] * c().basis(j)[k];
181 fInter_ += 0.5*chi*temp;
190 const int meshSize = domain().mesh().size();
192 for (
int i = 0; i < nm; ++i) {
193 for (
int j = i; j < nm; ++j) {
194 const double chi = interaction().chi(i,j);
195 if (std::abs(chi) > 1.0E-9) {
198 fInter_ += 0.5*chi*temp;
205 fInter_ /= double(meshSize);
208 fHelmholtz_ += fInter_;
211 pressure_ = -fHelmholtz_;
217 for (
int i = 0; i < np; ++i) {
218 polymerPtr = &mixture().polymerSpecies(i);
219 phi = polymerPtr->phi();
220 mu = polymerPtr->mu();
222 length = polymerPtr->length();
224 length = (double) polymerPtr->nBead();
227 pressure_ += mu * phi / length;
236 for (
int i = 0; i < ns; ++i) {
237 solventPtr = &mixture().solventSpecies(i);
238 phi = solventPtr->phi();
239 mu = solventPtr->mu();
240 size = solventPtr->size();
242 pressure_ += mu * phi / size;
253 template <
int D,
class T>
255 { hasData_ =
false; }
260 template <
int D,
class T>
268 out <<
"fHelmholtz " <<
Dbl(
fHelmholtz(), 18, 11) << std::endl;
269 out <<
"pressure " <<
Dbl(
pressure(), 18, 11) << std::endl;
271 out <<
"fIdeal " <<
Dbl(fIdeal_, 18, 11) << std::endl;
272 out <<
"fInter " <<
Dbl(fInter_, 18, 11) << std::endl;
274 out <<
"fExt " <<
Dbl(fExt_, 18, 11) << std::endl;
278 int np = mixture().nPolymer();
279 int ns = mixture().nSolvent();
282 out <<
"polymers:" << std::endl;
287 for (
int i = 0; i < np; ++i) {
289 <<
" " <<
Dbl(mixture().polymer(i).phi(),18, 11)
290 <<
" " <<
Dbl(mixture().polymer(i).mu(), 18, 11)
297 out <<
"solvents:" << std::endl;
302 for (
int i = 0; i < ns; ++i) {
304 <<
" " <<
Dbl(mixture().solvent(i).phi(),18, 11)
305 <<
" " <<
Dbl(mixture().solvent(i).mu(), 18, 11)
311 out <<
"cellParams:" << std::endl;
312 for (
int i = 0; i < domain().unitCell().nParameter(); ++i) {
315 <<
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 clear()
Clear all thermodynamic data.
void write(std::ostream &out)
Write SCFT thermodynamic properties to a file.
void compute()
Compute SCFT free energy density and pressure for current fields.
typename T::System SystemT
Parent System type name alias.
double fHelmholtz() const
Get total Helmholtz free energy per monomer / kT.
typename T::SystemConstRef SystemConstRefT
Base class type name alias.
double pressure() const
Get the precomputed pressure times monomer volume / kT.
ScftThermo(SystemT const &system)
Constructor.
Descriptor for a solvent species.
double size() const
Get the size (number of monomers) in this solvent.
WT mu() const
Get the chemical potential for this species (units kT=1).
WT phi() const
Get the overall volume fraction for this species.
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.
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute Euclidean inner product of two real arrays .
bool isThread()
Is the thread model in use ?
Periodic fields and crystallography.
Class templates for real-valued periodic fields.
PSCF package top-level namespace.