PSCF v1.3.3
r1d/solvers/Mixture.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 "Mixture.h"
9#include "Polymer.h"
10#include "Solvent.h"
11#include "Block.h"
12#include "Propagator.h"
13#include <r1d/domain/Domain.h>
14#include <pscf/solvers/MixtureTmpl.tpp>
15
16#include <cmath>
17
18// Explicit instantiation of base class
19namespace Pscf {
21}
22
23namespace Pscf {
24namespace R1d {
25
26 /*
27 * Constructor.
28 */
30 : ds_(-1.0),
31 domainPtr_(0)
32 { setClassName("Mixture"); }
33
34 /*
35 * Destructor.
36 */
39
40 /*
41 * Read parameter file block.
42 */
43 void Mixture::readParameters(std::istream& in)
44 {
46
47 // Read optimal contour step size
48 read(in, "ds", ds_);
49
50 UTIL_CHECK(nMonomer() > 0);
52 UTIL_CHECK(ds_ > 0);
53 }
54
55 /*
56 * Create association with domain, set spatial discretization.
57 */
58 void Mixture::setDomain(Domain const& domain)
59 {
60 UTIL_CHECK(nMonomer() > 0);
62 UTIL_CHECK(ds_ > 0);
63
64 domainPtr_ = &domain;
65
66 // Process polymers - set discretization for all blocks
67 if (nPolymer() > 0) {
68 int i, j;
69 for (i = 0; i < nPolymer(); ++i) {
70 for (j = 0; j < polymer(i).nBlock(); ++j) {
71 polymer(i).block(j).setDiscretization(domain, ds_);
72 }
73 }
74 }
75
76 // Process solvents - set discretization for all solvents
77 if (nSolvent() > 0) {
78 for (int i = 0; i < nSolvent(); ++i) {
79 solvent(i).setDiscretization(domain);
80 }
81 }
82
83 }
84
85 /*
86 * Reset statistical segment length for one monomer type.
87 */
88 void Mixture::setKuhn(int monomerId, double kuhn)
89 {
90 // Set new Kuhn length for relevant Monomer object
91 monomer(monomerId).setKuhn(kuhn);
92
93 // Update kuhn length for all blocks of this monomer type
94 for (int i = 0; i < nPolymer(); ++i) {
95 for (int j = 0; j < polymer(i).nBlock(); ++j) {
96 if (monomerId == polymer(i).block(j).monomerId()) {
97 polymer(i).block(j).setKuhn(kuhn);
98 }
99 }
100 }
101 }
102
103 /*
104 * Compute concentrations (but not total free energy).
105 */
108 {
109 UTIL_CHECK(domainPtr_);
110 UTIL_CHECK(domain().nx() > 0);
111 UTIL_CHECK(nMonomer() > 0);
112 UTIL_CHECK(nPolymer() + nSolvent() > 0);
113 UTIL_CHECK(wFields.capacity() == nMonomer());
114 UTIL_CHECK(cFields.capacity() == nMonomer());
115
116 int nx = domain().nx();
117 int nm = nMonomer();
118 int i, j, k;
119
120 // Clear all monomer concentration fields
121 for (i = 0; i < nm; ++i) {
122 UTIL_CHECK(cFields[i].capacity() == nx);
123 UTIL_CHECK(wFields[i].capacity() == nx);
124 for (j = 0; j < nx; ++j) {
125 cFields[i][j] = 0.0;
126 }
127 }
128
129 // Process polymer species
130 if (nPolymer() > 0) {
131
132 for (i = 0; i < nPolymer(); ++i) {
133
134 // Solve MDE for all blocks in polymer
135 polymer(i).compute(wFields);
136
137 // Accumulate monomer concentrations
138 for (j = 0; j < polymer(i).nBlock(); ++j) {
139 int monomerId = polymer(i).block(j).monomerId();
140 UTIL_CHECK(monomerId >= 0);
141 UTIL_CHECK(monomerId < nm);
142 FieldT& monomerField = cFields[monomerId];
143 FieldT const & blockField = polymer(i).block(j).cField();
144 for (k = 0; k < nx; ++k) {
145 monomerField[k] += blockField[k];
146 }
147 }
148
149 }
150
151 }
152
153 // Process solvent species
154 if (nSolvent() > 0) {
155 for (i = 0; i < nSolvent(); ++i) {
156
157 int monomerId = solvent(i).monomerId();
158 UTIL_CHECK(monomerId >= 0);
159 UTIL_CHECK(monomerId < nm);
160
161 // Compute solvent concentration and q
162 solvent(i).compute(wFields[monomerId]);
163
164 // Add to monomer concentrations
165 FieldT& monomerField = cFields[monomerId];
166 FieldT const & solventField = solvent(i).cField();
167 for (k = 0; k < nx; ++k) {
168 monomerField[k] += solventField[k];
169 }
170
171 }
172 }
173
174 }
175
176} // namespace R1d
177} // namespace Pscf
int nPolymer() const
Get number of polymer species.
Monomer const & monomer(int id) const
Get a Monomer type descriptor by const reference.
int nMonomer() const
Get number of monomer types.
int nSolvent() const
Get number of solvent (point particle) species.
Solvers for a mixture of polymer and solvent species.
Definition MixtureTmpl.h:27
virtual void readParameters(std::istream &in)
Read parameters from file and initialize.
void setKuhn(double kuhn)
Set statistical segment length.
Definition Monomer.h:139
One-dimensional spatial domain and discretization grid.
void setKuhn(int monomerId, double kuhn)
Reset statistical segment length for one monomer type.
ScalarParam< Type > & read(std::istream &in, const char *label, Type &value)
Add and read a new required ScalarParam < Type > object.
void compute(DArray< FieldT > const &wFields, DArray< FieldT > &cFields)
Compute concentrations.
void setClassName(const char *className)
Set class name string.
void readParameters(std::istream &in)
Read all parameters and initialize.
DArray< double > FieldT
Field type.
void setDomain(Domain const &domain)
Create an association with the domain and allocate memory.
int capacity() const
Return allocated size.
Definition Array.h:159
Dynamically allocatable contiguous array template.
Definition DArray.h:32
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
PSCF package top-level namespace.