1#ifndef CPC_SIMULATOR_TPP
2#define CPC_SIMULATOR_TPP
12#include <pscf/cpu/complex.h>
15#include <cpc/system/System.h>
16#include <cpc/solvers/Mixture.h>
17#include <cpc/solvers/Polymer.h>
18#include <cpc/solvers/Solvent.h>
19#include <cpc/field/Domain.h>
20#include <cpc/fts/step/Step.h>
21#include <cpc/fts/step/StepFactory.h>
23#include <cpc/fts/analyzer/AnalyzerFactory.h>
24#include <cpc/fts/trajectory/TrajectoryReader.h>
25#include <cpc/fts/trajectory/TrajectoryReaderFactory.h>
27#include <pscf/interaction/Interaction.h>
28#include <util/random/Random.h>
29#include <util/misc/Timer.h>
33#include <gsl/gsl_eigen.h>
57 idealHamiltonian_(0.0),
58 fieldHamiltonian_(0.0),
61 stepFactoryPtr_(nullptr),
66 hasHamiltonian_(false),
87 if (stepFactoryPtr_) {
88 delete stepFactoryPtr_;
91 if (trajectoryReaderFactoryPtr_) {
92 delete trajectoryReaderFactoryPtr_;
105 const int nMonomer =
system().mixture().nMonomer();
108 u_.allocate(nMonomer, nMonomer);
109 evecs_.allocate(nMonomer, nMonomer);
110 evals_.allocate(nMonomer);
111 isPositiveEval_.allocate(nMonomer);
114 wc_.allocate(nMonomer);
115 cc_.allocate(nMonomer);
116 dc_.allocate(nMonomer);
118 for (
int i = 0; i < nMonomer; ++i) {
119 wc_[i].allocate(dimensions);
120 cc_[i].allocate(dimensions);
121 dc_[i].allocate(dimensions);
140 stepFactoryPtr_->readObjectOptional(in, *
this,
className,
148 Analyzer<D>::baseInterval = 0;
158 void Simulator<D>::setup(
int nStep)
163 analyzeInteraction();
172 computeHamiltonian();
176 if (analyzerManager_.size() > 0){
177 analyzerManager_.setup();
188 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::simulate"); }
211 analyzerTimer.
start();
212 if (analyzerManager_.size() > 0){
213 analyzerManager_.sample(iStep_);
215 analyzerTimer.
stop();
218 for (iTotalStep_ = 0; iTotalStep_ < nStep; ++iTotalStep_) {
226 analyzerTimer.
start();
227 if (Analyzer<D>::baseInterval != 0) {
228 if (analyzerManager_.size() > 0) {
229 if (iStep_ % Analyzer<D>::baseInterval == 0) {
230 analyzerManager_.sample(iStep_);
234 analyzerTimer.
stop();
240 double time = timer.
time();
241 double analyzerTime = analyzerTimer.
time();
245 if (Analyzer<D>::baseInterval > 0){
246 analyzerManager_.output();
252 Log::file() <<
"nStep " << nStep << std::endl;
254 <<
" sec" << std::endl;
255 double rStep = double(nStep);
256 Log::file() <<
"time / nStep " << time / rStep
257 <<
" sec" << std::endl;
258 Log::file() <<
"Analyzer run time " << analyzerTime
259 <<
" sec" << std::endl;
271 std::string classname,
272 std::string filename)
273 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::analyze"); }
282 std::string classname,
283 std::string filename)
292 TrajectoryReader<D>* trajectoryReaderPtr;
293 trajectoryReaderPtr = trajectoryReaderFactory().factory(classname);
294 if (!trajectoryReaderPtr) {
296 message =
"Invalid TrajectoryReader class name " + classname;
301 trajectoryReaderPtr->open(filename);
302 trajectoryReaderPtr->readHeader();
308 hasFrame = trajectoryReaderPtr->readFrame();
310 for (iStep_ = 0; iStep_ <=
max && hasFrame; ++iStep_) {
322 analyzerManager_.sample(iStep_);
326 hasFrame = trajectoryReaderPtr->readFrame();
329 Log::file() <<
"end main loop" << std::endl;
330 int nFrames = iStep_ -
min;
331 trajectoryReaderPtr->close();
332 delete trajectoryReaderPtr;
335 analyzerManager_.output();
339 Log::file() <<
"# of frames " << nFrames << std::endl;
341 <<
" sec" << std::endl;
342 Log::file() <<
"time / frame " << timer.
time()/double(nFrames)
343 <<
" sec" << std::endl;
355 hasHamiltonian_ =
false;
371 hasHamiltonian_ =
false;
376 const int nMonomer = mixture.
nMonomer();
377 const int meshSize = domain.
mesh().size();
383 const double vSystem = domain.
unitCell().volume();
384 const double vMonomer = mixture.
vMonomer();
385 const double nMonomerSystem = vSystem / vMonomer;
388 std::complex<double> phi, mu, lnQ;
389 lnQ = std::complex<double>(0.0, 0.0);
393 for (
int i = 0; i < np; ++i) {
394 polymerPtr = &mixture.
polymer(i);
395 phi = polymerPtr->
phi();
396 if (std::abs(phi) > 1.0E-08) {
397 mu = polymerPtr->
mu();
399 length = polymerPtr->
length();
401 length = (double)polymerPtr->
nBead();
403 lnQ += phi*( -mu + 1.0 )/length;
413 for (
int i = 0; i < ns; ++i) {
414 solventPtr = &mixture.
solvent(i);
415 phi = solventPtr->
phi();
416 if (std::abs(phi) > 1.0E-8) {
417 mu = solventPtr->
mu();
418 size = solventPtr->
size();
419 lnQ += phi*( -mu + 1.0 )/size;
424 idealHamiltonian_ = -1.0 * nMonomerSystem * lnQ;
427 fieldHamiltonian_ = std::complex<double>(0.0, 0.0);
428 std::complex<double> w;
431 for (j = 0; j < nMonomer; ++j) {
433 prefactor = -0.5*double(nMonomer)/evals_[j];
434 for (i = 0; i < meshSize; ++i) {
436 fieldHamiltonian_ += prefactor * w * w;
439 fieldHamiltonian_ /= double(meshSize);
440 fieldHamiltonian_ *= nMonomerSystem;
442 hamiltonian_ = idealHamiltonian_ + fieldHamiltonian_;
444 hasHamiltonian_ =
true;
455 const int nMonomer =
system().mixture().nMonomer();
457 double const & zeta =
system().interaction().zeta();
461 for (i = 0; i < nMonomer; ++i) {
462 for (j = 0; j < nMonomer; ++j) {
463 u_(i, j) = chi(i,j) + zeta;
471 gsl_matrix* A = gsl_matrix_alloc(nMonomer, nMonomer);
474 for (i = 0; i < nMonomer; ++i) {
475 for (j = 0; j < nMonomer; ++j) {
476 gsl_matrix_set(A, i, j, u_(i, j));
481 gsl_eigen_symmv_workspace* work = gsl_eigen_symmv_alloc(nMonomer);
482 gsl_vector* Avals = gsl_vector_alloc(nMonomer);
483 gsl_matrix* Avecs = gsl_matrix_alloc(nMonomer, nMonomer);
485 error = gsl_eigen_symmv(A, Avals, Avecs, work);
490 for (i = 0; i < nMonomer; ++i) {
491 val = gsl_vector_get(Avals, i);
494 isPositiveEval_[i] =
true;
496 isPositiveEval_[i] =
false;
498 for (j = 0; j < nMonomer; ++j) {
499 evecs_(i, j) = gsl_matrix_get(Avecs, j, i);
501 if (evecs_(i, 0) < 0.0) {
502 for (j = 0; j < nMonomer; ++j) {
503 evecs_(i, j) = -evecs_(i, j);
509 double vec, norm, prefactor;
510 for (i = 0; i < nMonomer; ++i) {
512 for (j = 0; j < nMonomer; ++j) {
516 prefactor = sqrt(
double(nMonomer)/norm );
517 for (j = 0; j < nMonomer; ++j) {
518 evecs_(i, j) *= prefactor;
524 for (i = 0; i < nMonomer; ++i) {
525 Log::file() <<
"Eigenpair " << i <<
"\n";
526 Log::file() <<
"value = " << evals_[i] <<
"\n";
528 for (j = 0; j < nMonomer; ++j) {
532 Log::file() <<
" sc[i] = " << sc_[i] << std::endl;
547 const int nMonomer =
system().mixture().nMonomer();
548 const int meshSize =
system().domain().mesh().size();
555 for (j = 0; j < nMonomer; ++j) {
559 for (i = 0; i < meshSize; ++i) {
564 for (k = 0; k < nMonomer; ++k) {
565 vec = evecs_(j, k)/double(nMonomer);
569 for (i = 0; i < meshSize; ++i) {
593 const int nMonomer =
system().mixture().nMonomer();
594 const int meshSize =
system().domain().mesh().size();
600 for (i = 0; i < nMonomer; ++i) {
604 for (k = 0; k < meshSize; ++k) {
609 for (j = 0; j < nMonomer; ++j) {
614 for (k = 0; k < meshSize; ++k) {
638 const int meshSize =
system().domain().mesh().size();
639 const int nMonomer =
system().mixture().nMonomer();
640 const double vMonomer =
system().mixture().vMonomer();
641 const double a = 1.0/vMonomer;
648 for (i = 0; i < nMonomer - 1; ++i) {
652 b = -1.0*double(nMonomer)/evals_[i];
654 for (k = 0; k < meshSize; ++k) {
671 void Simulator<D>::readRandomSeed(std::istream& in)
675 readOptional(in,
"seed", seed_);
679 random().setSeed(seed_);
int nPolymer() const
Get number of polymer species.
int nSolvent() const
Get number of solvent (point particle) species.
PolymerT & polymer(int id)
Get a polymer solver object by non-const reference.
SolventT & solvent(int id)
Get a solvent solver object.
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
int nMonomer() const
Get number of monomer types.
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.
Descriptor and solver for one polymer species.
std::complex< 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).
int nBead() const
Total number of beads in the polymer (bead model).
std::complex< double > phi() const
Get the overall volume fraction for this species.
Simulator for complex Langevin field theoretic simulation.
void allocate()
Allocate required memory.
virtual void simulate(int nStep)
Perform a complex Langevin field theoretic simulation.
void computeHamiltonian()
Compute the Hamiltonian used in PS-FTS.
System< D > & system()
Get parent system by reference.
void computeCc()
Compute eigenvector components of the current c fields.
void clearData()
Clear field eigen-components and hamiltonian components.
void computeWc()
Compute eigenvector components of the current w fields.
virtual void readParameters(std::istream &in)
Read parameters for a simulation.
void analyzeInteraction()
Perform eigenvalue analysis of the interaction matrix U.
bool hasStep() const
Does this Simulator have a Step object?
void computeDc()
Compute functional derivatives of the Hamiltonian.
Solver and descriptor for a solvent species.
double size() const
Get the size (number of monomers) in this solvent.
Factory for subclasses of Step.
Main class for CL-FTS, representing a complete physical system.
An IntVec<D, T> is a D-component vector of elements of integer type T.
Field of complex double precision values on an FFT mesh.
WT mu() const
Get the chemical potential for this species (units kT=1).
WT phi() const
Get the overall volume fraction for this species.
Dynamically allocated 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.
void setClassName(const char *className)
Set class name string.
std::string className() const
Get class name string.
void readParamCompositeOptional(std::istream &in, ParamComposite &child, bool next=true)
Add and attempt to read an optional child ParamComposite.
void start(TimePoint begin)
Start timing from an externally supplied time.
double time() const
Return the accumulated time, in seconds.
void stop(TimePoint end)
Stop the clock at an externally supplied time.
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.
void addEq(fftw_complex &a, fftw_complex const &b)
In-place addition of fftw_complex numbers, a += b.
void assign(fftw_complex &z, double const &a, double const &b)
Create an fftw_complex from real and imaginary parts, z = a + ib.
void mul(fftw_complex &z, fftw_complex const &a, fftw_complex const &b)
Multiplication of fftw_complex numbers, z = a * b.
double min(Array< double > const &in)
Get minimum of array elements .
double max(Array< double > const &in)
Get maximum of array elements (real).
Complex periodic fields, CL-FTS (CPU).
bool isThread()
Is the thread model in use ?
PSCF package top-level namespace.
float product(float a, float b)
Product for float Data.