10#include <fd1d/iterator/Iterator.h>
11#include <fd1d/iterator/IteratorFactory.h>
12#include <fd1d/sweep/Sweep.h>
13#include <fd1d/sweep/SweepFactory.h>
14#include <fd1d/iterator/NrIterator.h>
15#include <fd1d/misc/HomogeneousComparison.h>
16#include <fd1d/misc/FieldIo.h>
18#include <pscf/inter/Interaction.h>
19#include <pscf/inter/Interaction.h>
20#include <pscf/homogeneous/Clump.h>
22#include <util/format/Str.h>
23#include <util/format/Int.h>
24#include <util/format/Dbl.h>
25#include <util/param/BracketPolicy.h>
26#include <util/misc/ioUtil.h>
48 iteratorFactoryPtr_(0),
79 if (interactionPtr_) {
80 delete interactionPtr_;
85 if (iteratorFactoryPtr_) {
86 delete iteratorFactoryPtr_;
91 if (sweepFactoryPtr_) {
92 delete sweepFactoryPtr_;
114 while ((c = getopt(argc, argv,
"er:p:c:i:o:f")) != -1) {
136 Log::file() <<
"Unknown option -" << optopt << std::endl;
194 iteratorPtr_ = iteratorFactoryPtr_->
readObject(in, *
this,
197 std::string msg =
"Unrecognized Iterator subclass name ";
234 out <<
"System{" << std::endl;
239 out <<
"}" << std::endl;
245 void System::allocateFields()
256 wFields_.allocate(nMonomer);
257 cFields_.allocate(nMonomer);
259 for (
int i = 0; i < nMonomer; ++i) {
275 std::string filename;
277 std::istream& inBuffer = in;
279 bool readNext =
true;
284 if (inBuffer.eof()) {
290 if (command ==
"FINISH") {
294 if (command ==
"READ_W") {
295 readEcho(inBuffer, filename);
298 if (command ==
"COMPUTE") {
303 if (command ==
"ITERATE") {
305 bool isContinuation =
false;
306 int fail =
iterate(isContinuation);
311 if (command ==
"SWEEP") {
316 if (command ==
"WRITE_PARAM") {
317 readEcho(inBuffer, filename);
323 if (command ==
"WRITE_THERMO") {
324 readEcho(inBuffer, filename);
330 if (command ==
"COMPARE_HOMOGENEOUS") {
334 Log::file() <<
"mode = " << mode << std::endl;
340 if (command ==
"WRITE_W") {
341 readEcho(inBuffer, filename);
344 if (command ==
"WRITE_C") {
345 readEcho(inBuffer, filename);
348 if (command ==
"WRITE_BLOCK_C") {
349 readEcho(inBuffer, filename);
352 if (command ==
"WRITE_Q_SLICE") {
353 int polymerId, blockId, directionId, segmentId;
354 readEcho(inBuffer, filename);
355 inBuffer >> polymerId;
357 inBuffer >> directionId;
358 inBuffer >> segmentId;
359 Log::file() <<
Str(
"polymer ID ", 21) << polymerId <<
"\n"
360 <<
Str(
"block ID ", 21) << blockId <<
"\n"
361 <<
Str(
"direction ID ", 21) << directionId <<
"\n"
362 <<
Str(
"segment ID ", 21) << segmentId << std::endl;
363 writeQSlice(filename, polymerId, blockId, directionId,
366 if (command ==
"WRITE_Q_TAIL") {
367 readEcho(inBuffer, filename);
368 int polymerId, blockId, directionId;
369 inBuffer >> polymerId;
371 inBuffer >> directionId;
372 Log::file() <<
Str(
"polymer ID ", 21) << polymerId <<
"\n"
373 <<
Str(
"block ID ", 21) << blockId <<
"\n"
374 <<
Str(
"direction ID ", 21) << directionId <<
"\n";
375 writeQTail(filename, polymerId, blockId, directionId);
377 if (command ==
"WRITE_Q_VERTEX") {
378 int polymerId, vertexId;
379 inBuffer >> polymerId;
382 <<
Int(polymerId, 5) << std::endl;
383 inBuffer >> vertexId;
385 <<
Int(vertexId, 5) << std::endl;
386 inBuffer >> filename;
388 <<
Str(filename, 20) << std::endl;
389 fieldIo_.
writeVertexQ(mixture_, polymerId, vertexId, filename);
391 if (command ==
"WRITE_Q") {
392 readEcho(inBuffer, filename);
393 int polymerId, blockId, directionId;
394 inBuffer >> polymerId;
396 inBuffer >> directionId;
397 Log::file() <<
Str(
"polymer ID ", 21) << polymerId <<
"\n"
398 <<
Str(
"block ID ", 21) << blockId <<
"\n"
399 <<
Str(
"direction ID ", 21) << directionId <<
"\n";
400 writeQ(filename, polymerId, blockId, directionId);
402 if (command ==
"WRITE_Q_ALL") {
403 readEcho(inBuffer, filename);
406 if (command ==
"REMESH_W") {
411 inBuffer >> filename;
412 Log::file() <<
"outfile = " <<
Str(filename, 20) << std::endl;
415 if (command ==
"EXTEND_W") {
420 inBuffer >> filename;
421 Log::file() <<
"outfile = " <<
Str(filename, 20) << std::endl;
424 Log::file() <<
" Error: Unknown command "
425 << command << std::endl;
446 void System::readEcho(std::istream& in, std::string&
string)
const
520 for (
int i = 0; i < np; ++i) {
522 phi = polymerPtr->
phi();
523 mu = polymerPtr->
mu();
525 length = polymerPtr->
length();
527 fHelmholtz_ += phi*( mu - 1.0 )/length;
536 for (
int i = 0; i < ns; ++i) {
538 phi = solventPtr->
phi();
539 mu = solventPtr->
mu();
541 size = solventPtr->
size();
543 fHelmholtz_ += phi*( mu - 1.0 )/size;
549 for (
int i = 0; i < nm; ++i) {
553 fIdeal_ = fHelmholtz_;
560 for (
int i = 0; i < nx; ++i) {
562 for (j = 0; j < nm; ++j) {
563 c_[j] = cFields_[j][i];
569 fInter_ = fHelmholtz_ - fIdeal_;
572 pressure_ = -fHelmholtz_;
576 for (
int i = 0; i < np; ++i) {
578 phi = polymerPtr->
phi();
579 mu = polymerPtr->
mu();
580 length = polymerPtr->
length();
582 pressure_ += phi*mu/length;
589 for (
int i = 0; i < ns; ++i) {
591 phi = solventPtr->
phi();
592 mu = solventPtr->
mu();
593 size = solventPtr->
size();
595 pressure_ += phi*mu/size;
602 void System::initHomogeneous()
627 for (i = 0; i < np; ++i) {
630 for (j = 0; j < nm; ++j) {
636 for (k = 0; k < nb; ++k) {
638 j = block.monomerId();
639 c_[j] += block.length();
644 for (j = 0; j < nm; ++j) {
645 if (c_[j] > 1.0E-8) {
653 for (j = 0; j < nm; ++j) {
654 if (c_[j] > 1.0E-8) {
669 for (
int is = 0; is < ns; ++is) {
685 out <<
"fHelmholtz " <<
Dbl(
fHelmholtz(), 18, 11) << std::endl;
686 out <<
"pressure " <<
Dbl(
pressure(), 18, 11) << std::endl;
688 out <<
"fIdeal " <<
Dbl(fIdeal_, 18, 11) << std::endl;
689 out <<
"fInter " <<
Dbl(fInter_, 18, 11) << std::endl;
695 out <<
"polymers:" << std::endl;
700 for (
int i = 0; i < np; ++i) {
702 <<
" " <<
Dbl(
mixture().polymer(i).phi(),18, 11)
703 <<
" " <<
Dbl(
mixture().polymer(i).mu(), 18, 11)
712 out <<
"solvents:" << std::endl;
717 for (
int i = 0; i < ns; ++i) {
719 <<
" " <<
Dbl(
mixture().solvent(i).phi(),18, 11)
720 <<
" " <<
Dbl(
mixture().solvent(i).mu(), 18, 11)
762 int polymerId,
int blockId,
763 int directionId,
int segmentId)
774 propagator = polymer.
propagator(blockId, directionId);
775 Field const& field = propagator.
q(segmentId);
783 int polymerId,
int blockId,
int directionId)
794 field = polymer.
propagator(blockId, directionId).tail();
802 int polymerId,
int blockId,
int directionId)
814 int nslice = propagator.
ns();
821 file <<
"ngrid" << std::endl
822 <<
" " << domain_.
nx() << std::endl
823 <<
"nslice" << std::endl
824 <<
" " << nslice << std::endl;
827 bool hasHeader =
false;
828 for (
int i = 0; i < nslice; ++i) {
829 file <<
"slice " << i << std::endl;
830 Field const& field = propagator.
q(i);
841 std::string filename;
842 int np, nb, ip, ib, id;
844 for (ip = 0; ip < np; ++ip) {
845 nb = mixture_.
polymer(ip).nBlock();
846 for (ib = 0; ib < nb; ++ib) {
847 for (
id = 0;
id < 2; ++id) {
856 writeQ(filename, ip, ib,
id);
double spatialAverage(Field const &f) const
Compute spatial average of a field.
int nx() const
Get number of spatial grid points, including both endpoints.
double innerProduct(Field const &f, Field const &g) const
Compute inner product of two real fields.
void writeField(Field const &field, std::ostream &out, bool writeHeader=true) const
Write a single field to an output stream.
void writeVertexQ(Mixture const &mixture, int polymerId, int vertexId, std::ostream &out)
Write product of incoming q fields for one vertex to stream.
void remesh(DArray< Field > const &fields, int nx, std::ostream &out)
Interpolate an array of fields onto a new mesh and write to stream.
void associate(Domain const &domain, FileMaster const &fileMaster)
Get and store addresses of associated objects.
void writeFields(DArray< Field > const &fields, std::ostream &out, bool writeHeader=true)
Write a set of fields, one per monomer type, to an output stream.
void extend(DArray< Field > const &fields, int m, std::ostream &out)
Add points to the end of a field mesh and write to stream.
void writeBlockCFields(Mixture const &mixture, std::ostream &out)
Write block concentration fields for all blocks to an output stream.
void readFields(DArray< Field > &fields, std::istream &in)
Read a set of fields, one per monomer type.
Command to compute properties of homogeneous reference system.
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.
Factory for subclasses of Iterator.
virtual int solve(bool isContinuation=false)=0
Iterate to solution.
void setDomain(Domain const &domain)
Create an association with the domain and allocate memory.
void compute(DArray< WField > const &wFields, DArray< CField > &cFields)
Compute concentrations.
Descriptor and solver for a branched polymer species.
MDE solver for one-direction of one block.
int ns() const
Number of values of s (or slices), including head and tail.
QField const & q(int i) const
Return q-field at specified step.
Solver and descriptor for a solvent species.
Default Factory for subclasses of Sweep.
virtual void setSystem(System &system)
Set the system after construction.
void writeThermo(std::ostream &out)
Write thermodynamic properties to a file.
WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
Iterator & iterator()
Get the Iterator by reference.
int iterate(bool isContinuation=false)
Iteratively solve a SCFT problem.
void computeFreeEnergy()
Compute free energy density and pressure for current fields.
DArray< WField > & wFields()
Get array of all chemical potential fields.
void compute()
Solve the modified diffusion equation once, without iteration.
void writeQSlice(std::string const &filename, int polymerId, int blockId, int directionId, int segmentId) const
Write slice of a propagator at fixed s in r-grid format.
void readCommands()
Read commands from default command file.
Domain & domain()
Get spatial domain (including grid info) by reference.
virtual void readParameters(std::istream &in)
Read input parameters (without opening and closing lines).
void sweep()
Sweep in parameter space, solving an SCF problem at each point.
Mixture & mixture()
Get Mixture by reference.
DArray< CField > & cFields()
Get array of all chemical potential fields.
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
void setOptions(int argc, char **argv)
Process command line options.
void writeBlockC(std::string const &filename)
Write c-fields for all blocks and solvents in r-grid format.
void writeQAll(std::string const &basename)
Write all propagators of all blocks, each to a separate file.
void readParam()
Read input parameters from default param file.
void writeC(std::string const &filename)
Write concentration fields in symmetrized basis format.
void writeParamNoSweep(std::ostream &out) const
Write parameter file to an ostream, omitting any Sweep block.
double pressure() const
Get precomputed pressure x monomer volume kT.
Interaction & interaction()
Get interaction (i.e., excess free energy) by reference.
void writeQ(std::string const &filename, int polymerId, int blockId, int directionId) const
Write one propagator for one block, in r-grid format.
void writeW(std::string const &filename)
Write chemical potential fields in symmetrized basis format.
void writeQTail(std::string const &filename, int polymerId, int blockId, int directionId) const
Write the final slice of a propagator in r-grid format.
CField & cField(int monomerId)
Get chemical potential field for a specific monomer type.
FileMaster & fileMaster()
Get FileMaster by reference.
void setSize(double size)
Set the size of this block.
void setMonomerId(int monomerId)
Set the monomer id.
Molecule & molecule(int id)
Get a molecule object (non-const reference).
int nMonomer() const
Get number of monomer types.
int nMolecule() const
Get number of molecule species (polymer + solvent).
void setNMonomer(int nMonomer)
Set the number of monomer types.
void setNMolecule(int nMolecule)
Set the number of molecular species and allocate memory.
Clump & clump(int id)
Get a specified Clump.
void setNClump(int nClump)
Set the number of clumps, and allocate memory.
void computeSize()
Compute total molecule size by adding clump sizes.
Flory-Huggins excess free energy model.
virtual double fHelmholtz(Array< double > const &c) const
Compute excess Helmholtz free energy per monomer.
void setNMonomer(int nMonomer)
Set the number of monomer types.
Polymer & polymer(int id)
Get a polymer object.
int nSolvent() const
Get number of solvent (point particle) species.
int nMonomer() const
Get number of monomer types.
Solvent & solvent(int id)
Set a solvent solver object.
int nPolymer() const
Get number of polymer species.
int nBlock() const
Number of blocks.
Propagator & propagator(int blockId, int directionId)
Get propagator for a specific block and direction.
double length() const
Sum of the lengths of all blocks in the polymer.
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).
virtual void sweep()
Iterate to solution.
int capacity() const
Return allocated size.
void allocate(int capacity)
Allocate the underlying C array.
bool isAllocated() const
Return true if this DArray has been allocated, false otherwise.
Wrapper for a double precision number, for formatted ostream output.
Data * readObject(std::istream &in, ParamComposite &parent, std::string &className, bool &isEnd, bool isRequired=true)
Read a class name, instantiate an object, and read its parameters.
Data * readObjectOptional(std::istream &in, ParamComposite &parent, std::string &className, bool &isEnd)
Read an optional class name, instantiate an object, and read its parameters.
void openOutputFile(const std::string &filename, std::ofstream &out, std::ios_base::openmode mode=std::ios_base::out) const
Open an output file.
void setParamFileName(const std::string ¶mFileName)
Set the parameter file name.
void setOutputPrefix(const std::string &outputPrefix)
Set the output file prefix string.
void setCommandFileName(const std::string &commandFileName)
Set the command file name.
void setInputPrefix(const std::string &inputPrefix)
Set the input file prefix string.
Wrapper for an int, for formatted ostream output.
static std::ostream & file()
Get log ostream by reference.
static void setEcho(bool echo=true)
Enable or disable echoing for all subclasses of ParamComponent.
Begin & readBegin(std::istream &in, const char *label, bool isRequired=true)
Add and read a class label and opening bracket.
void setClassName(const char *className)
Set class name string.
virtual void writeParam(std::ostream &out) const
Write all parameters to an output stream.
std::string className() const
Get class name string.
void readParamComposite(std::istream &in, ParamComposite &child, bool next=true)
Add and read a required child ParamComposite.
End & readEnd(std::istream &in)
Add and read the closing bracket.
Wrapper for a std::string, for formatted ostream output.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
std::string toString(int n)
Return string representation of an integer.
C++ namespace for polymer self-consistent field theory (PSCF).
void set(BracketPolicy::Type policy)
Set policy regarding use of bracket delimiters on arrays.
Utility classes for scientific computation.