1#ifndef RPG_SIMULATOR_TPP
2#define RPG_SIMULATOR_TPP
13#include <rpg/system/System.h>
14#include <rpg/fts/compressor/Compressor.h>
15#include <rpg/fts/compressor/CompressorFactory.h>
16#include <rpg/fts/perturbation/Perturbation.h>
17#include <rpg/fts/perturbation/PerturbationFactory.h>
18#include <rpg/fts/ramp/Ramp.h>
19#include <rpg/fts/ramp/RampFactory.h>
20#include <rpg/fts/VecOpFts.h>
22#include <prdc/cuda/resources.h>
24#include <pscf/cuda/CudaRandom.h>
25#include <pscf/inter/Interaction.h>
26#include <pscf/math/IntVec.h>
28#include <util/random/Random.h>
29#include <util/misc/Timer.h>
32#include <gsl/gsl_eigen.h>
58 compressorFactoryPtr_(nullptr),
59 compressorPtr_(nullptr),
60 perturbationFactoryPtr_(nullptr),
61 perturbationPtr_(nullptr),
62 rampFactoryPtr_(nullptr),
78 if (compressorFactoryPtr_) {
79 delete compressorFactoryPtr_;
82 delete compressorPtr_;
84 if (perturbationFactoryPtr_) {
85 delete perturbationFactoryPtr_;
87 if (perturbationPtr_) {
88 delete perturbationPtr_;
90 if (rampFactoryPtr_) {
91 delete rampFactoryPtr_;
106 const int nMonomer =
system().mixture().nMonomer();
109 chiP_.allocate(nMonomer, nMonomer);
110 chiEvals_.allocate(nMonomer);
111 chiEvecs_.allocate(nMonomer, nMonomer);
112 sc_.allocate(nMonomer);
115 wc_.allocate(nMonomer);
116 cc_.allocate(nMonomer);
118 for (
int i = 0; i < nMonomer; ++i) {
119 wc_[i].allocate(dimensions);
120 cc_[i].allocate(dimensions);
124 dc_.allocate(nMonomer-1);
125 for (
int i = 0; i < nMonomer - 1; ++i) {
126 dc_[i].allocate(dimensions);
131 wcs_.allocate(dimensions);
134 if (!
state_.isAllocated) {
135 state_.allocate(nMonomer, dimensions);
177 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::simulate"); }
184 std::string classname,
185 std::string filename)
186 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::analyze"); }
203 const int nMonomer = mixture.
nMonomer();
204 const int meshSize = domain.
mesh().size();
215 for (
int i = 0; i < np; ++i) {
216 polymerPtr = &mixture.
polymer(i);
217 phi = polymerPtr->
phi();
218 mu = polymerPtr->
mu();
220 length = polymerPtr->
length();
222 length = (double) polymerPtr->
nBead();
226 lnQ += phi*( -mu + 1.0 )/length;
235 for (
int i = 0; i < ns; ++i) {
236 solventPtr = &mixture.
solvent(i);
237 phi = solventPtr->
phi();
238 mu = solventPtr->
mu();
239 size = solventPtr->
size();
242 lnQ += phi*( -mu + 1.0 )/size;
248 double sum_xi = Reduce::sum(
wc_[nMonomer-1]);
249 lnQ += sum_xi/double(meshSize);
259 for (j = 0; j < nMonomer - 1; ++j) {
260 prefactor = -0.5*double(nMonomer)/chiEvals_[j];
267 wSqure = Reduce::innerProduct(wcs_, wcs_);
268 HW += prefactor * wSqure;
272 HW /= double(meshSize);
275 HW += 0.5*sc_[nMonomer - 1];
278 const double vSystem = domain.
unitCell().volume();
279 const double vMonomer = mixture.
vMonomer();
280 const double nMonomerSystem = vSystem / vMonomer;
302 const int nMonomer =
system().mixture().nMonomer();
304 double d = 1.0/double(nMonomer);
310 for (i = 0; i < nMonomer; ++i) {
311 for (j = 0; j < nMonomer; ++j) {
320 for (i = 0; i < nMonomer; ++i) {
321 for (j = 0; j < nMonomer; ++j) {
323 for (k = 0; k < nMonomer; ++k) {
324 T(i,j) += chi(i,k)*P(k,j);
332 for (i = 0; i < nMonomer; ++i) {
333 for (j = 0; j < nMonomer; ++j) {
335 for (k = 0; k < nMonomer; ++k) {
336 chiP(i,j) += P(i,k)*T(k,j);
345 gsl_matrix* A = gsl_matrix_alloc(nMonomer, nMonomer);
348 for (i = 0; i < nMonomer; ++i) {
349 for (j = 0; j < nMonomer; ++j) {
350 gsl_matrix_set(A, i, j, chiP(i, j));
355 gsl_eigen_symmv_workspace* work = gsl_eigen_symmv_alloc(nMonomer);
356 gsl_vector* Avals = gsl_vector_alloc(nMonomer);
357 gsl_matrix* Avecs = gsl_matrix_alloc(nMonomer, nMonomer);
359 error = gsl_eigen_symmv(A, Avals, Avecs, work);
371 for (i = 0; i < nMonomer; ++i) {
372 val = gsl_vector_get(Avals, i);
373 if (std::abs(val) < 1.0E-8) {
380 for (j = 0; j < nMonomer; ++j) {
381 chiEvecs_(k, j) = gsl_matrix_get(Avecs, j, i);
383 if (chiEvecs_(k, 0) < 0.0) {
384 for (j = 0; j < nMonomer; ++j) {
385 chiEvecs_(k, j) = -chiEvecs_(k, j);
397 for (j = 0; j < nMonomer; ++j) {
398 chiEvecs_(i, j) = gsl_matrix_get(Avecs, j, iNull);
400 if (chiEvecs_(i, 0) < 0) {
401 for (j = 0; j < nMonomer; ++j) {
402 chiEvecs_(i, j) = -chiEvecs_(i, j);
407 double vec, norm, prefactor;
408 for (i = 0; i < nMonomer; ++i) {
410 for (j = 0; j < nMonomer; ++j) {
411 vec = chiEvecs_(i, j);
414 prefactor = sqrt(
double(nMonomer)/norm );
415 for (j = 0; j < nMonomer; ++j) {
416 chiEvecs_(i, j) *= prefactor;
421 for (j = 0; j < nMonomer; ++j) {
422 UTIL_CHECK(std::abs(chiEvecs_(nMonomer-1, j) - 1.0) < 1.0E-8);
428 for (i = 0; i < nMonomer; ++i) {
430 for (j = 0; j < nMonomer; ++j) {
433 s[i] = s[i]/double(nMonomer);
437 for (i = 0; i < nMonomer; ++i) {
439 for (j = 0; j < nMonomer; ++j) {
440 sc_[i] += chiEvecs_(i,j)*s[j];
442 sc_[i] = sc_[i]/double(nMonomer);
447 for (i = 0; i < nMonomer; ++i) {
448 Log::file() <<
"Eigenpair " << i <<
"\n";
449 Log::file() <<
"value = " << chiEvals_[i] <<
"\n";
451 for (j = 0; j < nMonomer; ++j) {
455 Log::file() <<
" sc[i] = " << sc_[i] << std::endl;
470 const int nMonomer =
system().mixture().nMonomer();
474 for (i = 0; i < nMonomer; ++i) {
481 for (j = 0; j < nMonomer; ++j) {
483 vec = (cudaReal) chiEvecs_(i, j)/nMonomer;
505 const int nMonomer =
system().mixture().nMonomer();
509 for (i = 0; i < nMonomer; ++i) {
516 for (j = 0; j < nMonomer; ++j) {
518 vec = (cudaReal)chiEvecs_(i, j);
540 const int nMonomer =
system().mixture().nMonomer();
541 const double vMonomer =
system().mixture().vMonomer();
542 const double a = 1.0/vMonomer;
547 for (i = 0; i < nMonomer - 1; ++i) {
551 b = -1.0*double(nMonomer)/chiEvals_[i];
580 int nMonomer =
system().mixture().nMonomer();
583 for (
int i = 0; i < nMonomer; ++i) {
591 for (
int i = 0; i < nMonomer; ++i) {
599 for (
int i = 0; i < nMonomer - 1; ++i) {
605 if (
state_.needsHamiltonian){
631 int nMonomer =
system().mixture().nMonomer();
632 int meshSize =
system().domain().mesh().size();
638 if (
state_.needsHamiltonian){
646 for (
int i = 0; i < nMonomer; ++i) {
652 for (
int i = 0; i < nMonomer; ++i) {
659 for (
int i = 0; i < nMonomer - 1; ++i) {
679 {
state_.hasData =
false; }
689 compressorPtr_->outputTimers(out);
700 out <<
"MDE counter "
701 << compressorPtr_->mdeCounter() << std::endl;
780 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 GPU.
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).
void readRandomSeed(std::istream &in)
Read random seed and initialize random number generators.
PerturbationFactory< D > & perturbationFactory()
Get the perturbation factory by reference.
bool hasPerturbation() const
Does this Simulator have a Perturbation?
Random random_
Random number generator.
System< D > & system()
Get parent system by reference.
void computeWc()
Compute eigenvector components of the current w fields.
void setClassName(const char *className)
Set class name string.
CudaRandom & cudaRandom()
Get cuda random number generator by reference.
void readRamp(std::istream &in, bool &isEnd)
Optionally read an associated ramp.
void computeCc()
Compute eigenvector components of the current c fields.
DArray< RField< D > > dc_
Components of d fields on a real space grid.
bool hasHamiltonian_
Has the Hamiltonian been computed for the current w and c fields?
bool hasWc_
Have eigen-components of the current w fields been computed ?
bool hasCc() const
Are eigen-components of current c fields valid ?
void setPerturbation(Perturbation< D > *ptr)
Set the associated perturbation.
void computeDc()
Compute functional derivatives of the Hamiltonian.
SimState< D > state_
State saved during fts simulation.
bool hasHamiltonian() const
Has the MC Hamiltonian been computed for current w and c fields?
double perturbationHamiltonian_
Perturbation to the standard Hamiltonian (if any).
long iTotalStep_
Simulation step counter.
virtual void analyze(int min, int max, std::string classname, std::string filename)
Read and analyze a trajectory file.
Random & random()
Get random number generator by reference.
bool hasDc_
Have functional derivatives of H[W] been computed ?
void allocate()
Allocate required memory.
DArray< RField< D > > cc_
Eigenvector components of c fields on a real space grid.
void saveState()
Save a copy of the fts move state.
void restoreState()
Restore the saved copy of the fts move state.
void readPerturbation(std::istream &in, bool &isEnd)
Optionally read an associated perturbation.
CompressorFactory< D > & compressorFactory()
Get the compressor factory by reference.
void readCompressor(std::istream &in, bool &isEnd)
Read the compressor block of the parameter file.
virtual void simulate(int nStep)
Perform a field theoretic Monte-Carlo simulation.
virtual void outputMdeCounter(std::ostream &out) const
Output MDE counter.
double hamiltonian() const
Get the Hamiltonian used in field theoretic simulations.
bool hasCc_
Have eigen-components of the current c fields been computed ?
CudaRandom cudaRandom_
Random number generator.
bool hasRamp() const
Does this Simulator have a Ramp?
virtual void readParameters(std::istream &in)
Read parameters for a simulation.
Simulator(System< D > &system)
Constructor.
double fieldHamiltonian_
Field contribution (H_W) to Hamiltonian.
void analyzeChi()
Perform eigenvalue analysis of projected chi matrix.
Compressor< D > & compressor()
Get the compressor by non-const reference.
bool hasCompressor() const
Does this Simulator have a Compressor object?
bool hasWc() const
Are eigen-components of current w fields valid ?
Perturbation< D > const & perturbation() const
Get the associated Perturbation by const reference.
bool hasDc() const
Are the current d fields valid ?
double idealHamiltonian_
Ideal gas contribution (lnQ) to Hamiltonian H[W].
void setRamp(Ramp< D > *ptr)
Set the associated ramp.
double fieldHamiltonian() const
Get the quadratic field contribution (HW) to MC Hamiltonian.
void clearState()
Clear the saved copy of the fts state.
long seed_
Random number generator seed.
long iStep_
Simulation step counter.
virtual void clearTimers()
Clear timers.
double hamiltonian_
Field theoretic Hamiltonian H[W] (extensive value).
RampFactory< D > & rampFactory()
Get the ramp factory by reference.
double idealHamiltonian() const
Get ideal gas contribution (-lnQ) to MC Hamiltonian.
DArray< RField< D > > wc_
Eigenvector components of w fields on a real space grid.
virtual void outputTimers(std::ostream &out) const
Output timing results.
double perturbationHamiltonian() const
Get the perturbation to the standard Hamiltonian (if any).
void computeHamiltonian()
Compute the Hamiltonian used in field theoretic simulations.
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 one complete 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 ?
void eqV(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, const int beginIdA, const int beginIdB, const int n)
Vector assignment, a[i] = b[i], kernel wrapper (cudaReal).
void eqS(DeviceArray< cudaReal > &a, const cudaReal b, const int beginIdA, const int n)
Vector assignment, a[i] = b, kernel wrapper (cudaReal).
void subVS(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, const cudaReal c, const int beginIdA, const int beginIdB, const int n)
Vector subtraction, a[i] = b[i] - c, kernel wrapper (cudaReal).
void addEqVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c)
Vector addition in-place w/ coefficient, a[i] += b[i] * c, kernel wrapper.
void computeDField(DeviceArray< cudaReal > &d, DeviceArray< cudaReal > const &Wc, DeviceArray< cudaReal > const &Cc, cudaReal const a, cudaReal const b, cudaReal const s)
Compute d field (functional derivative of H[w])
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.