PSCF v1.2
PolymerTmpl.h
1#ifndef PSCF_POLYMER_TMPL_H
2#define PSCF_POLYMER_TMPL_H
3
4/*
5* PSCF - Polymer Self-Consistent Field Theory
6*
7* Copyright 2016 - 2022, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include <pscf/chem/PolymerSpecies.h> // base class
12#include <util/containers/DArray.h> // member template
13
14// Classes used in implementation
15#include <pscf/chem/Vertex.h>
16#include <pscf/chem/PolymerType.h>
17#include <util/containers/Pair.h>
18
19#include <cmath>
20
21namespace Pscf
22{
23
24 class Edge;
25 using namespace Util;
26
45 template <class Block>
47 {
48
49 public:
50
51 // Modified diffusion equation solver for one block.
52 typedef typename Block::Propagator Propagator;
53
54 // Monomer concentration field.
55 typedef typename Propagator::CField CField;
56
57 // Chemical potential field.
58 typedef typename Propagator::WField WField;
59
64
69
75 virtual void readParameters(std::istream& in);
76
103 virtual void solve(double phiTot = 1.0);
104
107
117 virtual Edge& edge(int id);
118
124 virtual Edge const& edge(int id) const;
125
131 Block& block(int id);
132
138 Block const& block(int id) const ;
139
151 Propagator& propagator(int blockId, int directionId);
152
159 Propagator const & propagator(int blockId, int directionId) const;
160
168 Propagator& propagator(int id);
169
171
172 // Inherited public members
182
183 using Species::phi;
184 using Species::mu;
185 using Species::q;
186 using Species::ensemble;
187
188 protected:
189
193 virtual void allocateBlocks();
194
200 virtual void readBlocks(std::istream& in);
201
202 private:
203
205 DArray<Block> blocks_;
206
207 };
208
209 /*
210 * Get a specified Edge (block descriptor) by non-const reference.
211 */
212 template <class Block>
214 { return blocks_[id]; }
215
216 /*
217 * Get a specified Edge (block descriptor) by const reference.
218 */
219 template <class Block>
220 inline
221 Edge const & PolymerTmpl<Block>::edge(int id) const
222 { return blocks_[id]; }
223
224 /*
225 * Get a specified Block solver by non-const reference.
226 */
227 template <class Block>
228 inline
230 { return blocks_[id]; }
231
232 /*
233 * Get a specified Block solver by const reference.
234 */
235 template <class Block>
236 inline
237 Block const & PolymerTmpl<Block>::block(int id) const
238 { return blocks_[id]; }
239
240 /*
241 * Get a Propagator indexed by block and direction (non-const).
242 */
243 template <class Block>
244 inline
245 typename Block::Propagator&
246 PolymerTmpl<Block>::propagator(int blockId, int directionId)
247 { return block(blockId).propagator(directionId); }
248
249 /*
250 * Get a Propagator indexed by block and direction (const).
251 */
252 template <class Block>
253 inline
254 typename Block::Propagator const &
255 PolymerTmpl<Block>::propagator(int blockId, int directionId) const
256 { return block(blockId).propagator(directionId); }
257
258 /*
259 * Get a propagator indexed in order of computation.
260 */
261 template <class Block>
262 inline
263 typename Block::Propagator& PolymerTmpl<Block>::propagator(int id)
264 {
265 Pair<int> propId = propagatorId(id);
266 return propagator(propId[0], propId[1]);
267 }
268
269 // Non-inline functions
270
271 /*
272 * Constructor.
273 */
274 template <class Block>
276 : PolymerSpecies(),
277 blocks_()
278 { setClassName("PolymerTmpl"); }
279
280 /*
281 * Destructor.
282 */
283 template <class Block>
286
287 template <class Block>
289 { blocks_.allocate(nBlock()); }
290
291 template <class Block>
292 void PolymerTmpl<Block>::readBlocks(std::istream& in)
293 { readDArray<Block>(in, "blocks", blocks_, nBlock()); }
294
295 template <class Block>
297 {
298
300
301 // Set sources for all propagators
302 Vertex const * vertexPtr = 0;
303 Propagator const * sourcePtr = 0;
304 Propagator * propagatorPtr = 0;
305 Pair<int> propagatorId;
306 int blockId, directionId, vertexId, i;
307 for (blockId = 0; blockId < nBlock(); ++blockId) {
308 // Add sources
309 for (directionId = 0; directionId < 2; ++directionId) {
310 vertexId = block(blockId).vertexId(directionId);
311 vertexPtr = &vertex(vertexId);
312 propagatorPtr = &block(blockId).propagator(directionId);
313 for (i = 0; i < vertexPtr->size(); ++i) {
314 propagatorId = vertexPtr->inPropagatorId(i);
315 if (propagatorId[0] == blockId) {
316 UTIL_CHECK(propagatorId[1] != directionId);
317 } else {
318 sourcePtr =
319 &block(propagatorId[0]).propagator(propagatorId[1]);
320 propagatorPtr->addSource(*sourcePtr);
321 }
322 }
323 }
324
325 }
326
327 }
328
329 /*
330 * Compute a solution to the MDE and block concentrations.
331 */
332 template <class Block>
333 void PolymerTmpl<Block>::solve(double phiTot)
334 {
335
336 // Clear all propagators
337 for (int j = 0; j < nPropagator(); ++j) {
338 propagator(j).setIsSolved(false);
339 }
340
341 // Solve modified diffusion equation for all propagators in
342 // the order specified by function makePlan.
343 for (int j = 0; j < nPropagator(); ++j) {
344 UTIL_CHECK(propagator(j).isReady());
345 propagator(j).solve();
346 }
347
348 // Compute molecular partition function q_
349 q_ = block(0).propagator(0).computeQ();
350
351 // The Propagator::computeQ function returns a spatial average.
352 // Correct for partial occupation of the unit cell.
353 q_ = q_/phiTot;
354
355 // Compute mu_ or phi_, depending on ensemble
356 if (ensemble() == Species::Closed) {
357 mu_ = log(phi_/q_);
358 } else
359 if (ensemble() == Species::Open) {
360 phi_ = exp(mu_)*q_;
361 }
362
363 // Compute block concentration fields
364 double prefactor = phi_ / ( q_ * length() );
365 for (int i = 0; i < nBlock(); ++i) {
366 block(i).computeConcentration(prefactor);
367 }
368
369 }
370
371}
372#endif
Descriptor for a block within an acyclic block polymer.
Definition Edge.h:50
Descriptor for a linear or acyclic branched block polymer.
const Vertex & vertex(int id) const
Get a specified Vertex by const reference.
Pair< int > const & path(int is, int it) const
Get an id for a propagator from one vertex towards a target.
int nVertex() const
Number of vertices (junctions and chain ends).
virtual Edge & edge(int id)=0
Get a specified Edge (block descriptor) by non-const reference.
virtual void readParameters(std::istream &in)
Read parameters and initialize.
int nPropagator() const
Number of propagators (2*nBlock).
int nBlock() const
Number of blocks.
double length() const
Sum of the lengths of all blocks in the polymer.
Pair< int > const & propagatorId(int id) const
Get a propagator identifier, indexed by order of computation.
PolymerType::Enum type() const
Get Polymer type (Branched or Linear)
Descriptor and MDE solver for an acyclic branched block polymer.
Definition PolymerTmpl.h:47
Block const & block(int id) const
Get a specified Block (solver and descriptor) by const reference.
virtual void readParameters(std::istream &in)
Read and initialize.
virtual Edge & edge(int id)
Get a specified Edge (block descriptor) by non-const reference.
Block & block(int id)
Get a specified Block (block solver and descriptor)
PolymerTmpl()
Constructor.
Propagator & propagator(int blockId, int directionId)
Get the Propagator for a specific block and direction (non-const).
Propagator const & propagator(int blockId, int directionId) const
Get the Propagator for a specific block and direction (const).
virtual Edge const & edge(int id) const
Get a specified Edge (block descriptor) by const reference.
virtual void allocateBlocks()
Allocate array of Block objects.
virtual void readBlocks(std::istream &in)
Read array of data for blocks from parameter file.
~PolymerTmpl()
Destructor.
Propagator & propagator(int id)
Get propagator indexed in order of computation (non-const).
virtual void solve(double phiTot=1.0)
Solve modified diffusion equation.
double phi() const
Get the overall volume fraction for this species.
Definition Species.h:90
Ensemble ensemble()
Get the statistical ensemble for this species (open or closed).
Definition Species.h:102
double mu() const
Get the chemical potential for this species (units kT=1).
Definition Species.h:96
double q() const
Get the molecular partition function for this species.
A junction or chain end in a block polymer.
Definition Vertex.h:31
int size() const
Get the number of attached blocks.
Definition Vertex.h:110
Pair< int > const & inPropagatorId(int i) const
Get the block and direction of an incoming propagator.
Definition Vertex.h:114
Dynamically allocatable contiguous array template.
An array of exactly 2 objects.
Definition Pair.h:24
void setClassName(const char *className)
Set class name string.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
PSCF package top-level namespace.
Definition param_pc.dox:1
Utility classes for scientific computation.