PSCF v1.1
pspc/solvers/Propagator.tpp
1#ifndef PSPC_PROPAGATOR_TPP
2#define PSPC_PROPAGATOR_TPP
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 "Propagator.h"
12#include "Block.h"
13
14#include <pscf/mesh/Mesh.h>
15
16namespace Pscf {
17namespace Pspc {
18
19 using namespace Util;
20
21 /*
22 * Constructor.
23 */
24 template <int D>
26 : blockPtr_(0),
27 meshPtr_(0),
28 ns_(0),
29 isAllocated_(false)
30 {}
31
32 /*
33 * Destructor.
34 */
35 template <int D>
37 {}
38
39 /*
40 * Allocate memory used by this propagator.
41 */
42 template <int D>
43 void Propagator<D>::allocate(int ns, const Mesh<D>& mesh)
44 {
45 UTIL_CHECK(!isAllocated_);
46 ns_ = ns;
47 meshPtr_ = &mesh;
48
49 qFields_.allocate(ns);
50 for (int i = 0; i < ns; ++i) {
51 qFields_[i].allocate(mesh.dimensions());
52 }
53 isAllocated_ = true;
54 }
55
56 /*
57 * Reallocate memory used by this propagator using new ns value.
58 */
59 template <int D>
61 {
62 UTIL_CHECK(isAllocated_);
63 UTIL_CHECK(ns_ != ns);
64 ns_ = ns;
65
66 // Deallocate all memory previously used by this propagator.
67 qFields_.deallocate();
68
69 // NOTE: The qFields_ container is a DArray<QField>, where QField
70 // is a typedef for DFields<D>. The DArray::deallocate() function
71 // calls "delete [] ptr", where ptr is a pointer to the underlying
72 // C array. The C++ delete [] command calls the destructor for
73 // each element in an array before deleting the array itself.
74 // The RField<D> destructor deletes the the double* array that
75 // stores the field associated with each slice of the propagator.
76
77 // Allocate new memory for qFields_ using new value of ns
78 qFields_.allocate(ns);
79 for (int i = 0; i < ns; ++i) {
80 qFields_[i].allocate(meshPtr_->dimensions());
81 }
82 }
83
84 /*
85 * Compute initial head QField from final tail QFields of sources.
86 */
87 template <int D>
89 {
90
91 // Reference to head of this propagator
92 QField& qh = qFields_[0];
93
94 // Initialize qh field to 1.0 at all grid points
95 int ix;
96 int nx = meshPtr_->size();
97 for (ix = 0; ix < nx; ++ix) {
98 qh[ix] = 1.0;
99 }
100
101 // Pointwise multiply tail QFields of all sources
102 for (int is = 0; is < nSource(); ++is) {
103 if (!source(is).isSolved()) {
104 UTIL_THROW("Source not solved in computeHead");
105 }
106 QField const& qt = source(is).tail();
107 for (ix = 0; ix < nx; ++ix) {
108 qh[ix] *= qt[ix];
109 }
110 }
111 }
112
113 /*
114 * Solve the modified diffusion equation for this block.
115 */
116 template <int D>
118 {
119 UTIL_CHECK(isAllocated());
120 computeHead();
121 for (int iStep = 0; iStep < ns_ - 1; ++iStep) {
122 block().step(qFields_[iStep], qFields_[iStep + 1]);
123 }
124 setIsSolved(true);
125 }
126
127 /*
128 * Solve the modified diffusion equation with a specified initial condition.
129 */
130 template <int D>
131 void Propagator<D>::solve(QField const & head)
132 {
133 int nx = meshPtr_->size();
134 UTIL_CHECK(head.capacity() == nx);
135
136 // Initialize initial (head) field
137 QField& qh = qFields_[0];
138 for (int i = 0; i < nx; ++i) {
139 qh[i] = head[i];
140 }
141
142 // Setup solver and solve
143 for (int iStep = 0; iStep < ns_ - 1; ++iStep) {
144 block().step(qFields_[iStep], qFields_[iStep + 1]);
145 }
146 setIsSolved(true);
147 }
148
149 /*
150 * Compute spatial average of product of head and tail of partner.
151 */
152 template <int D>
154 {
155 // Preconditions
156 if (!isSolved()) {
157 UTIL_THROW("Propagator is not solved.");
158 }
159 if (!hasPartner()) {
160 UTIL_THROW("Propagator has no partner set.");
161 }
162 if (!partner().isSolved()) {
163 UTIL_THROW("Partner propagator is not solved");
164 }
165 QField const& qh = head();
166 QField const& qt = partner().tail();
167 int nx = meshPtr_->size();
168 UTIL_CHECK(qt.capacity() == nx);
169 UTIL_CHECK(qh.capacity() == nx);
170
171 // Take inner product of head and partner tail fields
172 double Q = 0;
173 for (int i =0; i < nx; ++i) {
174 Q += qh[i]*qt[i];
175 }
176 Q /= double(nx);
177 return Q;
178 }
179
180}
181}
182#endif
Description of a regular grid of points in a periodic domain.
Definition: Mesh.h:61
IntVec< D > dimensions() const
Get an IntVec<D> of the grid dimensions.
Definition: Mesh.h:217
void computeHead()
Compute initial QField at head from tail QFields of sources.
void solve()
Solve the modified diffusion equation (MDE) for this block.
void reallocate(int ns)
Reallocate memory used by this propagator.
double computeQ()
Compute and return partition function for the polymer.
void allocate(int ns, const Mesh< D > &mesh)
Allocate memory used by this propagator.
Field of real double precision values on an FFT mesh.
Definition: RField.h:29
int capacity() const
Return allocated size.
Definition: Array.h:159
#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:51
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1