PSCF v1.3
rpg/fts/simulator/Simulator.tpp
1#ifndef RPG_SIMULATOR_TPP
2#define RPG_SIMULATOR_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field
6*
7* Copyright 2015 - 2025, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "Simulator.h"
12
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>
21
22#include <prdc/cuda/resources.h>
23
24#include <pscf/cuda/CudaRandom.h>
25#include <pscf/inter/Interaction.h>
26#include <pscf/math/IntVec.h>
27
28#include <util/random/Random.h>
29#include <util/misc/Timer.h>
30#include <util/global.h>
31
32#include <gsl/gsl_eigen.h>
33
34namespace Pscf {
35namespace Rpg {
36
37 using namespace Util;
38
39 /*
40 * Constructor.
41 */
42 template <int D>
44 : random_(),
46 hamiltonian_(0.0),
50 iStep_(0),
51 iTotalStep_(0),
52 seed_(0),
53 hasHamiltonian_(false),
54 hasWc_(false),
55 hasCc_(false),
56 hasDc_(false),
57 systemPtr_(&system),
58 compressorFactoryPtr_(nullptr),
59 compressorPtr_(nullptr),
60 perturbationFactoryPtr_(nullptr),
61 perturbationPtr_(nullptr),
62 rampFactoryPtr_(nullptr),
63 rampPtr_(nullptr),
64 isAllocated_(false)
65 {
66 setClassName("Simulator");
67 compressorFactoryPtr_ = new CompressorFactory<D>(system);
68 perturbationFactoryPtr_ = new PerturbationFactory<D>(*this);
69 rampFactoryPtr_ = new RampFactory<D>(*this);
70 }
71
72 /*
73 * Destructor.
74 */
75 template <int D>
77 {
78 if (compressorFactoryPtr_) {
79 delete compressorFactoryPtr_;
80 }
81 if (compressorPtr_) {
82 delete compressorPtr_;
83 }
84 if (perturbationFactoryPtr_) {
85 delete perturbationFactoryPtr_;
86 }
87 if (perturbationPtr_) {
88 delete perturbationPtr_;
89 }
90 if (rampFactoryPtr_) {
91 delete rampFactoryPtr_;
92 }
93 if (rampPtr_) {
94 delete rampPtr_;
95 }
96 }
97
98 /*
99 * Allocate required memory.
100 */
101 template <int D>
103 {
104 UTIL_CHECK(!isAllocated_);
105
106 const int nMonomer = system().mixture().nMonomer();
107
108 // Allocate projected chi matrix chiP_ and associated arrays
109 chiP_.allocate(nMonomer, nMonomer);
110 chiEvals_.allocate(nMonomer);
111 chiEvecs_.allocate(nMonomer, nMonomer);
112 sc_.allocate(nMonomer);
113
114 // Allocate memory for eignevector components of w and c fields
115 wc_.allocate(nMonomer);
116 cc_.allocate(nMonomer);
117 const IntVec<D> dimensions = system().domain().mesh().dimensions();
118 for (int i = 0; i < nMonomer; ++i) {
119 wc_[i].allocate(dimensions);
120 cc_[i].allocate(dimensions);
121 }
122
123 // Allocate memory for components of d (functional derivative)
124 dc_.allocate(nMonomer-1);
125 for (int i = 0; i < nMonomer - 1; ++i) {
126 dc_[i].allocate(dimensions);
127 }
128
129 // Allocate memory for single eigenvector components of w
130 // after constant shift
131 wcs_.allocate(dimensions);
132
133 // Allocate state_, if necessary.
134 if (!state_.isAllocated) {
135 state_.allocate(nMonomer, dimensions);
136 }
137
138 isAllocated_ = true;
139 }
140
141 /*
142 * Virtual function - this version is only used for testing.
143 */
144 template <int D>
145 void Simulator<D>::readParameters(std::istream &in)
146 {
147 readRandomSeed(in);
148
149 #if 0
150 // Optionally random seed
151 seed_ = 0;
152 readOptional(in, "seed", seed_);
153
154 // Set random number generator seed.
155 // Default value seed_ = 0 uses clock time.
156 random().setSeed(seed_);
157 cudaRandom().setSeed(seed_);
158 #endif
159
160 bool isEnd = false;
161
162 // Read required Compressor block
163 readCompressor(in, isEnd);
164
165 // Optionally read a Perturbation
166 readPerturbation(in, isEnd);
167
168 // Optionally read a Ramp
169 readRamp(in, isEnd);
170 }
171
172 /*
173 * Perform a field theoretic simulation of nStep steps.
174 */
175 template <int D>
177 { UTIL_THROW("Error: Unimplemented function Simulator<D>::simulate"); }
178
179 /*
180 * Open, read and analyze a trajectory file
181 */
182 template <int D>
183 void Simulator<D>::analyze(int min, int max,
184 std::string classname,
185 std::string filename)
186 { UTIL_THROW("Error: Unimplemented function Simulator<D>::analyze"); }
187
188 /*
189 * Compute field theoretic Hamiltonian H[W].
190 */
191 template <int D>
193 {
194 UTIL_CHECK(isAllocated_);
195 UTIL_CHECK(system().w().hasData());
196 UTIL_CHECK(system().c().hasData());
198 hasHamiltonian_ = false;
199
200 Mixture<D> const & mixture = system().mixture();
201 Domain<D> const & domain = system().domain();
202
203 const int nMonomer = mixture.nMonomer();
204 const int meshSize = domain.mesh().size();
205
206 const int np = mixture.nPolymer();
207 const int ns = mixture.nSolvent();
208 double phi, mu;
209
210 // Compute polymer ideal gas contributions to lnQ
211 double lnQ = 0.0;
212 if (np > 0) {
213 Polymer<D> const * polymerPtr;
214 double length;
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();
221 } else {
222 length = (double) polymerPtr->nBead();
223 }
224 // Recall: mu = ln(phi/q)
225 if (phi > 1.0E-08) {
226 lnQ += phi*( -mu + 1.0 )/length;
227 }
228 }
229 }
230
231 // Compute solvent ideal gas contributions to lnQ
232 if (ns > 0) {
233 Solvent<D> const * solventPtr;
234 double size;
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();
240 // Recall: mu = ln(phi/q)
241 if (phi > 1.0E-8) {
242 lnQ += phi*( -mu + 1.0 )/size;
243 }
244 }
245 }
246
247 // Add average of pressure field wc_[nMonomer-1] to lnQ
248 double sum_xi = Reduce::sum(wc_[nMonomer-1]);
249 lnQ += sum_xi/double(meshSize);
250
251 // lnQ now contains a value per monomer
252
253 // Initialize field contribution HW
254
255 // Compute quadratic field contribution to HW
256 double HW = 0.0;
257 double prefactor, s;
258 int j;
259 for (j = 0; j < nMonomer - 1; ++j) {
260 prefactor = -0.5*double(nMonomer)/chiEvals_[j];
261 // Obtain constant shift
262 s = sc_[j];
263 // Subtract of constant shift s
264 VecOp::subVS(wcs_, wc_[j], s);
265 // Compute quadratic field contribution to HW
266 double wSqure = 0;
267 wSqure = Reduce::innerProduct(wcs_, wcs_);
268 HW += prefactor * wSqure;
269 }
270
271 // Normalize HW to equal a value per monomer
272 HW /= double(meshSize);
273
274 // Add constant term K/2 per monomer (K=s=e^{T}chi e/M^2)
275 HW += 0.5*sc_[nMonomer - 1];
276
277 // Compute number of monomers in the system (nMonomerSystem)
278 const double vSystem = domain.unitCell().volume();
279 const double vMonomer = mixture.vMonomer();
280 const double nMonomerSystem = vSystem / vMonomer;
281
282 // Compute final Hamiltonian components
283 fieldHamiltonian_ = nMonomerSystem * HW;
284 idealHamiltonian_ = -1.0 * nMonomerSystem * lnQ;
286
287 if (hasPerturbation()) {
290 } else {
292 }
293
294 hasHamiltonian_ = true;
295 }
296
297 template <int D>
299 {
300 UTIL_CHECK(isAllocated_);
301
302 const int nMonomer = system().mixture().nMonomer();
303 DMatrix<double> const & chi = system().interaction().chi();
304 double d = 1.0/double(nMonomer);
305 int i, j, k;
306
307 // Compute orthogonal projection matrix P
309 P.allocate(nMonomer, nMonomer);
310 for (i = 0; i < nMonomer; ++i) {
311 for (j = 0; j < nMonomer; ++j) {
312 P(i,j) = -d;
313 }
314 P(i,i) += 1.0;
315 }
316
317 // Compute T = chi*P (temporary matrix)
319 T.allocate(nMonomer, nMonomer);
320 for (i = 0; i < nMonomer; ++i) {
321 for (j = 0; j < nMonomer; ++j) {
322 T(i, j) = 0.0;
323 for (k = 0; k < nMonomer; ++k) {
324 T(i,j) += chi(i,k)*P(k,j);
325 }
326 }
327 }
328
329 // Compute chiP = = P*chi*P = P*T
330 DMatrix<double> chiP;
331 chiP.allocate(nMonomer, nMonomer);
332 for (i = 0; i < nMonomer; ++i) {
333 for (j = 0; j < nMonomer; ++j) {
334 chiP(i, j) = 0.0;
335 for (k = 0; k < nMonomer; ++k) {
336 chiP(i,j) += P(i,k)*T(k,j);
337 }
338 }
339 }
340
341 // Eigenvalue calculations use data structures and
342 // functions from the Gnu Scientific Library (GSL)
343
344 // Allocate GSL matrix A that will hold a copy of chiP
345 gsl_matrix* A = gsl_matrix_alloc(nMonomer, nMonomer);
346
347 // Copy DMatrix<double> chiP to gsl_matrix A
348 for (i = 0; i < nMonomer; ++i) {
349 for (j = 0; j < nMonomer; ++j) {
350 gsl_matrix_set(A, i, j, chiP(i, j));
351 }
352 }
353
354 // Compute eigenvalues and eigenvectors of chiP (or A)
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);
358 int error;
359 error = gsl_eigen_symmv(A, Avals, Avecs, work);
360 UTIL_CHECK(error == 0);
361
362 // Requirements:
363 // - A has exactly one zero eigenvalue, with eigenvector (1,...,1)
364 // - All other eigenvalues must be negative.
365
366 // Copy eigenpairs with non-null eigenvalues
367 int iNull = -1; // index for null eigenvalue
368 int nNull = 0; // number of null eigenvalue
369 k = 0; // re-ordered index for non-null eigenvalue
370 double val;
371 for (i = 0; i < nMonomer; ++i) {
372 val = gsl_vector_get(Avals, i);
373 if (std::abs(val) < 1.0E-8) {
374 ++nNull;
375 iNull = i;
376 UTIL_CHECK(nNull <= 1);
377 } else {
378 chiEvals_[k] = val;
379 UTIL_CHECK(val < 0.0);
380 for (j = 0; j < nMonomer; ++j) {
381 chiEvecs_(k, j) = gsl_matrix_get(Avecs, j, i);
382 }
383 if (chiEvecs_(k, 0) < 0.0) {
384 for (j = 0; j < nMonomer; ++j) {
385 chiEvecs_(k, j) = -chiEvecs_(k, j);
386 }
387 }
388 ++k;
389 }
390 }
391 UTIL_CHECK(nNull == 1);
392 UTIL_CHECK(iNull >= 0);
393
394 // Set eigenpair with zero eigenvalue
395 i = nMonomer - 1;
396 chiEvals_[i] = 0.0;
397 for (j = 0; j < nMonomer; ++j) {
398 chiEvecs_(i, j) = gsl_matrix_get(Avecs, j, iNull);
399 }
400 if (chiEvecs_(i, 0) < 0) {
401 for (j = 0; j < nMonomer; ++j) {
402 chiEvecs_(i, j) = -chiEvecs_(i, j);
403 }
404 }
405
406 // Normalize all eigenvectors so that the sum of squares = nMonomer
407 double vec, norm, prefactor;
408 for (i = 0; i < nMonomer; ++i) {
409 norm = 0.0;
410 for (j = 0; j < nMonomer; ++j) {
411 vec = chiEvecs_(i, j);
412 norm += vec*vec;
413 }
414 prefactor = sqrt( double(nMonomer)/norm );
415 for (j = 0; j < nMonomer; ++j) {
416 chiEvecs_(i, j) *= prefactor;
417 }
418 }
419
420 // Check final eigenvector is (1, ..., 1)
421 for (j = 0; j < nMonomer; ++j) {
422 UTIL_CHECK(std::abs(chiEvecs_(nMonomer-1, j) - 1.0) < 1.0E-8);
423 }
424
425 // Compute vector s in monomer basis
427 s.allocate(nMonomer);
428 for (i = 0; i < nMonomer; ++i) {
429 s[i] = 0.0;
430 for (j = 0; j < nMonomer; ++j) {
431 s[i] += chi(i,j);
432 }
433 s[i] = s[i]/double(nMonomer);
434 }
435
436 // Compute components of s in eigenvector basis -> sc_
437 for (i = 0; i < nMonomer; ++i) {
438 sc_[i] = 0.0;
439 for (j = 0; j < nMonomer; ++j) {
440 sc_[i] += chiEvecs_(i,j)*s[j];
441 }
442 sc_[i] = sc_[i]/double(nMonomer);
443 }
444
445 #if 0
446 // Debugging output
447 for (i = 0; i < nMonomer; ++i) {
448 Log::file() << "Eigenpair " << i << "\n";
449 Log::file() << "value = " << chiEvals_[i] << "\n";
450 Log::file() << "vector = [ ";
451 for (j = 0; j < nMonomer; ++j) {
452 Log::file() << chiEvecs_(i, j) << " ";
453 }
454 Log::file() << "]\n";
455 Log::file() << " sc[i] = " << sc_[i] << std::endl;
456 }
457 #endif
458
459 }
460
461 /*
462 * Compute the eigenvector components of the w fields, using the
463 * eigenvectors chiEvecs_ of the projected chi matrix as a basis.
464 */
465 template <int D>
467 {
468 UTIL_CHECK(isAllocated_);
469
470 const int nMonomer = system().mixture().nMonomer();
471 int i,j;
472
473 // Loop over eigenvectors (i is an eigenvector index)
474 for (i = 0; i < nMonomer; ++i) {
475
476 // Loop over grid points to zero out field wc_[i]
477 RField<D>& Wc = wc_[i];
478 VecOp::eqS(Wc, 0.0);
479
480 // Loop over monomer types (j is a monomer index)
481 for (j = 0; j < nMonomer; ++j) {
482 cudaReal vec;
483 vec = (cudaReal) chiEvecs_(i, j)/nMonomer;
484
485 // Loop over grid points
486 VecOp::addEqVc(Wc, system().w().rgrid(j), vec);
487 }
488 }
489
490 hasWc_ = true;
491 }
492
493 /*
494 * Compute the eigenvector components of the c-fields, using the
495 * eigenvectors chiEvecs_ of the projected chi matrix as a basis.
496 */
497 template <int D>
499 {
500 // Preconditions
501 UTIL_CHECK(isAllocated_);
502 UTIL_CHECK(system().w().hasData());
503 UTIL_CHECK(system().c().hasData());
504
505 const int nMonomer = system().mixture().nMonomer();
506 int i, j;
507
508 // Loop over eigenvectors (i is an eigenvector index)
509 for (i = 0; i < nMonomer; ++i) {
510
511 // Set cc_[i] to zero
512 RField<D>& Cc = cc_[i];
513 VecOp::eqS(Cc, 0.0);
514
515 // Loop over monomer types
516 for (j = 0; j < nMonomer; ++j) {
517 cudaReal vec;
518 vec = (cudaReal)chiEvecs_(i, j);
519
520 // Loop over grid points
521 VecOp::addEqVc(Cc, system().c().rgrid(j), vec);
522 }
523 }
524
525 hasCc_ = true;
526 }
527
528 /*
529 * Compute d fields, i.e., functional derivatives of H[W].
530 */
531 template <int D>
533 {
534 // Preconditions
535 UTIL_CHECK(isAllocated_);
536 if (!hasWc_) computeWc();
537 if (!hasCc_) computeCc();
538
539 // Local constants and variables
540 const int nMonomer = system().mixture().nMonomer();
541 const double vMonomer = system().mixture().vMonomer();
542 const double a = 1.0/vMonomer;
543 double b, s;
544 int i;
545
546 // Loop over composition eigenvectors (exclude the last)
547 for (i = 0; i < nMonomer - 1; ++i) {
548 RField<D>& Dc = dc_[i];
549 RField<D> const & Wc = wc_[i];
550 RField<D> const & Cc = cc_[i];
551 b = -1.0*double(nMonomer)/chiEvals_[i];
552 s = sc_[i];
553
554 // Loop over grid points
555 VecOpFts::computeDField(Dc, Wc, Cc, a, b, s);
556 }
557
558 // Add derivatives arising from a perturbation (if any).
559 if (hasPerturbation()) {
560 perturbation().incrementDc(dc_);
561 }
562
563 hasDc_ = true;
564 }
565
566 /*
567 * Save the current state prior to a next move.
568 *
569 * Invoked before each move.
570 */
571 template <int D>
573 {
574 UTIL_CHECK(system().w().hasData());
575 UTIL_CHECK(hasWc());
576 UTIL_CHECK(state_.isAllocated);
577 UTIL_CHECK(!state_.hasData);
578
579 // Set fields
580 int nMonomer = system().mixture().nMonomer();
581
582 // Set field components
583 for (int i = 0; i < nMonomer; ++i) {
584 VecOp::eqV(state_.w[i], system().w().rgrid(i));
585 VecOp::eqV(state_.wc[i], wc_[i]);
586 }
587
588 // Save cc based on ccSavePolicy
589 if (state_.needsCc) {
590 UTIL_CHECK(hasCc());
591 for (int i = 0; i < nMonomer; ++i) {
592 VecOp::eqV(state_.cc[i], cc_[i]);
593 }
594 }
595
596 // Save dc based on dcSavePolicy
597 if (state_.needsDc) {
598 UTIL_CHECK(hasDc());
599 for (int i = 0; i < nMonomer - 1; ++i) {
600 VecOp::eqV(state_.dc[i], dc_[i]);
601 }
602 }
603
604 // Save Hamiltonian based on hamiltonianSavePolicy
605 if (state_.needsHamiltonian){
607 state_.hamiltonian = hamiltonian();
608 state_.idealHamiltonian = idealHamiltonian();
609 state_.fieldHamiltonian = fieldHamiltonian();
610 state_.perturbationHamiltonian = perturbationHamiltonian();
611 }
612
613 if (hasPerturbation()) {
614 perturbation().saveState();
615 }
616
617 state_.hasData = true;
618 }
619
620 /*
621 * Restore a saved fts state.
622 *
623 * Invoked after an attempted Monte-Carlo move is rejected
624 * or an fts move fails to converge
625 */
626 template <int D>
628 {
629 UTIL_CHECK(state_.isAllocated);
630 UTIL_CHECK(state_.hasData);
631 int nMonomer = system().mixture().nMonomer();
632 int meshSize = system().domain().mesh().size();
633
634 // Restore fields
635 system().w().setRGrid(state_.w);
636
637 // Restore Hamiltonian and components
638 if (state_.needsHamiltonian){
639 hamiltonian_ = state_.hamiltonian;
640 idealHamiltonian_ = state_.idealHamiltonian;
641 fieldHamiltonian_ = state_.fieldHamiltonian;
642 perturbationHamiltonian_ = state_.perturbationHamiltonian;
643 hasHamiltonian_ = true;
644 }
645
646 for (int i = 0; i < nMonomer; ++i) {
647 VecOp::eqV(wc_[i], state_.wc[i]);
648 }
649 hasWc_ = true;
650
651 if (state_.needsCc) {
652 for (int i = 0; i < nMonomer; ++i) {
653 VecOp::eqV(cc_[i], state_.cc[i]);
654 }
655 hasCc_ = true;
656 }
657
658 if (state_.needsDc) {
659 for (int i = 0; i < nMonomer - 1; ++i) {
660 VecOp::eqV(dc_[i], state_.dc[i]);
661 }
662 hasDc_ = true;
663 }
664
665 if (hasPerturbation()) {
666 perturbation().restoreState();
667 }
668
669 state_.hasData = false;
670 }
671
672 /*
673 * Clear the saved Monte-Carlo state.
674 *
675 * Invoked when an attempted Monte-Carlo move is accepted.
676 */
677 template <int D>
679 { state_.hasData = false; }
680
681 /*
682 * Output all timer results.
683 */
684 template<int D>
685 void Simulator<D>::outputTimers(std::ostream& out) const
686 {
687 UTIL_CHECK(compressorPtr_);
688 outputMdeCounter(out);
689 compressorPtr_->outputTimers(out);
690 }
691
692 /*
693 * Output modified diffusion equation (MDE) counter.
694 */
695 template<int D>
696 void Simulator<D>::outputMdeCounter(std::ostream& out) const
697 {
698 UTIL_CHECK(compressorPtr_);
699 //out << std::endl;
700 out << "MDE counter "
701 << compressorPtr_->mdeCounter() << std::endl;
702 out << std::endl;
703 }
704
705 /*
706 * Clear all timers.
707 */
708 template<int D>
710 {
712 compressor().clearTimers();
713 }
714
715 // Protected Functions
716
717 /*
718 * Read random seed and initialize random number generators.
719 */
720 template <int D>
721 void Simulator<D>::readRandomSeed(std::istream &in)
722 {
723 // Optionally random seed
724 seed_ = 0;
725 readOptional(in, "seed", seed_);
726
727 // Set seed values for both random number generators
728 // Default value seed_ = 0 uses clock time.
729 random().setSeed(seed_);
730 cudaRandom().setSeed(seed_);
731 }
732
733 /*
734 * Read the required Compressor parameter file block.
735 */
736 template<int D>
737 void Simulator<D>::readCompressor(std::istream& in, bool& isEnd)
738 {
739 if (!isEnd) {
741 UTIL_CHECK(compressorFactoryPtr_);
742 std::string className;
743 compressorPtr_ =
744 compressorFactory().readObjectOptional(in, *this,
745 className, isEnd);
746 }
748 Log::file() << indent() << " Compressor{ [absent] }\n";
749 }
750 }
751
752 // Functions related to an associated Perturbation
753
754 /*
755 * Optionally read a Perturbation parameter file block.
756 */
757 template<int D>
758 void Simulator<D>::readPerturbation(std::istream& in, bool& isEnd)
759 {
760 if (!isEnd) {
762 UTIL_CHECK(perturbationFactoryPtr_);
763 std::string className;
764 perturbationPtr_ =
765 perturbationFactory().readObjectOptional(in, *this,
766 className, isEnd);
767 }
769 Log::file() << indent() << " Perturbation{ [absent] }\n";
770 }
771 }
772
773 /*
774 * Set the associated Perturbation<D> object.
775 */
776 template<int D>
778 {
779 UTIL_CHECK(ptr != 0);
780 perturbationPtr_ = ptr;
781 }
782
783 /*
784 * Optionally read a parameter file block for an associated Ramp.
785 */
786 template<int D>
787 void Simulator<D>::readRamp(std::istream& in, bool& isEnd)
788 {
789 if (!isEnd) {
791 UTIL_CHECK(rampFactoryPtr_);
792 std::string className;
793 rampPtr_ =
794 rampFactory().readObjectOptional(in, *this,
795 className, isEnd);
796 }
797 if (!hasRamp() && ParamComponent::echo()) {
798 Log::file() << indent() << " Ramp{ [absent] }\n";
799 }
800 }
801
802 /*
803 * Set the associated Ramp<D> object.
804 */
805 template<int D>
807 {
808 UTIL_CHECK(ptr != 0);
809 rampPtr_ = ptr;
810 }
811
812}
813}
814#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Field of real double precision values on an FFT mesh.
Definition cpu/RField.h:29
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.
Definition Species.h:149
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).
Definition Species.h:155
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.
Definition Species.h:149
double mu() const
Get the chemical potential for this species (units kT=1).
Definition Species.h:155
double size() const
Get the size (number of monomers) in this solvent.
Main class, representing one complete system.
Dynamically allocatable contiguous array template.
Definition DArray.h:32
void allocate(int capacity)
Allocate the underlying C array.
Definition DArray.h:199
Dynamically allocated Matrix.
Definition DMatrix.h:25
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition DMatrix.h:170
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
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.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
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).
Definition VecOp.cu:1039
void eqS(DeviceArray< cudaReal > &a, const cudaReal b, const int beginIdA, const int n)
Vector assignment, a[i] = b, kernel wrapper (cudaReal).
Definition VecOp.cu:1073
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).
Definition VecOp.cu:1323
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.
Definition VecOpMisc.cu:343
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])
Definition VecOpFts.cu:112
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.
Definition param_pc.dox:1