1#ifndef PSPC_FILM_ITERATOR_BASE_TPP
2#define PSPC_FILM_ITERATOR_BASE_TPP
11#include "FilmIteratorBase.h"
12#include "pscf/crystal/UnitCell.h"
13#include "pscf/crystal/groupFile.h"
14#include "pscf/math/RealVec.h"
15#include "pscf/crystal/SpaceGroup.h"
16#include "pspc/System.h"
17#include "pspc/field/RField.h"
18#include "pspc/field/FieldIo.h"
19#include "util/containers/FArray.h"
20#include "util/format/Dbl.h"
33 template <
int D,
typename IteratorType>
47 setClassName(iterator_.className().append(
"FilmBase").c_str());
55 template <
int D,
typename IteratorType>
62 template <
int D,
typename IteratorType>
68 setParent(iterator_,
false);
69 addComponent(iterator_,
false);
72 iterator_.readParameters(in);
75 read(in,
"normalVecId", normalVecId_);
76 read(in,
"interfaceThickness", t_);
77 read(in,
"wallThickness", T_);
80 if (normalVecId_ > D || normalVecId_ < 0) {
81 UTIL_THROW(
"bad value for normalVecId, must be in [0,D)");
84 UTIL_THROW(
"wallThickness must be larger than interfaceThickness");
86 if ((T_ <= 0) || (t_ <= 0)) {
87 UTIL_THROW(
"wallThickness and interfaceThickness must be >0");
92 int nm = system().mixture().nMonomer();
93 chiBottom_.allocate(nm);
95 for (
int i = 0; i < nm; i++) {
99 readDArray(in,
"chiBottom", chiBottom_, nm);
100 readDArray(in,
"chiTop", chiTop_, nm);
115 template <
int D,
typename IteratorType>
119 UTIL_CHECK(system().unitCell().isInitialized());
122 if (!system().mask().isAllocated()) {
123 system().mask().allocate(system().basis().nBasis(),
124 system().mesh().dimensions());
127 if (!system().h().isAllocatedRGrid()) {
128 system().h().allocateRGrid(system().mesh().dimensions());
130 if (!system().h().isAllocatedBasis()) {
131 system().h().allocateBasis(system().basis().nBasis());
142 generateWallFields();
143 ungenerated_ =
false;
155 template <
int D,
typename IteratorType>
162 return iterator_.solve(isContinuation);
172 template <
int D,
typename IteratorType>
176 UTIL_CHECK(wallThickness() > interfaceThickness());
179 if (ungenerated_) ungenerated_ =
false;
182 checkLatticeVectors();
186 a = system().domain().unitCell().rBasis(normalVecId_);
187 double norm_sqd(0.0);
188 for (
int i = 0; i < D; i++) {
189 norm_sqd += a[i]*a[i];
191 double L(sqrt(norm_sqd));
196 for (
int ind = 0; ind < 3; ind++) {
198 dim[ind] = system().domain().mesh().dimensions()[ind];
206 rGrid.
allocate(system().domain().mesh().dimensions());
212 for (x = 0; x < dim[0]; x++) {
214 for (y = 0; y < dim[1]; y++) {
216 for (z = 0; z < dim[2]; z++) {
221 d = coords[normalVecId_] * L / dim[normalVecId_];
224 rho_w = 0.5*(1+tanh(4*(((.5*(T_-L))+fabs(d-(L/2)))/t_)));
225 rGrid[counter++] = 1-rho_w;
231 system().mask().setRGrid(rGrid,
true);
234 parameters_ = system().domain().unitCell().parameters();
237 generateExternalFields();
249 template <
int D,
typename IteratorType>
254 system().domain().unitCell().parameters();
256 bool identical =
true;
257 for (
int i = 0; i < parameters_.size(); i++) {
258 if (fabs(sysParams[i] - parameters_[i]) > 1e-10) {
266 generateWallFields();
270 bool newExternalFields =
false;
271 for (
int i = 0; i < chiBottom_.capacity(); i++) {
272 if ((chiBottom_[i] != chiBottomCurrent_[i]) ||
273 (chiTop_[i] != chiTopCurrent_[i])) {
274 newExternalFields =
true;
278 if (newExternalFields) {
279 generateExternalFields();
288 template <
int D,
typename IteratorType>
293 chiBottomCurrent_ = chiBottom_;
294 chiTopCurrent_ = chiTop_;
299 if ((isAthermal()) && (!system().h().hasData())) {
306 int nm = system().mixture().nMonomer();
310 a = system().domain().unitCell().rBasis(normalVecId_);
311 double norm_sqd(0.0);
312 for (
int i = 0; i < D; i++) {
313 norm_sqd += a[i]*a[i];
315 double L(sqrt(norm_sqd));
321 for (
int ind = 0; ind < 3; ind++) {
323 dim[ind] = system().domain().mesh().dimensions()[ind];
332 for (
int i = 0; i < nm; i++) {
333 hRGrid[i].
allocate(system().domain().mesh().dimensions());
341 for (i = 0; i < nm; i++) {
342 for (x = 0; x < dim[0]; x++) {
344 for (y = 0; y < dim[1]; y++) {
346 for (z = 0; z < dim[2]; z++) {
351 d = coords[normalVecId_] * L / dim[normalVecId_];
355 rho_w = 0.5*(1+tanh(4*(((.5*(T_-L))+fabs(d-(L/2)))/t_)));
357 hRGrid[i][counter++] = rho_w * chiBottom_[i];
359 hRGrid[i][counter++] = rho_w * chiTop_[i];
368 system().h().setRGrid(hRGrid,
true);
375 template <
int D,
typename IteratorType>
379 std::string groupName = system().groupName();
384 if (groupName ==
"I") {
388 bool foundFile =
false;
406 Log::file() <<
"\nFailed to open group file: "
408 Log::file() <<
"\n Error: Unknown space group\n";
415 int nv = normalVecId();
416 bool symmetric = isSymmetric();
417 std::string msg =
"Space group contains forbidden symmetry operations";
418 for (
int i = 0; i < group.
size(); i++) {
419 for (
int j = 0; j < D; j++) {
420 int r = group[i].R(nv,j);
423 if ((r != -1) || (!symmetric)) {
433 if (group[i].t(nv) != 0) {
443 template <
int D,
typename IteratorType>
446 int nm = system().mixture().nMonomer();
452 for (
int i = 0; i < nm; i++) {
453 if (fabs(chiBottom_[i]-chiTop_[i]) > 1e-7) {
464 template <
int D,
typename IteratorType>
467 int nm = system().mixture().nMonomer();
473 for (
int i = 0; i < nm; i++) {
474 if ((fabs(chiBottom_[i]) >= 1e-7) || (fabs(chiTop_[i]) >= 1e-7)) {
An IntVec<D, T> is a D-component vector of elements of integer type T.
FilmIteratorBase(System< D > &system)
Constructor.
void generateExternalFields()
Generate external fields for the walls.
int solve(bool isContinuation=false)
Iterate to a solution.
bool isAthermal() const
Are the walls athermal?
void readParameters(std::istream &in)
Read and initialize.
bool isSymmetric() const
Are the walls chemically identical?
void setup()
Initialize just before entry to iterative loop.
void generateWallFields()
Generates mask and external field for the walls and stores in System.
void updateWallFields()
Updates the mask and external fields for the walls if needed.
~FilmIteratorBase()
Destructor.
void checkSpaceGroup() const
Check that space group is compatible with the thin film constraint.
Base class for iterative solvers for SCF equations.
System< D > const & system() const
Get parent system by const reference.
Field of real double precision values on an FFT mesh.
void allocate(const IntVec< D > &meshDimensions)
Allocate the underlying C array for an FFT grid.
Main class for SCFT simulation of one system.
A RealVec<D, T> is D-component vector with elements of floating type T.
Crystallographic space group.
int size() const
Return number of elements in group (i.e., the order of the group).
void makeCompleteGroup()
Generate a complete group from the current elements.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
A fixed size (static) contiguous array template.
A fixed capacity (static) contiguous array with a variable logical size.
int size() const
Return logical size of this array (i.e., number of elements).
static std::ostream & file()
Get log ostream by reference.
void setClassName(const char *className)
Set class name string.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
std::string makeGroupFileName(int D, std::string groupName)
Generates the file name from a group name.
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.