PSCF v1.1
pspg/solvers/Propagator.tpp
1#ifndef PSPG_PROPAGATOR_TPP
2#define PSPG_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#include <thrust/reduce.h>
14#include "device_launch_parameters.h"
15#include <cuda.h>
16//#include <device_functions.h>
17#include <thrust/count.h>
18#include <pspg/math/GpuResources.h>
19#include <pscf/mesh/Mesh.h>
20//#include <Windows.h>
21
22namespace Pscf {
23namespace Pspg {
24
25 using namespace Util;
26
27 /*
28 * Constructor.
29 */
30 template <int D>
32 : blockPtr_(0),
33 meshPtr_(0),
34 ns_(0),
35 temp_(0),
36 isAllocated_(false)
37 {
38 }
39
40 /*
41 * Destructor.
42 */
43 template <int D>
45 {
46 if (temp_) {
47 delete[] temp_;
48 cudaFree(d_temp_);
49 }
50 }
51
52 template <int D>
53 void Propagator<D>::allocate(int ns, const Mesh<D>& mesh)
54 {
55 ns_ = ns;
56 meshPtr_ = &mesh;
57
59
60 gpuErrchk(cudaMalloc((void**)&qFields_d, sizeof(cudaReal)* mesh.size() *
61 ns));
62 gpuErrchk(cudaMalloc((void**)&d_temp_, ThreadGrid::nBlocks() * sizeof(cudaReal)));
63 temp_ = new cudaReal[ThreadGrid::nBlocks()];
64 isAllocated_ = true;
65 }
66
67 /*
68 * Compute initial head QField from final tail QFields of sources.
69 */
70 template <int D>
72 {
73
74 // Reference to head of this propagator
75 //QField& qh = qFields_[0];
76
77 // Initialize qh field to 1.0 at all grid points
78 int nx = meshPtr_->size();
79
80 // GPU resources
81 int nBlocks, nThreads;
82 ThreadGrid::setThreadsLogical(nx, nBlocks, nThreads);
83
84 //qh[ix] = 1.0;
85 //qFields_d points to the first element in gpu memory
86 assignUniformReal<<<nBlocks, nThreads>>>(qFields_d, 1.0, nx);
87
88
89 // Pointwise multiply tail QFields of all sources
90 // this could be slow with many sources. Should launch 1 kernel for the whole
91 // function of computeHead
92 const cudaReal* qt;
93 for (int is = 0; is < nSource(); ++is) {
94 if (!source(is).isSolved()) {
95 UTIL_THROW("Source not solved in computeHead");
96 }
97 //need to modify tail to give the total_size - mesh_size pointer
98 qt = source(is).tail();
99
100 //qh[ix] *= qt[ix];
101 inPlacePointwiseMul<<<nBlocks, nThreads>>>(qFields_d, qt, nx);
102 }
103 }
104
105 /*
106 * Solve the modified diffusion equation for this block.
107 */
108 template <int D>
110 {
111 UTIL_CHECK(isAllocated());
112 computeHead();
113 // Setup solver and solve
114 block().setupFFT();
115 //cudaReal* qf;
116 //qf = new cudaReal;
117
118 int currentIdx;
119 for (int iStep = 0; iStep < ns_ - 1; ++iStep) {
120 currentIdx = iStep * meshPtr_->size();
121 //block has to learn to deal with the cudaReal
122 block().step(qFields_d + currentIdx, qFields_d + currentIdx + meshPtr_->size());
123 }
124 //delete qf;
125 setIsSolved(true);
126 }
127
128 /*
129 * Solve the modified diffusion equation with specified initial field.
130 */
131 template <int D>
132 void Propagator<D>::solve(const cudaReal * head)
133 {
134 int nx = meshPtr_->size();
135
136 // GPU resources
137 int nBlocks, nThreads;
138 ThreadGrid::setThreadsLogical(nx, nBlocks, nThreads);
139
140 // Initialize initial (head) field
141 cudaReal* qh = qFields_d;
142 // qh[i] = head[i];
143 assignReal<<<nBlocks, nThreads>>>(qh, head, nx);
144
145 // Setup solver and solve
146 int currentIdx;
147 for (int iStep = 0; iStep < ns_ - 1; ++iStep) {
148 currentIdx = iStep * nx;
149 block().step(qFields_d + currentIdx, qFields_d + currentIdx + nx);
150 }
151 setIsSolved(true);
152 }
153
154 /*
155 * Integrate to calculate monomer concentration for this block
156 */
157 template <int D>
159 {
160 // Preconditions
161 if (!isSolved()) {
162 UTIL_THROW("Propagator is not solved.");
163 }
164 if (!hasPartner()) {
165 UTIL_THROW("Propagator has no partner set.");
166 }
167 if (!partner().isSolved()) {
168 UTIL_THROW("Partner propagator is not solved");
169 }
170 const cudaReal * qh = head();
171 const cudaReal * qt = partner().tail();
172 int nx = meshPtr_->size();
173
174 // Take inner product of head and partner tail fields
175 // cannot reduce assuming one propagator, qh == 1
176 // polymers are divided into blocks midway through
177 double Q = 0;
178
179 Q = gpuInnerProduct(qh, qt, nx);
180 Q /= double(nx);
181 return Q;
182 }
183
184}
185}
186#endif
Description of a regular grid of points in a periodic domain.
Definition: Mesh.h:61
int size() const
Get total number of grid points.
Definition: Mesh.h:229
double computeQ()
Compute and return partition function for the molecule.
void solve()
Solve the modified diffusion equation (MDE) for this block.
void computeHead()
Compute initial QField at head from tail QFields of sources.
void allocate(int ns, const Mesh< D > &mesh)
Associate this propagator with a block.
#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
int nBlocks()
Get the current number of blocks for execution.
Definition: ThreadGrid.cu:170
void setThreadsLogical(int nThreadsLogical)
Set the total number of threads required for execution.
Definition: ThreadGrid.cu:80
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1