PSCF v1.1
pscf/math/Field.h
1#ifndef PSCF_FIELD_H
2#define PSCF_FIELD_H
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 <util/containers/DArray.h>
12
13namespace Pscf {
14
15 using namespace Util;
16
24 template <typename T = double>
25 class Field : public DArray<T>
26 {
27 public:
28
32 Field();
33
37 Field(Field<T> const & other);
38
42 Field<T>& operator = (Field<T> const & other);
43
47 Field<T>& operator = (T& scalar);
48
53
58
63
68
72 void setToZero();
73
77 T average() const;
78
79 using Array<T>::operator [];
80 using Array<T>::capacity;
81 using DArray<T>::allocate;
82 using DArray<T>::deallocate;
83 using DArray<T>::isAllocated;
84
85 protected:
86
87 using Array<T>::capacity_;
88 using Array<T>::data_;
89
90 };
91
92 /*
93 * Copy constructor.
94 *
95 * Allocates new memory and copies all elements by value.
96 *
97 *\param other the Field to be copied.
98 */
99 template <class T>
101 : DArray<T>()
102 {
103 if (!other.isAllocated()) {
104 UTIL_THROW("Other Field not allocated.");
105 }
107 capacity_ = other.capacity_;
108 for (int i = 0; i < capacity_; ++i) {
109 data_[i] = other.data_[i];
110 }
111 }
112
113 /*
114 * Assignment from another Field, element-by-element.
115 *
116 * This operator will allocate memory if not allocated previously.
117 *
118 * \throw Exception if other Field is not allocated.
119 * \throw Exception if both Fields are allocated with unequal capacities.
120 *
121 * \param other the rhs Field
122 */
123 template <class T>
125 {
126 // Check for self assignment
127 if (this == &other) return *this;
128
129 // Precondition
130 if (!other.isAllocated()) {
131 UTIL_THROW("Other Field not allocated.");
132 }
133
134 if (!isAllocated()) {
135 allocate(other.capacity());
136 } else if (capacity_ != other.capacity_) {
137 UTIL_THROW("Fields of unequal capacity");
138 }
139
140 // Copy elements
141 for (int i = 0; i < capacity_; ++i) {
142 data_[i] = other[i];
143 }
144
145 return *this;
146 }
147
148 /*
149 * Assignment - assign all elements to a common scalar.
150 */
151 template <typename T>
153 {
154 if (!isAllocated()) {
155 UTIL_THROW("Field not allocated.");
156 }
157 for (int i = 0; i < capacity_; ++i) {
158 data_[i] = scalar;
159 }
160 return *this;
161 }
162
163 /*
164 * Increment& Field<T>::operator, add one field by another.
165 */
166 template <typename T>
168 {
169 if (!other.isAllocated()) {
170 UTIL_THROW("Other Field no allocated.");
171 }
172 if (!isAllocated()) {
173 UTIL_THROW("This Field not allocated.");
174 }
175 if (capacity_ != other.capacity_) {
176 UTIL_THROW("Fields of unequal capacity");
177 }
178 for (int i = 0; i < capacity_; ++i) {
179 data_[i] += other.data_[i];
180 }
181 return *this;
182 }
183
184 /*
185 * Decrement& Field<T>::operator, subtract one field from another.
186 */
187 template <typename T>
189 {
190
191 // Preconditions
192 if (!other.isAllocated()) {
193 UTIL_THROW("Other Field not allocated.");
194 }
195 if (!isAllocated()) {
196 UTIL_THROW("This Field not allocated.");
197 }
198 if (capacity_ != other.capacity_) {
199 UTIL_THROW("Fields of unequal capacity");
200 }
201
202 for (int i = 0; i < capacity_; ++i) {
203 data_[i] -= other.data_[i];
204 }
205 return *this;
206 }
207
208 /*
209 * Multiplication& Field<T>::operator - multiply one field by a scalar.
210 */
211 template <typename T>
213 {
214 // Precondition
215 if (!isAllocated()) {
216 UTIL_THROW("Field not allocated.");
217 }
218
219 for (int i = 0; i < capacity_; ++i) {
220 data_[i] *= scalar;
221 }
222 return *this;
223 }
224
225 /*
226 * Pointwise multipication of field& Field<T>::operator.
227 */
228 template <typename T>
230 {
231 // Preconditions
232 if (!other.isAllocated()) {
233 UTIL_THROW("Other Field not allocated.");
234 }
235 if (!isAllocated()) {
236 UTIL_THROW("This Field not allocated.");
237 }
238 if (capacity_ != other.capacity_) {
239 UTIL_THROW("Unequal capacity");
240 }
241
242 for (int i = 0; i < capacity_; ++i) {
243 data_[i] *= other.data_[i];
244 }
245 return *this;
246 }
247
248 /*
249 * Set to zero.
250 */
251 template <typename T>
253 {
254 for (int i = 0; i < capacity_; ++i) {
255 data_[i] *= 0.0;
256 }
257 }
258
259 /*
260 * Compute and return average of all elements.
261 */
262 template <typename T>
264 {
265 double value = 0.0;
266 for (int i = 0; i < capacity_; ++i) {
267 value += data_[i];
268 }
269 return value/T(capacity_);
270 }
271
272}
273#endif
Base class template for a field defined on a spatial grid.
Field< T > & operator-=(Field< T > &other)
Decrement operator - subtract one field from another.
T average() const
Compute and return average of all elements.
Field< T > & operator*=(T scalar)
Multiplication operator - multiply one field by a scalar.
void setToZero()
Set all elements to zero.
Field< T > & operator=(Field< T > const &other)
Assignment operator.
Field(Field< T > const &other)
Copy constructor.
Field()
Constructor.
Definition: Field.tpp:26
Field< T > & operator+=(Field< T > &other)
Increment operator - add one field by another.
Array container class template.
Definition: Array.h:34
Data * data_
Pointer to an array of Data elements.
Definition: Array.h:109
int capacity() const
Return allocated size.
Definition: Array.h:159
int capacity_
Allocated size of the data_ array.
Definition: Array.h:112
Dynamically allocatable contiguous array template.
Definition: DArray.h:32
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:199
void deallocate()
Dellocate the underlying C array.
Definition: DArray.h:217
bool isAllocated() const
Return true if this DArray has been allocated, false otherwise.
Definition: DArray.h:247
static void allocate(Data *&ptr, size_t size)
Allocate a C++ array.
Definition: Memory.h:132
#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