1#ifndef RPC_SIMULATOR_TPP
2#define RPC_SIMULATOR_TPP
13#include <rpc/system/System.h>
14#include <rpc/solvers/Mixture.h>
15#include <rpc/solvers/Polymer.h>
16#include <rpc/solvers/Solvent.h>
17#include <rpc/field/Domain.h>
18#include <rpc/fts/compressor/Compressor.h>
19#include <rpc/fts/compressor/CompressorFactory.h>
20#include <rpc/fts/perturbation/Perturbation.h>
21#include <rpc/fts/perturbation/PerturbationFactory.h>
22#include <rpc/fts/ramp/Ramp.h>
23#include <rpc/fts/ramp/RampFactory.h>
25#include <pscf/inter/Interaction.h>
27#include <util/misc/Timer.h>
28#include <util/random/Random.h>
32#include <gsl/gsl_eigen.h>
57 compressorFactoryPtr_(nullptr),
58 compressorPtr_(nullptr),
59 perturbationFactoryPtr_(nullptr),
60 perturbationPtr_(nullptr),
61 rampFactoryPtr_(nullptr),
77 if (compressorFactoryPtr_) {
78 delete compressorFactoryPtr_;
80 if (compressorPtr_ ) {
81 delete compressorPtr_;
83 if (perturbationFactoryPtr_) {
84 delete perturbationFactoryPtr_;
86 if (perturbationPtr_) {
87 delete perturbationPtr_;
89 if (rampFactoryPtr_) {
90 delete rampFactoryPtr_;
105 const int nMonomer =
system().mixture().nMonomer();
108 chiP_.allocate(nMonomer, nMonomer);
109 chiEvals_.allocate(nMonomer);
110 chiEvecs_.allocate(nMonomer, nMonomer);
111 sc_.allocate(nMonomer);
114 wc_.allocate(nMonomer);
115 cc_.allocate(nMonomer);
117 for (
int i = 0; i < nMonomer; ++i) {
118 wc_[i].allocate(dimensions);
119 cc_[i].allocate(dimensions);
123 dc_.allocate(nMonomer-1);
124 for (
int i = 0; i < nMonomer - 1; ++i) {
125 dc_[i].allocate(dimensions);
129 if (!
state_.isAllocated) {
131 state_.allocate(nMonomer, dimensions);
164 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::simulate"); }
171 std::string classname,
172 std::string filename)
173 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::analyze"); }
202 const int nMonomer = mixture.
nMonomer();
203 const int meshSize = domain.
mesh().size();
214 for (
int i = 0; i < np; ++i) {
215 polymerPtr = &mixture.
polymer(i);
216 phi = polymerPtr->
phi();
217 mu = polymerPtr->
mu();
219 length = polymerPtr->
length();
221 length = (double)polymerPtr->
nBead();
225 lnQ += phi*( -mu + 1.0 )/length;
234 for (
int i = 0; i < ns; ++i) {
235 solventPtr = &mixture.
solvent(i);
236 phi = solventPtr->
phi();
237 mu = solventPtr->
mu();
238 size = solventPtr->
size();
241 lnQ += phi*( -mu + 1.0 )/size;
248 for (
int i = 0; i < meshSize; ++i) {
249 lnQ += Wc[i]/double(meshSize);
257 double prefactor, w, s;
259 for (j = 0; j < nMonomer - 1; ++j) {
261 prefactor = -0.5*double(nMonomer)/chiEvals_[j];
263 for (i = 0; i < meshSize; ++i) {
270 HW /= double(meshSize);
273 HW += 0.5*sc_[nMonomer - 1];
276 const double vSystem = domain.
unitCell().volume();
277 const double vMonomer = mixture.
vMonomer();
278 const double nMonomerSystem = vSystem / vMonomer;
300 const int nMonomer =
system().mixture().nMonomer();
302 double d = 1.0/double(nMonomer);
308 for (i = 0; i < nMonomer; ++i) {
309 for (j = 0; j < nMonomer; ++j) {
318 for (i = 0; i < nMonomer; ++i) {
319 for (j = 0; j < nMonomer; ++j) {
321 for (k = 0; k < nMonomer; ++k) {
322 T(i,j) += chi(i,k)*P(k,j);
330 for (i = 0; i < nMonomer; ++i) {
331 for (j = 0; j < nMonomer; ++j) {
333 for (k = 0; k < nMonomer; ++k) {
334 chiP(i,j) += P(i,k)*T(k,j);
343 gsl_matrix* A = gsl_matrix_alloc(nMonomer, nMonomer);
346 for (i = 0; i < nMonomer; ++i) {
347 for (j = 0; j < nMonomer; ++j) {
348 gsl_matrix_set(A, i, j, chiP(i, j));
353 gsl_eigen_symmv_workspace* work = gsl_eigen_symmv_alloc(nMonomer);
354 gsl_vector* Avals = gsl_vector_alloc(nMonomer);
355 gsl_matrix* Avecs = gsl_matrix_alloc(nMonomer, nMonomer);
357 error = gsl_eigen_symmv(A, Avals, Avecs, work);
369 for (i = 0; i < nMonomer; ++i) {
370 val = gsl_vector_get(Avals, i);
371 if (std::abs(val) < 1.0E-8) {
378 for (j = 0; j < nMonomer; ++j) {
379 chiEvecs_(k, j) = gsl_matrix_get(Avecs, j, i);
381 if (chiEvecs_(k, 0) < 0.0) {
382 for (j = 0; j < nMonomer; ++j) {
383 chiEvecs_(k, j) = -chiEvecs_(k, j);
395 for (j = 0; j < nMonomer; ++j) {
396 chiEvecs_(i, j) = gsl_matrix_get(Avecs, j, iNull);
398 if (chiEvecs_(i, 0) < 0) {
399 for (j = 0; j < nMonomer; ++j) {
400 chiEvecs_(i, j) = -chiEvecs_(i, j);
405 double vec, norm, prefactor;
406 for (i = 0; i < nMonomer; ++i) {
408 for (j = 0; j < nMonomer; ++j) {
409 vec = chiEvecs_(i, j);
412 prefactor = sqrt(
double(nMonomer)/norm );
413 for (j = 0; j < nMonomer; ++j) {
414 chiEvecs_(i, j) *= prefactor;
419 for (j = 0; j < nMonomer; ++j) {
420 UTIL_CHECK(std::abs(chiEvecs_(nMonomer-1, j) - 1.0) < 1.0E-8);
426 for (i = 0; i < nMonomer; ++i) {
428 for (j = 0; j < nMonomer; ++j) {
431 s[i] = s[i]/double(nMonomer);
435 for (i = 0; i < nMonomer; ++i) {
437 for (j = 0; j < nMonomer; ++j) {
438 sc_[i] += chiEvecs_(i,j)*s[j];
440 sc_[i] = sc_[i]/double(nMonomer);
445 for (i = 0; i < nMonomer; ++i) {
446 Log::file() <<
"Eigenpair " << i <<
"\n";
447 Log::file() <<
"value = " << chiEvals_[i] <<
"\n";
449 for (j = 0; j < nMonomer; ++j) {
453 Log::file() <<
" sc[i] = " << sc_[i] << std::endl;
468 const int nMonomer =
system().mixture().nMonomer();
469 const int meshSize =
system().domain().mesh().size();
473 for (j = 0; j < nMonomer; ++j) {
477 for (i = 0; i < meshSize; ++i) {
482 for (k = 0; k < nMonomer; ++k) {
483 double vec = chiEvecs_(j, k)/double(nMonomer);
487 for (i = 0; i < meshSize; ++i) {
509 const int nMonomer =
system().mixture().nMonomer();
510 const int meshSize =
system().domain().mesh().size();
514 for (i = 0; i < nMonomer; ++i) {
518 for (k = 0; k < meshSize; ++k) {
523 for (j = 0; j < nMonomer; ++j) {
525 double vec = chiEvecs_(i, j);
528 for (k = 0; k < meshSize; ++k) {
550 const int meshSize =
system().domain().mesh().size();
551 const int nMonomer =
system().mixture().nMonomer();
552 const double vMonomer =
system().mixture().vMonomer();
553 const double a = 1.0/vMonomer;
559 for (i = 0; i < nMonomer - 1; ++i) {
563 b = -1.0*double(nMonomer)/chiEvals_[i];
566 for (k = 0; k < meshSize; ++k) {
567 Dc[k] = a*( b*(Wc[k] - s) + Cc[k] );
593 int nMonomer =
system().mixture().nMonomer();
595 for (
int i = 0; i < nMonomer; ++i) {
604 for (
int i = 0; i < nMonomer; ++i) {
613 for (
int i = 0; i < nMonomer - 1; ++i) {
619 if (
state_.needsHamiltonian){
645 const int nMonomer =
system().mixture().nMonomer();
651 if (
state_.needsHamiltonian){
659 for (
int i = 0; i < nMonomer; ++i) {
665 for (
int i = 0; i < nMonomer; ++i) {
672 for (
int i = 0; i < nMonomer - 1; ++i) {
692 {
state_.hasData =
false; }
703 compressorPtr_->outputTimers(out);
713 out <<
"MDE counter "
714 << compressorPtr_->mdeCounter() << std::endl;
725 compressorPtr_->clearTimers();
790 perturbationPtr_ = ptr;
An IntVec<D, T> is a D-component vector of elements of integer type T.
Field of real double precision values on an FFT mesh.
SolventT & solvent(int id)
Get a solvent solver object.
PolymerT & polymer(int id)
Get a polymer solver object by non-const reference.
Factory for subclasses of Compressor.
Spatial domain for a periodic structure with real fields, on a CPU.
Mesh< D > & mesh()
Get the Mesh by non-const reference.
UnitCell< D > & unitCell()
Get the UnitCell by non-const reference.
Solver and descriptor for a mixture of polymers and solvents.
int nPolymer() const
Get number of polymer species.
int nMonomer() const
Get number of monomer types.
int nSolvent() const
Get number of solvent (point particle) species.
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
Factory for subclasses of Perturbation.
Base class for additive perturbations of standard FTS Hamiltonian.
Descriptor and solver for one polymer species.
double phi() const
Get the overall volume fraction for this species.
int nBead() const
Total number of beads in the polymer (bead model).
double mu() const
Get the chemical potential for this species (units kT=1).
double length() const
Sum of the lengths of all blocks in the polymer (thread model).
Factory for subclasses of Ramp.
Class that varies parameters during a simulation (abstract).
bool hasCc_
Have eigen-components of the current c fields been computed ?
void readPerturbation(std::istream &in, bool &isEnd)
Optionally read a Perturbation parameter file block.
Perturbation< D > & perturbation()
Get the perturbation factory by non-const reference.
System< D > & system()
Get parent system by reference.
bool hasWc_
Have eigen-components of the current w fields been computed ?
void computeDc()
Compute functional derivatives of the Hamiltonian.
SimState< D > state_
Previous state saved during at the beginning of a step.
bool hasHamiltonian_
Has the Hamiltonian been computed for the current w and c fields?
virtual void analyze(int min, int max, std::string classname, std::string filename)
Read and analyze a trajectory file.
void setClassName(const char *className)
Set class name string.
double perturbationHamiltonian() const
Get the perturbation to the standard Hamiltonian (if any).
void clearState()
Clear the saved copy of the fts state.
PerturbationFactory< D > & perturbationFactory()
Get the perturbation factory by reference.
void computeWc()
Compute eigenvector components of the current w fields.
DArray< RField< D > > const & cc() const
Get all eigenvector components of the current c fields.
void setPerturbation(Perturbation< D > *ptr)
Set the associated Perturbation.
void clearData()
Clear field eigen-components and hamiltonian components.
bool hasDc() const
Are the current d fields valid ?
void analyzeChi()
Perform eigenvalue analysis of projected chi matrix.
double fieldHamiltonian_
Field contribution (H_W) to Hamiltonian.
virtual void outputMdeCounter(std::ostream &out) const
Output MDE counter.
long seed_
Random number generator seed.
virtual void readParameters(std::istream &in)
Read parameters for a simulation.
void allocate()
Allocate required memory.
double idealHamiltonian_
Ideal gas contribution (-lnQ) to Hamiltonian H[W].
virtual void simulate(int nStep)
Perform a field theoretic Monte-Carlo simulation.
void setRamp(Ramp< D > *ptr)
Set the associated ramp.
DArray< RField< D > > wc_
Eigenvector components of w fields on a real space grid.
DArray< RField< D > > dc_
Components of d fields on a real space grid.
bool hasCc() const
Are eigen-components of current c fields valid ?
RampFactory< D > & rampFactory()
Get the ramp factory by reference.
double hamiltonian_
Total field theoretic Hamiltonian H[W] (extensive value).
double perturbationHamiltonian_
Perturbation to the standard Hamiltonian (if any).
virtual void clearTimers()
Clear timers.
bool hasWc() const
Are eigen-components of current w fields valid ?
CompressorFactory< D > & compressorFactory()
Get the compressor factory by reference.
bool hasDc_
Have functional derivatives of H[W] been computed ?
void restoreState()
Restore the saved copy of the fts move state.
void saveState()
Save a copy of the fts move state.
long iTotalStep_
Step counter - total number of attempted BD or MC steps.
double hamiltonian() const
Get the Hamiltonian used in PS-FTS.
bool hasCompressor() const
Does this Simulator have a Compressor?
void readRandomSeed(std::istream &in)
Optionally read a random number generator seed.
bool hasPerturbation() const
Does this Simulator have a Perturbation?
DArray< RField< D > > cc_
Eigenvector components of c fields on a real space grid.
virtual void outputTimers(std::ostream &out) const
Output timing results.
void readCompressor(std::istream &in, bool &isEnd)
Optionally read a Compressor parameter file block.
double fieldHamiltonian() const
Get the quadratic field contribution to the Hamiltonian.
long iStep_
Step counter - attempted steps for which compressor converges.
void readRamp(std::istream &in, bool &isEnd)
Optionally read a Ramp parameter file block.
bool hasHamiltonian() const
Has the Hamiltonian been computed for current w and c fields?
DArray< RField< D > > const & dc() const
Get all of the current d fields.
Random random_
Random number generator.
DArray< RField< D > > const & wc() const
Get all eigenvector components of the current w fields.
void computeHamiltonian()
Compute the Hamiltonian used in PS-FTS.
double idealHamiltonian() const
Get ideal gas contribution to the Hamiltonian.
Random & random()
Get random number generator by reference.
void computeCc()
Compute eigenvector components of the current c fields.
Solver and descriptor for a solvent species.
double phi() const
Get the overall volume fraction for this species.
double mu() const
Get the chemical potential for this species (units kT=1).
double size() const
Get the size (number of monomers) in this solvent.
Main class, representing a complete physical system.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
Dynamically allocated Matrix.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
static std::ostream & file()
Get log ostream by reference.
std::string indent() const
Return indent string for this object (string of spaces).
static bool echo()
Get echo parameter.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
std::string className() const
Get class name string.
File containing preprocessor macros for error handling.
#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.
bool isThread()
Is the thread model in use ?
Real periodic fields, SCFT and PS-FTS (CPU).
PSCF package top-level namespace.