1#ifndef RPG_SIMULATOR_TPP
2#define RPG_SIMULATOR_TPP
13#include <rpg/system/System.h>
14#include <rpg/solvers/Mixture.h>
15#include <rpg/solvers/Polymer.h>
16#include <rpg/solvers/Solvent.h>
17#include <rpg/field/Domain.h>
18#include <rpg/fts/compressor/Compressor.h>
19#include <rpg/fts/compressor/CompressorFactory.h>
20#include <rpg/fts/perturbation/Perturbation.h>
21#include <rpg/fts/perturbation/PerturbationFactory.h>
22#include <rpg/fts/ramp/Ramp.h>
23#include <rpg/fts/ramp/RampFactory.h>
24#include <rpg/fts/VecOpFts.h>
26#include <prdc/cuda/resources.h>
28#include <pscf/cuda/CudaRandom.h>
29#include <pscf/inter/Interaction.h>
30#include <pscf/math/IntVec.h>
32#include <util/misc/Timer.h>
33#include <util/random/Random.h>
36#include <gsl/gsl_eigen.h>
62 compressorFactoryPtr_(nullptr),
63 compressorPtr_(nullptr),
64 perturbationFactoryPtr_(nullptr),
65 perturbationPtr_(nullptr),
66 rampFactoryPtr_(nullptr),
82 if (compressorFactoryPtr_) {
83 delete compressorFactoryPtr_;
86 delete compressorPtr_;
88 if (perturbationFactoryPtr_) {
89 delete perturbationFactoryPtr_;
91 if (perturbationPtr_) {
92 delete perturbationPtr_;
94 if (rampFactoryPtr_) {
95 delete rampFactoryPtr_;
110 const int nMonomer =
system().mixture().nMonomer();
113 chiP_.allocate(nMonomer, nMonomer);
114 chiEvals_.allocate(nMonomer);
115 chiEvecs_.allocate(nMonomer, nMonomer);
116 sc_.allocate(nMonomer);
119 wc_.allocate(nMonomer);
120 cc_.allocate(nMonomer);
122 for (
int i = 0; i < nMonomer; ++i) {
123 wc_[i].allocate(dimensions);
124 cc_[i].allocate(dimensions);
128 dc_.allocate(nMonomer-1);
129 for (
int i = 0; i < nMonomer - 1; ++i) {
130 dc_[i].allocate(dimensions);
135 wcs_.allocate(dimensions);
138 if (!
state_.isAllocated) {
139 state_.allocate(nMonomer, dimensions);
181 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::simulate"); }
188 std::string classname,
189 std::string filename)
190 {
UTIL_THROW(
"Error: Unimplemented function Simulator<D>::analyze"); }
207 const int nMonomer = mixture.
nMonomer();
208 const int meshSize = domain.
mesh().size();
219 for (
int i = 0; i < np; ++i) {
220 polymerPtr = &mixture.
polymer(i);
221 phi = polymerPtr->
phi();
222 mu = polymerPtr->
mu();
224 length = polymerPtr->
length();
226 length = (double) polymerPtr->
nBead();
230 lnQ += phi*( -mu + 1.0 )/length;
239 for (
int i = 0; i < ns; ++i) {
240 solventPtr = &mixture.
solvent(i);
241 phi = solventPtr->
phi();
242 mu = solventPtr->
mu();
243 size = solventPtr->
size();
246 lnQ += phi*( -mu + 1.0 )/size;
253 lnQ += sum_xi/double(meshSize);
263 for (j = 0; j < nMonomer - 1; ++j) {
264 prefactor = -0.5*double(nMonomer)/chiEvals_[j];
272 HW += prefactor * wSqure;
276 HW /= double(meshSize);
279 HW += 0.5*sc_[nMonomer - 1];
282 const double vSystem = domain.
unitCell().volume();
283 const double vMonomer = mixture.
vMonomer();
284 const double nMonomerSystem = vSystem / vMonomer;
306 const int nMonomer =
system().mixture().nMonomer();
308 double d = 1.0/double(nMonomer);
314 for (i = 0; i < nMonomer; ++i) {
315 for (j = 0; j < nMonomer; ++j) {
324 for (i = 0; i < nMonomer; ++i) {
325 for (j = 0; j < nMonomer; ++j) {
327 for (k = 0; k < nMonomer; ++k) {
328 T(i,j) += chi(i,k)*P(k,j);
336 for (i = 0; i < nMonomer; ++i) {
337 for (j = 0; j < nMonomer; ++j) {
339 for (k = 0; k < nMonomer; ++k) {
340 chiP(i,j) += P(i,k)*T(k,j);
349 gsl_matrix* A = gsl_matrix_alloc(nMonomer, nMonomer);
352 for (i = 0; i < nMonomer; ++i) {
353 for (j = 0; j < nMonomer; ++j) {
354 gsl_matrix_set(A, i, j, chiP(i, j));
359 gsl_eigen_symmv_workspace* work = gsl_eigen_symmv_alloc(nMonomer);
360 gsl_vector* Avals = gsl_vector_alloc(nMonomer);
361 gsl_matrix* Avecs = gsl_matrix_alloc(nMonomer, nMonomer);
363 error = gsl_eigen_symmv(A, Avals, Avecs, work);
375 for (i = 0; i < nMonomer; ++i) {
376 val = gsl_vector_get(Avals, i);
377 if (std::abs(val) < 1.0E-8) {
384 for (j = 0; j < nMonomer; ++j) {
385 chiEvecs_(k, j) = gsl_matrix_get(Avecs, j, i);
387 if (chiEvecs_(k, 0) < 0.0) {
388 for (j = 0; j < nMonomer; ++j) {
389 chiEvecs_(k, j) = -chiEvecs_(k, j);
401 for (j = 0; j < nMonomer; ++j) {
402 chiEvecs_(i, j) = gsl_matrix_get(Avecs, j, iNull);
404 if (chiEvecs_(i, 0) < 0) {
405 for (j = 0; j < nMonomer; ++j) {
406 chiEvecs_(i, j) = -chiEvecs_(i, j);
411 double vec, norm, prefactor;
412 for (i = 0; i < nMonomer; ++i) {
414 for (j = 0; j < nMonomer; ++j) {
415 vec = chiEvecs_(i, j);
418 prefactor = sqrt(
double(nMonomer)/norm );
419 for (j = 0; j < nMonomer; ++j) {
420 chiEvecs_(i, j) *= prefactor;
425 for (j = 0; j < nMonomer; ++j) {
426 UTIL_CHECK(std::abs(chiEvecs_(nMonomer-1, j) - 1.0) < 1.0E-8);
432 for (i = 0; i < nMonomer; ++i) {
434 for (j = 0; j < nMonomer; ++j) {
437 s[i] = s[i]/double(nMonomer);
441 for (i = 0; i < nMonomer; ++i) {
443 for (j = 0; j < nMonomer; ++j) {
444 sc_[i] += chiEvecs_(i,j)*s[j];
446 sc_[i] = sc_[i]/double(nMonomer);
451 for (i = 0; i < nMonomer; ++i) {
452 Log::file() <<
"Eigenpair " << i <<
"\n";
453 Log::file() <<
"value = " << chiEvals_[i] <<
"\n";
455 for (j = 0; j < nMonomer; ++j) {
459 Log::file() <<
" sc[i] = " << sc_[i] << std::endl;
474 const int nMonomer =
system().mixture().nMonomer();
478 for (i = 0; i < nMonomer; ++i) {
485 for (j = 0; j < nMonomer; ++j) {
487 vec = (cudaReal) chiEvecs_(i, j)/nMonomer;
509 const int nMonomer =
system().mixture().nMonomer();
513 for (i = 0; i < nMonomer; ++i) {
520 for (j = 0; j < nMonomer; ++j) {
522 vec = (cudaReal)chiEvecs_(i, j);
544 const int nMonomer =
system().mixture().nMonomer();
545 const double vMonomer =
system().mixture().vMonomer();
546 const double a = 1.0/vMonomer;
551 for (i = 0; i < nMonomer - 1; ++i) {
555 b = -1.0*double(nMonomer)/chiEvals_[i];
584 int nMonomer =
system().mixture().nMonomer();
587 for (
int i = 0; i < nMonomer; ++i) {
595 for (
int i = 0; i < nMonomer; ++i) {
603 for (
int i = 0; i < nMonomer - 1; ++i) {
609 if (
state_.needsHamiltonian){
635 int nMonomer =
system().mixture().nMonomer();
636 int meshSize =
system().domain().mesh().size();
642 if (
state_.needsHamiltonian){
650 for (
int i = 0; i < nMonomer; ++i) {
656 for (
int i = 0; i < nMonomer; ++i) {
663 for (
int i = 0; i < nMonomer - 1; ++i) {
683 {
state_.hasData =
false; }
693 compressorPtr_->outputTimers(out);
704 out <<
"MDE counter "
705 << compressorPtr_->mdeCounter() << std::endl;
784 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 a Ramp parameter file block.
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 a Perturbation parameter file block.
CompressorFactory< D > & compressorFactory()
Get the compressor factory by reference.
void readCompressor(std::istream &in, bool &isEnd)
Optionally read a Compressor parameter file block.
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.
Main class, representing a complete physical system.
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).
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 ?
double sum(Array< double > const &in)
Compute sum of array elements .
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute inner product of two real arrays .
void eqV(Array< double > &a, Array< double > const &b)
Vector assignment, a[i] = b[i].
void subVS(Array< double > &a, Array< double > const &b, double c)
Vector subtraction, a[i] = b[i] - c.
void eqS(Array< double > &a, double b)
Vector assignment, a[i] = b.
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.