12#include "Propagator.h"
14#include <prdc/cpu/WaveList.h>
15#include <prdc/cpu/FFT.h>
16#include <pscf/cpu/complex.h>
17#include <prdc/crystal/UnitCell.h>
18#include <prdc/crystal/shiftToMinimum.h>
20#include <pscf/chem/Edge.h>
21#include <pscf/mesh/Mesh.h>
22#include <pscf/mesh/MeshIterator.h>
23#include <pscf/math/IntVec.h>
24#include <pscf/solvers/BlockTmpl.tpp>
26#include <util/containers/DMatrix.h>
27#include <util/containers/DArray.h>
28#include <util/containers/FSArray.h>
47 unitCellPtr_(nullptr),
48 waveListPtr_(nullptr),
82 waveListPtr_ = &wavelist;
99 UTIL_CHECK(mesh().dimensions() == fft().meshDimensions());
103 expKsq_.allocate(mesh().dimensions());
104 expKsq2_.allocate(mesh().dimensions());
105 expW_.allocate(mesh().dimensions());
106 qr_.allocate(mesh().dimensions());
107 qr2_.allocate(mesh().dimensions());
108 qk_.allocate(mesh().dimensions());
109 qk2_.allocate(mesh().dimensions());
111 expW2_.allocate(mesh().dimensions());
113 expWInv_.allocate(mesh().dimensions());
117 cField().allocate(mesh().dimensions());
126 tempNs = floor(
length() / (2.0 *
ds) + 0.5);
131 ds_ =
length()/double(ns_-1);
162 tempNs = floor(
length()/(2.0 *dsTarget_) + 0.5 );
167 ds_ =
length()/double(ns_-1);
202 void Block<D>::computeExpKsq()
209 if (!waveListPtr_->hasKSq()) {
210 waveListPtr_->computeKSq();
212 RField<D> const & kSq = waveListPtr_->kSq();
217 double bSqFactor = -1.0*kuhn()*kuhn() / 6.0;
229 arg = kSq[i]*bSqFactor;
230 expKsq_[i] = exp(arg);
231 expKsq2_[i] = exp(0.5*arg);
245 int nx = mesh().size();
250 fftw_complex arg, arg2;
253 double c2 = -0.25*ds_;
254 for (
int i = 0; i < nx; ++i) {
268 for (
int i = 0; i < nx; ++i) {
270 mul(arg, w[i], -1.0);
272 inverse(expWInv_[i], expW_[i]);
297 int nx = mesh().size();
300 UTIL_CHECK(mesh().dimensions() == fft().meshDimensions());
322 for (i = 0; i < nx; ++i) {
324 mul(qr_[i], q[i], expW_[i] );
325 mul(qr2_[i], q[i], expW2_[i]);
330 fft().forwardTransform(qr_, qk_);
331 fft().forwardTransform(qr2_, qk2_);
332 for (i = 0; i < nx; ++i) {
333 qk_[i][0] *= expKsq_[i];
334 qk_[i][1] *= expKsq_[i];
335 qk2_[i][0] *= expKsq2_[i];
336 qk2_[i][1] *= expKsq2_[i];
338 fft().inverseTransform(qk_, qr_);
339 fft().inverseTransform(qk2_, qr2_);
340 for (i = 0; i < nx; ++i) {
341 mulEq(qr_[i], expW_[i]);
342 mulEq(qr2_[i], expW_[i]);
352 fft().forwardTransform(qr2_, qk2_);
353 for (i = 0; i < nx; ++i) {
354 qk2_[i][0] *= expKsq2_[i];
355 qk2_[i][1] *= expKsq2_[i];
357 fft().inverseTransform(qk2_, qr2_);
358 for (i = 0; i < nx; ++i) {
359 mulEq(qr2_[i], expW2_[i]);
364 for (i = 0; i < nx; ++i) {
365 qout[i][0] = (4.0*qr2_[i][0] - qr_[i][0])/3.0;
366 qout[i][1] = (4.0*qr2_[i][1] - qr_[i][1])/3.0;
393 int nx = mesh().size();
400 fft().forwardTransform(q, qk_);
401 for (
int i = 0; i < nx; ++i) {
402 qk_[i][0] *= expKsq_[i];
403 qk_[i][1] *= expKsq_[i];
405 fft().inverseTransform(qk_, qout);
418 int nx = mesh().size();
426 fft().forwardTransform(q, qk_);
427 for (
int i = 0; i < nx; ++i) {
428 qk_[i][0] *= expKsq2_[i];
429 qk_[i][1] *= expKsq2_[i];
431 fft().inverseTransform(qk_, qout);
441 int nx = mesh().size();
447 for (
int i = 0; i < nx; ++i) {
448 mulEq(q[i], expW_[i]);
462 int nx = mesh().size();
475 for (i = 0; i < nx; ++i) {
490 for (i = 0; i < nx; ++i) {
491 mul(z, hf[i], hr[i]);
500 for (i = 0; i < nx; ++i) {
501 mul(z, tf[i], tr[i]);
508 for (j = 1; j < (ns_ - 1); j += 2) {
511 for (i = 0; i < nx; ++i) {
512 mul(z, qf[i], qr[i]);
521 for (j = 2; j < (ns_ - 2); j += 2) {
524 for (i = 0; i < nx; ++i) {
525 mul(z, qf[i], qr[i]);
534 mul(z, prefactor, d);
536 for (i = 0; i < nx; ++i) {
551 int nx = mesh().size();
565 for (i = 0; i < nx; ++i) {
575 for (j = 1; j < (ns_ -1); ++j) {
578 for (i = 0; i < nx; ++i) {
579 mul(z, qf[i], qr[i]);
580 mulEq(z, expWInv_[i]);
589 for (i = 0; i < nx; ++i) {
590 mulEq(c[i], prefactor);
virtual void setKuhn(double kuhn)
void clearUnitCellData()
Clear all internal data that depends on the unit cell parameters.
void stepFieldBead(CField< D > &q) const
Apply the exponential field operator for the bead model.
int nBead() const
Get the number of beads in this block, in the bead model.
void computeConcentrationThread(fftw_complex const &prefactor)
Compute the concentration for this block, for the thread model.
void computeConcentrationBead(fftw_complex const &prefactor)
Compute the concentration for this block, using the bead model.
void allocate(double ds)
Allocate memory and set number of counter steps.
void stepBead(CField< D > const &qin, CField< D > &qout) const
Compute one step of solution of MDE for the bead model.
void stepHalfBondBead(CField< D > const &qin, CField< D > &qout) const
Apply a half-bond operator for the bead model.
void setLength(double newLength)
Set or reset block length (only used in thread model).
double ds() const
Get contour length step size.
void stepBondBead(CField< D > const &qin, CField< D > &qout) const
Apply a bond operator for the bead model.
void setKuhn(double kuhn)
Set or reset monomer statistical segment length.
void stepThread(CField< D > const &qin, CField< D > &qout) const
Compute one step of solution of MDE for the thread model.
CField< D > & cField()
Get the associated monomer concentration field.
double length() const
Get the length of this block, in the thread model.
double kuhn() const
Get monomer statistical segment length.
Propagator< D > & propagator(int directionId)
Get a Propagator for a specified direction.
void associate(Mesh< D > const &mesh, FFT< D > const &fft, UnitCell< D > const &cell, WaveList< D > &wavelist)
Create permanent associations with related objects.
void setupSolver(CField< D > const &w)
Set up the MDE solver for this block.
MDE solver for one direction of one block.
const FieldT & q(int i) const
Return slice of q-field at a specified step.
virtual void setLength(double length)
Set the length of this block (only valid for thread model).
Iterator over points in a Mesh<D>.
int rank() const
Get the rank of current element.
void begin()
Set iterator to the first point in the mesh.
bool atEnd() const
Is this the end (i.e., one past the last point)?
void setDimensions(const IntVec< D > &dimensions)
Set the grid dimensions in all directions.
Description of a regular grid of points in a periodic domain.
Field of complex double precision values on an FFT mesh.
Fourier transform wrapper.
bool isAllocated() const
Return true if the FftwDArray has been allocated, false otherwise.
Field of real double precision values on an FFT mesh.
Class to compute and store properties associated with wavevectors.
Base template for UnitCell<D> classes, D=1, 2 or 3.
int capacity() const
Return allocated size.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
void mulEq(fftw_complex &a, fftw_complex const &b)
In-place multiplication of two complex number, a *= b.
void addEq(fftw_complex &a, fftw_complex const &b)
In-place addition of fftw_complex numbers, a += b.
void inverse(fftw_complex &z, fftw_complex const &a)
Inversion of an fftw_complex number, z = 1 / a .
void assignExp(fftw_complex &z, fftw_complex const &a)
Exponentation of a ffts_complex variable, z = exp(a).
void assign(fftw_complex &z, double const &a, double const &b)
Create an fftw_complex from real and imaginary parts, z = a + ib.
void mul(fftw_complex &z, fftw_complex const &a, fftw_complex const &b)
Multiplication of fftw_complex numbers, z = a * b.
Complex periodic fields, CL-FTS (CPU).
bool isThread()
Is the thread model in use ?
bool isBead()
Is the bead model in use ?
Fields and FFTs for periodic boundary conditions (CPU)
Periodic fields and crystallography.
PSCF package top-level namespace.