PSCF v1.4.0
PolymerTmpl.tpp
1#ifndef PSCF_POLYMER_TMPL_TPP
2#define PSCF_POLYMER_TMPL_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 "PolymerTmpl.h"
12#include <pscf/math/arithmetic.h>
13#include <util/containers/Pair.h>
14
15namespace Pscf {
16
17 class Edge;
18 using namespace Util;
19
20 /*
21 * Constructor.
22 */
23 template <class BT, class PT, typename WT>
28
29 /*
30 * Allocate blocks array.
31 */
32 template <class BT, class PT, typename WT>
35
36 /*
37 * Read blocks array from parameter file.
38 */
39 template <class BT, class PT, typename WT>
40 void PolymerTmpl<BT,PT,WT>::readBlocks(std::istream& in)
41 {
42 const int nBlock = PolymerSpeciesT::nBlock();
43 ParamComposite::readDArray<BT>(in, "blocks", blocks_, nBlock);
44 }
45
46 /*
47 * Read parameter file block.
48 */
49 template <class BT, class PT, typename WT>
51 {
52
53 // Call PoymerSpecies base class member function
54 // Initializes PolymerSpecies, and Edge and Vertex components
56
57 // The remainder of this function sets and validates immutable
58 // information about graph topology that is stored by propagators.
59
60 PT * propagatorPtr = nullptr;
61 PT const * sourcePtr = nullptr;
62 Vertex const * headPtr = nullptr;
63 Vertex const * tailPtr = nullptr;
64 Pair<int> propId;
65 int blockId, forwardId, reverseId, headId, tailId, i;
66 const int nBlock = PolymerSpeciesT::nBlock();
67 bool isHeadEnd, isTailEnd;
68
69 // Set sources and end flags for all propagators
70 for (blockId = 0; blockId < nBlock; ++blockId) {
71 for (forwardId = 0; forwardId < 2; ++forwardId) {
72
73 propagatorPtr = &block(blockId).propagator(forwardId);
75 // Identify head and tail vertices
76 if (forwardId == 0) {
77 reverseId = 1;
78 } else {
79 reverseId = 0;
80 }
81 headId = block(blockId).vertexId(forwardId);
82 tailId = block(blockId).vertexId(reverseId);
83 headPtr = &PolymerSpeciesT::vertex(headId); // head vertex
84 tailPtr = &PolymerSpeciesT::vertex(tailId); // tail vertex
85
86 // Add pointers to source propagators
87 for (i = 0; i < headPtr->size(); ++i) {
88 propId = headPtr->inPropagatorId(i);
89 if (propId[0] == blockId) {
90 UTIL_CHECK(propId[1] != forwardId);
91 } else {
92 sourcePtr =
93 &block(propId[0]).propagator(propId[1]);
94 propagatorPtr->addSource(*sourcePtr);
95 }
96 }
97
98 // Set vertex end flags
99 isHeadEnd = (headPtr->size() == 1) ? true : false;
100 isTailEnd = (tailPtr->size() == 1) ? true : false;
101 propagatorPtr->setEndFlags(isHeadEnd, isTailEnd);
102
103 } // end loop over forwardId (propagator direction id)
104 } // end loop over blockId
105
106 // Check validity - throw Exception if error detected
107 isValid();
108 }
109
110 /*
111 * Checks validity of propagator data set in readParameters.
112 *
113 * This function only checks validity of propagator source and end flag
114 * member data that is set in PolymerTmpl<BT,PT,WT>::readParameters. It
115 * does not check validity of members of PolymerSpecies, Edge, and Vertex
116 * that are set and validated within the PolymerSpecies::readParameters
117 * base class member function.
118 */
119 template <class BT, class PT, typename WT>
120 void PolymerTmpl<BT,PT,WT>::isValid()
121 {
122 Vertex const * v0Ptr = nullptr;
123 Vertex const * v1Ptr = nullptr;
124 PT const * p0Ptr = nullptr;
125 PT const * p1Ptr = nullptr;
126 int bId, v0Id, v1Id;
127 const int nVertex = PolymerSpeciesT::nVertex();
128 const int nBlock = PolymerSpeciesT::nBlock();
129
130 // Loop over blocks
131 for (bId = 0; bId < nBlock; ++bId) {
132 v0Id = block(bId).vertexId(0);
133 v1Id = block(bId).vertexId(1);
134 UTIL_CHECK(v0Id >= 0 && v0Id < nVertex);
135 UTIL_CHECK(v1Id >= 0 && v1Id < nVertex);
136 UTIL_CHECK(v0Id != v1Id);
137 v0Ptr = &PolymerSpeciesT::vertex(v0Id);
138 v1Ptr = &PolymerSpeciesT::vertex(v1Id);
139 p0Ptr = &(block(bId).propagator(0));
140 p1Ptr = &(block(bId).propagator(1));
141 UTIL_CHECK(v0Ptr->size() >= 1);
142 UTIL_CHECK(v1Ptr->size() >= 1);
143 UTIL_CHECK(p0Ptr->nSource() == (v0Ptr->size() - 1));
144 UTIL_CHECK(p1Ptr->nSource() == (v1Ptr->size() - 1));
145 UTIL_CHECK(p0Ptr->isHeadEnd() == p1Ptr->isTailEnd());
146 UTIL_CHECK(p0Ptr->isTailEnd() == p1Ptr->isHeadEnd());
147 UTIL_CHECK(p0Ptr->isHeadEnd() == (v0Ptr->size() == 1));
148 UTIL_CHECK(p1Ptr->isHeadEnd() == (v1Ptr->size() == 1));
149 }
150
151 }
152
153 /*
154 * Solve the MDE for all blocks of this polymer.
155 */
156 template <class BT, class PT, typename WT>
158 {
160
161 // Clear all propagators
162 for (int j = 0; j < nPropagator; ++j) {
163 propagator(j).setIsSolved(false);
164 }
165
166 // Solve modified diffusion equation for all propagators in
167 // the order specified by function makePlan.
168 for (int j = 0; j < nPropagator; ++j) {
169 UTIL_CHECK(propagator(j).isReady());
170 propagator(j).solve();
171 }
172
173 // Compute molecular partition function Q
174 WT Q;
175 block(0).propagator(0).computeQ(Q);
176
177 // The PT::computeQ function returns an overall spatial average.
178 // Correct for possible partial occupation of the unit cell.
179 divEq(Q, phiTot);
180
181 // Set q and compute phi or mu, depending on the ensemble
182 SpeciesT::setQ(Q);
183
184 }
185
186 /*
187 * Get a propagator, indexed by block and direction ids (non-const).
188 */
189 template <class BT, class PT, typename WT>
190 PT& PolymerTmpl<BT,PT,WT>::propagator(int blockId, int directionId)
191 { return block(blockId).propagator(directionId); }
192
193 /*
194 * Get a propagator, indexed by block and direction ids (const).
195 */
196 template <class BT, class PT, typename WT>
197 PT const &
198 PolymerTmpl<BT,PT,WT>::propagator(int blockId, int directionId) const
199 { return block(blockId).propagator(directionId); }
200
201 /*
202 * Get a propagator, indexed in order of computation.
203 */
204 template <class BT, class PT, typename WT>
206 {
208 return propagator(propId[0], propId[1]);
210
211}
212#endif
Descriptor for a block within a block polymer.
Definition Edge.h:59
virtual void readParameters(std::istream &in)
const Vertex & vertex(int id) const
Pair< int > const & propagatorId(int id) const
PolymerTmpl()
Constructor.
Propagator & propagator(int blockId, int directionId)
PolymerSpecies< WT > PolymerSpeciesT
Direct (parent) base class.
void readParameters(std::istream &in) override
Read and initialize.
BT & block(int id)
Get a specified Block (solver and descriptor).
virtual void solve(double phiTot=1.0)
Solve modified diffusion equation for all propagators.
void allocateBlocks() final
Allocate array of Block objects.
void readBlocks(std::istream &in) final
Read array of data for blocks from parameter file.
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
An array of exactly 2 objects.
Definition Pair.h:24
DArrayParam< Type > & readDArray(std::istream &in, const char *label, DArray< Type > &array, int n)
Add and read a required DArray < Type > parameter.
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
void divEq(fftw_complex &a, fftw_complex const &b)
In-place division of fftw_complex numbers, a /= b.
PSCF package top-level namespace.