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