PSCF v1.4.0
rp/solvers/Propagator.tpp
1#ifndef RP_PROPAGATOR_TPP
2#define RP_PROPAGATOR_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 "Propagator.h"
12#include <pscf/mesh/Mesh.h>
13
14namespace Pscf {
15namespace Rp {
16
17 using namespace Util;
18
19 /*
20 * Constructor.
21 */
22 template <int D, class T>
24 : ns_(0),
25 isAllocated_(false),
26 blockPtr_(nullptr),
27 meshPtr_(nullptr)
28 {}
29
30 /*
31 * Destructor.
32 */
33 template <int D, class T>
36
37 /*
38 * Allocate memory used by this propagator.
39 */
40 template <int D, class T>
42 {
44 ns_ = ns;
45 meshPtr_ = &mesh;
46 }
47
48 /*
49 * Reallocate memory used by this propagator using new ns value.
50 */
51 template <int D, class T>
53 {
54 UTIL_CHECK(meshPtr_);
56 UTIL_CHECK(ns_ != ns);
57 ns_ = ns;
58 }
59
60 /*
61 * Compute initial head q-field as a product of tail slices of sources.
62 */
63 template <int D, class T>
65 {
66 UTIL_CHECK(meshPtr_);
68
69 // Reference to head slice of this propagator
70 typename T::RField& qh = qFields_[0];
71
72 // Initialize head slice qh to 1.0 at all grid points
73 VecOp::eqS(qh, 1.0);
74
75 // Pointwise multiply tail q-fields of all source propagators
77 const int ns = PropagatorTmplT::nSource();
78 UTIL_CHECK(ns > 0);
79 for (int is = 0; is < ns; ++is) {
80 if (!source(is).isSolved()) {
81 UTIL_THROW("Source not solved in computeHead");
82 }
83 VecOp::mulEqV(qh, source(is).tail());
84 }
85 }
86
87 }
88
89 /*
90 * Solve the modified diffusion equation for this block.
91 *
92 * This function calls computeHead to compute the head slice as
93 * a product of tail slices from source propagators.
94 */
95 template <int D, class T>
97 {
99 solveMde();
100 }
101
102 /*
103 * Solve the MDE with a specified initial condition at the head.
104 */
105 template <int D, class T>
106 void Propagator<D,T>::solve(typename T::RField const & head)
107 {
108 UTIL_CHECK(meshPtr_);
109 UTIL_CHECK(head.capacity() == mesh().size());
110
111 // Initialize initial (head) slice
113
114 solveMde();
115 }
116
117 /*
118 * Solve the MDE, using stored precomputed head slice (private).
119 */
120 template <int D, class T>
122 {
123 UTIL_CHECK(blockPtr_);
125
127
128 // MDE step loop for thread model
129 for (int iStep = 0; iStep < ns_ - 1; ++iStep) {
130 block().stepThread(qFields_[iStep], qFields_[iStep + 1]);
131 }
132
133 } else
134 if (PolymerModel::isBead()) {
135
136 // Half-bond and bead weight for first bead
139 } else {
140 block().stepHalfBondBead(qFields_[0], qFields_[1]);
141 }
142 block().stepFieldBead(qFields_[1]);
143
144 // MDE step loop for bead model (stop before tail vertex)
145 int iStep;
146 for (iStep = 1; iStep < ns_ - 2; ++iStep) {
147 block().stepBead(qFields_[iStep], qFields_[iStep + 1]);
148 }
149
150 // Half-bond for tail slice, applied to slice for the last bead
152 // Don't compute tail for chain end, since it won't be needed
154 } else {
155 // If not a chain end, apply a half-bond after the last bead
156 block().stepHalfBondBead(qFields_[ns_-2], qFields_[ns_-1]);
157 }
158
159 } else {
160 // This should be impossible
161 UTIL_THROW("Unexpected PolymerModel type");
162 }
163
165 }
166
167 /*
168 * Compute spatial average of product of head and tail of partner.
169 */
170 template <int D, class T>
171 void Propagator<D,T>::computeQ(double & Q) const
172 {
173 // Preconditions
174 UTIL_CHECK(meshPtr_);
177 UTIL_THROW("Propagator is not solved.");
178 }
180 UTIL_THROW("Propagator has no partner set.");
181 }
182 if (!partner().isSolved()) {
183 UTIL_THROW("Partner propagator is not solved");
184 }
186
187 Q = 0.0;
189 // Compute average of q for last bead of partner
190 Q = Reduce::sum(partner().q(ns_-2));
191 } else {
192 // Compute average product of head slice and partner tail slice
194 }
195 Q /= double(mesh().size());
196 }
197
198} // namespace Rp
199} // namespace Pscf
200#endif
Description of a regular grid of points in a periodic domain.
Definition Mesh.h:61
Mesh< D > const & mesh() const
Return the associated Mesh object by const reference.
void computeQ(double &Q) const
Compute and return partition function for the polymer molecule.
bool isAllocated() const
Has memory been allocated for this propagator?
int ns() const
Get the number of values of s (or slices), including head and tail.
const T::RField & head() const
Return q-field at the initial (head) vertex.
T::Block const & block() const
Get the associated Block object by const reference.
void computeHead()
Compute initial q-field at the head vertex.
virtual void reallocate(int ns)
Reallocate memory used by this propagator.
void solve()
Solve the modified diffusion equation (MDE) for this block.
int ns_
Number of slices, including head and tail slices.
void solveMde()
Compute solution of modified diffusion equation (MDE).
const typename T::Propagator & source(int id) const
Get a source propagator.
bool isAllocated_
Is this propagator allocated?
const typename T::Propagator & partner() const
Get partner propagator.
const T::RField & tail() const
Return q-field at the terminal (tail) vertex.
const T::RField & q(int i) const
Return q-field at a specified step.
DArray< typename T::RField > qFields_
Array of propagator slices at different contour variable values.
virtual void allocate(int ns, const Mesh< D > &mesh)
Allocate memory used by this propagator.
#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
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute Euclidean inner product of two real arrays .
Definition Reduce.cpp:117
double sum(Array< double > const &in)
Compute sum of array elements (real).
Definition Reduce.cpp:20
void mulEqV(Array< double > &a, Array< double > const &b)
Vector-vector in-place multiplication, a[i] *= b[i] (real).
Definition VecOp.cpp:252
void eqV(Array< double > &a, Array< double > const &b, const int beginIdA, const int beginIdB, const int n)
Vector assignment, a[i] = b[i] (real, slice).
Definition VecOp.cpp:21
void eqS(Array< double > &a, double b)
Vector assignment, a[i] = b (real).
Definition VecOp.cpp:50
bool isThread()
Is the thread model in use ?
bool isBead()
Is the bead model in use ?
Class templates for real-valued periodic fields.
PSCF package top-level namespace.