PSCF v1.4.0
r1d/system/System.cpp
1/*
2* PSCF - Polymer Self-Consistent Field
3*
4* Copyright 2015 - 2025, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include "System.h"
9#include <r1d/solvers/Polymer.h>
10#include <r1d/solvers/Solvent.h>
11
12#include <r1d/iterator/Iterator.h>
13#include <r1d/iterator/IteratorFactory.h>
14#include <r1d/sweep/Sweep.h>
15#include <r1d/sweep/SweepFactory.h>
16#include <r1d/iterator/NrIterator.h>
17#include <r1d/system/HomogeneousComparison.h>
18#include <r1d/field/FieldIo.h>
19
20#include <pscf/interaction/Interaction.h>
21
22#include <util/format/Str.h>
23#include <util/format/Int.h>
24#include <util/format/Dbl.h>
25#include <util/param/BracketPolicy.h>
26#include <util/misc/ioUtil.h>
27
28#include <string>
29#include <unistd.h>
30
31namespace Pscf {
32namespace R1d
33{
34
35 using namespace Util;
36
37 /*
38 * Constructor.
39 */
41 : mixture_(),
42 domain_(),
43 fileMaster_(),
44 fieldIo_(),
45 interactionPtr_(0),
46 iteratorPtr_(0),
47 iteratorFactoryPtr_(0),
48 sweepPtr_(0),
49 sweepFactoryPtr_(0),
50 wFields_(),
51 cFields_(),
52 f_(),
53 c_(),
54 fHelmholtz_(0.0),
55 fIdeal_(0.0),
56 fInter_(0.0),
57 pressure_(0.0),
58 hasMixture_(0),
59 hasDomain_(0),
60 hasFields_(0),
61 hasSweep_(0)
62 {
63 setClassName("System");
64
65 fieldIo_.associate(domain_, fileMaster_);
66 interactionPtr_ = new Interaction();
67 iteratorFactoryPtr_ = new IteratorFactory(*this);
68 sweepFactoryPtr_ = new SweepFactory(*this);
69
70 BracketPolicy::set(BracketPolicy::Optional);
71 }
72
73 /*
74 * Destructor.
75 */
77 {
78 if (interactionPtr_) {
79 delete interactionPtr_;
80 }
81 if (iteratorPtr_) {
82 delete iteratorPtr_;
83 }
84 if (iteratorFactoryPtr_) {
85 delete iteratorFactoryPtr_;
86 }
87 if (sweepPtr_) {
88 delete sweepPtr_;
89 }
90 if (sweepFactoryPtr_) {
91 delete sweepFactoryPtr_;
92 }
93 }
94
95 /*
96 * Process command line options.
97 */
98 void System::setOptions(int argc, char **argv)
99 {
100 bool eflag = false; // echo
101 bool pFlag = false; // param file
102 bool cFlag = false; // command file
103 bool iFlag = false; // input prefix
104 bool oFlag = false; // output prefix
105 char* pArg = 0;
106 char* cArg = 0;
107 char* iArg = 0;
108 char* oArg = 0;
109
110 // Read program arguments
111 int c;
112 opterr = 0;
113 while ((c = getopt(argc, argv, "er:p:c:i:o:f")) != -1) {
114 switch (c) {
115 case 'e':
116 eflag = true;
117 break;
118 case 'p': // parameter file
119 pFlag = true;
120 pArg = optarg;
121 break;
122 case 'c': // command file
123 cFlag = true;
124 cArg = optarg;
125 break;
126 case 'i': // input prefix
127 iFlag = true;
128 iArg = optarg;
129 break;
130 case 'o': // output prefix
131 oFlag = true;
132 oArg = optarg;
133 break;
134 case '?':
135 Log::file() << "Unknown option -" << optopt << std::endl;
136 UTIL_THROW("Invalid command line option");
137 }
138 }
139
140 // Set flag to echo parameters as they are read.
141 if (eflag) {
143 }
144
145 // If option -p, set parameter file name
146 if (pFlag) {
147 fileMaster().setParamFileName(std::string(pArg));
148 }
149
150 // If option -c, set command file name
151 if (cFlag) {
152 fileMaster().setCommandFileName(std::string(cArg));
153 }
154
155 // If option -i, set path prefix for input files
156 if (iFlag) {
157 fileMaster().setInputPrefix(std::string(iArg));
158 }
159
160 // If option -o, set path prefix for output files
161 if (oFlag) {
162 fileMaster().setOutputPrefix(std::string(oArg));
163 }
164
165 }
166
167 /*
168 * Read parameters and initialize.
169 */
170 void System::readParameters(std::istream& in)
171 {
173 hasMixture_ = true;
174
175 interaction().setNMonomer(mixture().nMonomer());
177
179 hasDomain_ = true;
180 allocateFields();
181
182 // Instantiate and initialize an Iterator
183 std::string className;
184 bool isEnd;
185 iteratorPtr_ = iteratorFactoryPtr_->readObject(in, *this,
186 className, isEnd);
187 if (!iteratorPtr_) {
188 std::string msg = "Unrecognized Iterator subclass name ";
189 msg += className;
190 UTIL_THROW(msg.c_str());
191 }
192
193 // Optionally instantiate and initialize a Sweep object
194 sweepPtr_ =
195 sweepFactoryPtr_->readObjectOptional(in, *this, className, isEnd);
196 if (sweepPtr_) {
197 hasSweep_ = true;
198 sweepPtr_->setSystem(*this);
199 } else {
200 hasSweep_ = false;
201 }
202 }
203
204 /*
205 * Read default parameter file.
206 */
207 void System::readParam(std::istream& in)
208 {
209 readBegin(in, className().c_str());
210 readParameters(in);
211 readEnd(in);
212 }
213
214 /*
215 * Read default parameter file.
216 */
218 { readParam(fileMaster().paramFile()); }
219
220 /*
221 * Write parameter file, omitting the sweep block.
222 */
223 void System::writeParamNoSweep(std::ostream& out) const
224 {
225 out << "System{" << std::endl;
226 mixture_.writeParam(out);
227 interactionPtr_->writeParam(out);
228 domain_.writeParam(out);
229 iteratorPtr_->writeParam(out);
230 out << "}" << std::endl;
231 }
232
233 /*
234 * Allocate memory for fields.
235 */
236 void System::allocateFields()
237 {
238 // Preconditions
239 UTIL_CHECK(hasMixture_);
240 UTIL_CHECK(hasDomain_);
241
242 // Allocate memory in mixture
244
245 // Allocate wFields and cFields
246 int nMonomer = mixture().nMonomer();
247 wFields_.allocate(nMonomer);
248 cFields_.allocate(nMonomer);
249 int nx = domain().nx();
250 for (int i = 0; i < nMonomer; ++i) {
251 wField(i).allocate(nx);
252 cField(i).allocate(nx);
253 }
254 hasFields_ = true;
255 }
256
257 /*
258 * Read and execute commands from a specified command file.
259 */
260 void System::readCommands(std::istream &in)
261 {
262 UTIL_CHECK(hasMixture_);
263 UTIL_CHECK(hasDomain_);
264
265 std::string command;
266 std::string filename;
267
268 std::istream& inBuffer = in;
269
270 bool readNext = true;
271 while (readNext) {
272
273 inBuffer >> command;
274
275 if (inBuffer.eof()) {
276 break;
277 } else {
278 Log::file() << command;
279 }
280
281 if (command == "FINISH") {
282 Log::file() << std::endl;
283 readNext = false;
284 } else
285 if (command == "READ_W") {
286 readEcho(inBuffer, filename);
287 fieldIo_.readFields(wFields(), filename);
288 } else
289 if (command == "COMPUTE") {
290 // Solve the modified diffusion equation, without iteration
291 Log::file() << std::endl;
292 compute();
293 } else
294 if (command == "ITERATE") {
295 // Attempt iteratively solve a single SCFT problem
296 bool isContinuation = false;
297 int fail = iterate(isContinuation);
298 if (fail) {
299 readNext = false;
300 }
301 } else
302 if (command == "SWEEP") {
303 // Attempt to solve a sequence of SCFT problems along a line
304 // through parameter space.
305 sweep();
306 } else
307 if (command == "WRITE_PARAM") {
308 readEcho(inBuffer, filename);
309 std::ofstream file;
310 fileMaster().openOutputFile(filename, file);
311 writeParam(file);
312 file.close();
313 } else
314 if (command == "WRITE_THERMO") {
315 readEcho(inBuffer, filename);
316 std::ofstream file;
317 fileMaster().openOutputFile(filename, file, std::ios_base::app);
318 writeThermo(file);
319 file.close();
320 } else
321 if (command == "COMPARE_HOMOGENEOUS") {
322 int mode;
323 inBuffer >> mode;
324
325 readEcho(inBuffer, filename);
326 Log::file() << std::endl;
327 Log::file() << "mode = " << mode << std::endl;
328
329 std::ofstream file;
330 fileMaster().openOutputFile(filename, file, std::ios_base::app);
331
332 HomogeneousComparison comparison(*this);
333 comparison.compute(mode);
334 comparison.output(mode, file);
335 file.close();
336 } else
337 if (command == "WRITE_W") {
338 readEcho(inBuffer, filename);
339 fieldIo_.writeFields(wFields(), filename);
340 } else
341 if (command == "WRITE_C") {
342 readEcho(inBuffer, filename);
343 fieldIo_.writeFields(cFields(), filename);
344 } else
345 if (command == "WRITE_BLOCK_C") {
346 readEcho(inBuffer, filename);
347 fieldIo_.writeBlockCFields(mixture_, filename);
348 } else
349 if (command == "WRITE_Q_SLICE") {
350 int polymerId, blockId, directionId, segmentId;
351 readEcho(inBuffer, filename);
352 inBuffer >> polymerId;
353 inBuffer >> blockId;
354 inBuffer >> directionId;
355 inBuffer >> segmentId;
356 Log::file() << Str("polymer ID ", 21) << polymerId << "\n"
357 << Str("block ID ", 21) << blockId << "\n"
358 << Str("direction ID ", 21) << directionId << "\n"
359 << Str("segment ID ", 21) << segmentId << std::endl;
360 writeQSlice(filename, polymerId, blockId, directionId,
361 segmentId);
362 } else
363 if (command == "WRITE_Q_TAIL") {
364 readEcho(inBuffer, filename);
365 int polymerId, blockId, directionId;
366 inBuffer >> polymerId;
367 inBuffer >> blockId;
368 inBuffer >> directionId;
369 Log::file() << Str("polymer ID ", 21) << polymerId << "\n"
370 << Str("block ID ", 21) << blockId << "\n"
371 << Str("direction ID ", 21) << directionId << "\n";
372 writeQTail(filename, polymerId, blockId, directionId);
373 } else
374 if (command == "WRITE_Q_VERTEX") {
375 int polymerId, vertexId;
376 inBuffer >> polymerId;
377 Log::file() << std::endl;
378 Log::file() << "polymerId = "
379 << Int(polymerId, 5) << std::endl;
380 inBuffer >> vertexId;
381 Log::file() << "vertexId = "
382 << Int(vertexId, 5) << std::endl;
383 inBuffer >> filename;
384 Log::file() << "outfile = "
385 << Str(filename, 20) << std::endl;
386 fieldIo_.writeVertexQ(mixture_, polymerId, vertexId, filename);
387 } else
388 if (command == "WRITE_Q") {
389 readEcho(inBuffer, filename);
390 int polymerId, blockId, directionId;
391 inBuffer >> polymerId;
392 inBuffer >> blockId;
393 inBuffer >> directionId;
394 Log::file() << Str("polymer ID ", 21) << polymerId << "\n"
395 << Str("block ID ", 21) << blockId << "\n"
396 << Str("direction ID ", 21) << directionId << "\n";
397 writeQ(filename, polymerId, blockId, directionId);
398 } else
399 if (command == "WRITE_Q_ALL") {
400 readEcho(inBuffer, filename);
401 writeQAll(filename);
402 } else
403 if (command == "REMESH_W") {
404 int nx;
405 inBuffer >> nx;
406 Log::file() << std::endl;
407 Log::file() << "nx = " << Int(nx, 20) << std::endl;
408 inBuffer >> filename;
409 Log::file() << "outfile = " << Str(filename, 20) << std::endl;
410 fieldIo_.remesh(wFields(), nx, filename);
411 } else
412 if (command == "EXTEND_W") {
413 int m;
414 inBuffer >> m;
415 Log::file() << std::endl;
416 Log::file() << "m = " << Int(m, 20) << std::endl;
417 inBuffer >> filename;
418 Log::file() << "outfile = " << Str(filename, 20) << std::endl;
419 fieldIo_.extend(wFields(), m, filename);
420 } else {
421 Log::file() << " Error: Unknown command "
422 << command << std::endl;
423 readNext = false;
424 }
425
426 }
427 }
428
429 /*
430 * Read and execute commands from the default command file.
431 */
433 {
434 if (fileMaster().commandFileName().empty()) {
435 UTIL_THROW("Empty command file name");
436 }
437 readCommands(fileMaster().commandFile());
438 }
439
440 /*
441 * Read a string (e.g., a filename) and echo to the log file.
442 */
443 void System::readEcho(std::istream& in, std::string& string) const
444 {
445 in >> string;
446 Log::file() << " " << Str(string, 20) << std::endl;
447 }
448
449 // Primary SCFT Computations
450
451 /*
452 * Solve MDE for current w-fields, without iteration.
453 */
455 {
456 //UTIL_CHECK(hasWFields_);
457
458 // Solve the modified diffusion equation (without iteration)
459 mixture_.compute(wFields(), cFields_);
460
461 //hasCFields_ = true;
462 }
463
464 /*
465 * Iteratively solve a SCFT problem for specified parameters.
466 */
467 int System::iterate(bool isContinuation)
468 {
469 // UTIL_CHECK(hasWFields_);
470 // hasCFields_ = false;
471
472 Log::file() << std::endl;
473
474 // Call iterator (return 0 for convergence, 1 for failure)
475 int error = iterator().solve(isContinuation);
476
477 //hasCFields_ = true;
478
479 // If converged, compute related properties
480 if (!error) {
483 }
484 return error;
485 }
486
487 /*
488 * Perform sweep along a line in parameter space.
489 */
491 {
492 //UTIL_CHECK(hasWFields_);
493 UTIL_CHECK(sweepPtr_);
494 Log::file() << std::endl;
495 Log::file() << std::endl;
496
497 sweepPtr_->sweep();
498 }
499
500 // Thermodynamic properties
501
502 /*
503 * Compute Helmholtz free energy and pressure
504 */
506 {
507 fHelmholtz_ = 0.0;
508 int np = mixture().nPolymer();
509 int ns = mixture().nSolvent();
510 int nm = mixture().nMonomer();
511 double phi, mu;
512
513 // Polymeric ideal gas contributions to fHelhmoltz_
514 if (np > 0) {
515 Polymer* polymerPtr;
516 double length;
517 for (int i = 0; i < np; ++i) {
518 polymerPtr = &mixture().polymer(i);
519 phi = polymerPtr->phi();
520 mu = polymerPtr->mu();
521 // Recall: mu = ln(phi/q)
522 length = polymerPtr->length();
523 if (phi > 1E-08) {
524 fHelmholtz_ += phi*( mu - 1.0 )/length;
525 }
526 }
527 }
528
529 // Solvent ideal gas contributions to fHelhmoltz_
530 if (ns > 0) {
531 Solvent* solventPtr;
532 double size;
533 for (int i = 0; i < ns; ++i) {
534 solventPtr = &mixture().solvent(i);
535 phi = solventPtr->phi();
536 mu = solventPtr->mu();
537 // Recall: mu = ln(phi/q)
538 size = solventPtr->size();
539 if (phi > 1E-08) {
540 fHelmholtz_ += phi*( mu - 1.0 )/size;
541 }
542 }
543 }
544
545 // Apply Legendre transform subtraction
546 for (int i = 0; i < nm; ++i) {
547 fHelmholtz_ -=
548 domain().innerProduct(wFields_[i], cFields_[i]);
549 }
550 fIdeal_ = fHelmholtz_;
551
552 // Add average interaction free energy density per monomer
553 int nx = domain().nx();
554 if (!f_.isAllocated()) f_.allocate(nx);
555 if (!c_.isAllocated()) c_.allocate(nm);
556 int j, k;
557 // FhInteraction fhInteraction(interaction());
558 Matrix<double> const & chi = interaction().chi();
559 for (int i = 0; i < nx; ++i) {
560 // Store c_[j] = local concentration of species j
561 for (j = 0; j < nm; ++j) {
562 c_[j] = cFields_[j][i];
563 }
564 // Compute f_[i] = excess free eenrgy at grid point i
565 // f_[i] = fhInteraction.fHelmholtz(c_);
566 f_[i] = 0.0;
567 for (j = 0; j < nm; ++j) {
568 for (k = 0; k < nm; ++k) {
569 f_[i] += c_[j]*chi(j, k)*c_[k];
570 }
571 }
572 f_[i] *= 0.5;
573 }
574 fHelmholtz_ += domain().spatialAverage(f_);
575 fInter_ = fHelmholtz_ - fIdeal_;
576
577 // Compute pressure
578 pressure_ = -fHelmholtz_;
579 if (np > 0) {
580 double length;
581 Polymer* polymerPtr;
582 for (int i = 0; i < np; ++i) {
583 polymerPtr = & mixture().polymer(i);
584 phi = polymerPtr->phi();
585 mu = polymerPtr->mu();
586 length = polymerPtr->length();
587 if (phi > 1E-08) {
588 pressure_ += phi*mu/length;
589 }
590 }
591 }
592 if (ns > 0) {
593 double size;
594 Solvent* solventPtr;
595 for (int i = 0; i < ns; ++i) {
596 solventPtr = & mixture().solvent(i);
597 phi = solventPtr->phi();
598 mu = solventPtr->mu();
599 size = solventPtr->size();
600 if (phi > 1E-08) {
601 pressure_ += phi*mu/size;
602 }
603 }
604 }
605
606 }
607
608 void System::writeThermo(std::ostream& out) const
609 {
610 out << std::endl;
611 out << "fHelmholtz " << Dbl(fHelmholtz(), 18, 11) << std::endl;
612 out << "pressure " << Dbl(pressure(), 18, 11) << std::endl;
613 out << std::endl;
614 out << "fIdeal " << Dbl(fIdeal_, 18, 11) << std::endl;
615 out << "fInter " << Dbl(fInter_, 18, 11) << std::endl;
616 out << std::endl;
617
618 // Polymers
619 int np = mixture().nPolymer();
620 if (np > 0) {
621 out << "polymers:" << std::endl;
622 out << " "
623 << " phi "
624 << " mu "
625 << std::endl;
626 for (int i = 0; i < np; ++i) {
627 out << Int(i, 5)
628 << " " << Dbl(mixture().polymer(i).phi(),18, 11)
629 << " " << Dbl(mixture().polymer(i).mu(), 18, 11)
630 << std::endl;
631 }
632 out << std::endl;
633 }
634
635 // Solvents
636 int ns = mixture().nSolvent();
637 if (ns > 0) {
638 out << "solvents:" << std::endl;
639 out << " "
640 << " phi "
641 << " mu "
642 << std::endl;
643 for (int i = 0; i < ns; ++i) {
644 out << Int(i, 5)
645 << " " << Dbl(mixture().solvent(i).phi(),18, 11)
646 << " " << Dbl(mixture().solvent(i).mu(), 18, 11)
647 << std::endl;
648 }
649 out << std::endl;
650 }
651
652 }
653
654 // Output operations (correspond to command file commands)
655
656 /*
657 * Write w-fields in symmetry-adapted basis format.
658 */
659 void System::writeW(std::string const & filename) const
660 {
661 //UTIL_CHECK(hasWFields_);
662 fieldIo_.writeFields(wFields(), filename);
663 }
664
665 /*
666 * Write all concentration fields in symmetry-adapted basis format.
667 */
668 void System::writeC(std::string const & filename) const
669 {
670 //UTIL_CHECK(hasCFields_);
671 fieldIo_.writeFields(cFields(), filename);
672 }
673
674 /*
675 * Write all concentration fields in real space (r-grid) format, for
676 * each block (or solvent) individually rather than for each species.
677 */
678 void System::writeBlockC(std::string const & filename) const
679 {
680 //UTIL_CHECK(hasCFields_);
681 fieldIo_.writeBlockCFields(mixture_, filename);
682 }
683
684 /*
685 * Write the last time slice of the propagator in r-grid format.
686 */
687 void System::writeQSlice(const std::string & filename,
688 int polymerId, int blockId,
689 int directionId, int segmentId)
690 const
691 {
692 UTIL_CHECK(polymerId >= 0);
693 UTIL_CHECK(polymerId < mixture_.nPolymer());
694 Polymer const& polymer = mixture_.polymer(polymerId);
695 UTIL_CHECK(blockId >= 0);
696 UTIL_CHECK(blockId < polymer.nBlock());
697 UTIL_CHECK(directionId >= 0);
698 UTIL_CHECK(directionId <= 1);
699 Propagator const &
700 propagator = polymer.propagator(blockId, directionId);
701 Field const& field = propagator.q(segmentId);
702 fieldIo_.writeField(field, filename);
703 }
704
705 /*
706 * Write the last time slice of the propagator in r-grid format.
707 */
708 void System::writeQTail(const std::string & filename,
709 int polymerId, int blockId, int directionId)
710 const
711 {
712 UTIL_CHECK(polymerId >= 0);
713 UTIL_CHECK(polymerId < mixture_.nPolymer());
714 Polymer const& polymer = mixture_.polymer(polymerId);
715 UTIL_CHECK(blockId >= 0);
716 UTIL_CHECK(blockId < polymer.nBlock());
717 UTIL_CHECK(directionId >= 0);
718 UTIL_CHECK(directionId <= 1);
719 Field const&
720 field = polymer.propagator(blockId, directionId).tail();
721 fieldIo_.writeField(field, filename);
722 }
723
724 /*
725 * Write the propagator for a block and direction.
726 */
727 void System::writeQ(const std::string & filename,
728 int polymerId, int blockId, int directionId)
729 const
730 {
731 UTIL_CHECK(polymerId >= 0);
732 UTIL_CHECK(polymerId < mixture_.nPolymer());
733 Polymer const& polymer = mixture_.polymer(polymerId);
734 UTIL_CHECK(blockId >= 0);
735 UTIL_CHECK(blockId < polymer.nBlock());
736 UTIL_CHECK(directionId >= 0);
737 UTIL_CHECK(directionId <= 1);
738 Propagator const& propagator
739 = polymer.propagator(blockId, directionId);
740 int nslice = propagator.ns();
741
742 // Open file
743 std::ofstream file;
744 fileMaster_.openOutputFile(filename, file);
745
746 // Write header
747 file << "ngrid" << std::endl
748 << " " << domain_.nx() << std::endl
749 << "nslice" << std::endl
750 << " " << nslice << std::endl;
751
752 // Write data
753 bool hasHeader = false;
754 for (int i = 0; i < nslice; ++i) {
755 file << "slice " << i << std::endl;
756 Field const& field = propagator.q(i);
757 fieldIo_.writeField(field, file, hasHeader);
758 }
759 file.close();
760 }
761
762 /*
763 * Write propagators for all blocks of all polymers to files.
764 */
765 void System::writeQAll(std::string const & basename) const
766 {
767 std::string filename;
768 int np, nb, ip, ib, id;
769 np = mixture_.nPolymer();
770 for (ip = 0; ip < np; ++ip) {
771 nb = mixture_.polymer(ip).nBlock();
772 for (ib = 0; ib < nb; ++ib) {
773 for (id = 0; id < 2; ++id) {
774 filename = basename;
775 filename += "_";
776 filename += toString(ip);
777 filename += "_";
778 filename += toString(ib);
779 filename += "_";
780 filename += toString(id);
781 //filename += ".q";
782 writeQ(filename, ip, ib, id);
783 }
784 }
785 }
786 }
787
788} // namespace R1d
789} // namespace Pscf
Interaction model for complex Langevin FTS.
Definition Interaction.h:24
DMatrix< double > const & chi() const
Return the chi matrix by const reference.
void setNMonomer(int nMonomer)
Set the number of monomer types.
int nSolvent() const
Get number of solvent (point particle) species.
int nPolymer() const
Get number of polymer species.
int nMonomer() const
Get number of monomer types.
PolymerT & polymer(int id)
Get a polymer solver object by non-const reference.
SolventT & solvent(int id)
Get a solvent solver object.
double length() const
Sum of the lengths of all blocks in the polymer (thread model).
int nBlock() const
Number of blocks.
PT & propagator(int blockId, int directionId)
Get the propagator for a specific block and direction (non-const).
int nx() const
Get number of spatial grid points, including both endpoints.
double spatialAverage(Field const &f) const
Compute spatial average of a field.
double innerProduct(Field const &f, Field const &g) const
Compute inner product of two real fields.
Command to compute properties of homogeneous reference system.
void output(int mode, std::ostream &out) const
Output comparison to a homogeneous reference system.
void compute(int mode)
Compute properties of a homogeneous reference system.
Factory for subclasses of Iterator.
virtual int solve(bool isContinuation=false)=0
Iterate to solution.
void setDomain(Domain const &domain)
Create an association with the domain and allocate memory.
Descriptor and solver for a block polymer species.
MDE solver for one-direction of one block.
FieldT const & q(int i) const
Return q-field at specified step.
int ns() const
Number of values of s (or slices), including head and tail.
Solver and descriptor for a solvent species in a mixture.
Default Factory for subclasses of Sweep.
DArray< double > Field
Generic Field type.
DArray< Field > & cFields()
Get array of all chemical potential fields.
void compute()
Solve the modified diffusion equation once, without iteration.
void readParam()
Read input parameters from default param file.
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
double pressure() const
Get precomputed pressure x monomer volume kT.
void writeC(std::string const &filename) const
Write concentration fields in symmetrized basis format.
int iterate(bool isContinuation=false)
Iteratively solve a SCFT problem.
void writeQSlice(std::string const &filename, int polymerId, int blockId, int directionId, int segmentId) const
Write slice of a propagator at fixed s in r-grid format.
Interaction & interaction()
Get interaction (i.e., excess free energy) by reference.
void computeFreeEnergy()
Compute free energy density and pressure for current fields.
void writeW(std::string const &filename) const
Write chemical potential fields in symmetrized basis format.
void readCommands()
Read commands from default command file.
Iterator & iterator()
Get the Iterator by reference.
Domain & domain()
Get spatial domain (including grid info) by reference.
void writeQAll(std::string const &basename) const
Write all propagators of all blocks, each to a separate file.
FileMaster & fileMaster()
Get FileMaster by reference.
Field & cField(int monomerId)
Get chemical potential field for a specific monomer type.
void setOptions(int argc, char **argv)
Process command line options.
WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
DArray< WField > & wFields()
Get array of all chemical potential fields.
void writeQ(std::string const &filename, int polymerId, int blockId, int directionId) const
Write one propagator for one block, in r-grid format.
void writeQTail(std::string const &filename, int polymerId, int blockId, int directionId) const
Write the final slice of a propagator in r-grid format.
virtual void readParameters(std::istream &in)
Read input parameters (without opening and closing lines).
void writeBlockC(std::string const &filename) const
Write c-fields for all blocks and solvents in r-grid format.
void sweep()
Sweep in parameter space, solving an SCF problem at each point.
void writeThermo(std::ostream &out) const
Write thermodynamic properties to a file.
void writeParamNoSweep(std::ostream &out) const
Write parameter file to an ostream, omitting any Sweep block.
Mixture & mixture()
Get Mixture by reference.
double size() const
Get the size (number of monomers) in this solvent.
WT mu() const
Get the chemical potential for this species (units kT=1).
Definition Species.h:166
WT phi() const
Get the overall volume fraction for this species.
Definition Species.h:159
void allocate(int capacity)
Allocate the underlying C array.
Definition DArray.h:269
Wrapper for a double precision number, for formatted ostream output.
Definition Dbl.h:40
void openOutputFile(const std::string &filename, std::ofstream &out, std::ios_base::openmode mode=std::ios_base::out) const
Open an output file.
void setParamFileName(const std::string &paramFileName)
Set the parameter file name.
void setOutputPrefix(const std::string &outputPrefix)
Set the output file prefix string.
void setCommandFileName(const std::string &commandFileName)
Set the command file name.
void setInputPrefix(const std::string &inputPrefix)
Set the input file prefix string.
Wrapper for an int, for formatted ostream output.
Definition Int.h:37
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
Two-dimensional array container template (abstract).
Definition Matrix.h:32
static void setEcho(bool echo=true)
Enable or disable echoing for all subclasses of ParamComponent.
Begin & readBegin(std::istream &in, const char *label, bool isRequired=true)
Add and read a class label and opening bracket.
void setClassName(const char *className)
Set class name string.
virtual void writeParam(std::ostream &out) const
Write all parameters to an output stream.
std::string className() const
Get class name string.
void readParamComposite(std::istream &in, ParamComposite &child, bool next=true)
Add and read a required child ParamComposite.
End & readEnd(std::istream &in)
Add and read the closing bracket.
Wrapper for a std::string, for formatted ostream output.
Definition Str.h:37
#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
std::string toString(int n)
Return string representation of an integer.
Definition ioUtil.cpp:52
SCFT with real 1D fields.
PSCF package top-level namespace.
void set(BracketPolicy::Type policy)
Set policy regarding use of bracket delimiters on arrays.