Field3D
MACFieldUtil.h
Go to the documentation of this file.
1//----------------------------------------------------------------------------//
2
3/*
4 * Copyright (c) 2009 Sony Pictures Imageworks Inc
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution. Neither the name of Sony Pictures Imageworks nor the
18 * names of its contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36//----------------------------------------------------------------------------//
37
43//----------------------------------------------------------------------------//
44
45#ifndef _INCLUDED_Field3D_MACFieldUtil_H_
46#define _INCLUDED_Field3D_MACFieldUtil_H_
47
48#include "MACField.h"
49
50//----------------------------------------------------------------------------//
51
52#include "ns.h"
53
55
56//----------------------------------------------------------------------------//
57// Utility functions
58//----------------------------------------------------------------------------//
59
61template <class Data_T, class Field_T>
63 typename Field_T::Ptr cc);
64
65//----------------------------------------------------------------------------//
66
68template <class Field_T, class Data_T>
69void convertCellCenteredToMAC(typename Field_T::Ptr cc,
70 typename MACField<Data_T>::Ptr mac);
71
72//----------------------------------------------------------------------------//
73// Implementations
74//----------------------------------------------------------------------------//
75
77template <class Data_T, class Field_T>
79 typename Field_T::Ptr cc)
80{
81 // Make sure the extents and data window match
82 if (cc->extents().min != mac->extents().min ||
83 cc->extents().max != mac->extents().max ||
84 cc->dataWindow().min != mac->dataWindow().min ||
85 cc->dataWindow().max != mac->dataWindow().max ) {
86 cc->setSize(mac->extents(), mac->dataWindow());
87 }
88
89 // Make sure mapping matches
90 if (!cc->mapping()->isIdentical(mac->mapping())) {
91 cc->setMapping(mac->mapping());
92 }
93
94 // MAC velocities are in simulation space (axis-aligned to the
95 // mapping) because the values are stored on the faces, so rotate
96 // vectors from simulation-space to world-space when transferring
97 // from MAC to cell-centered
98
99 bool rotateVector = false;
100 M44d ssToWsMtx;
103 if (mapping) {
104 M44d localToWorldMtx = mapping->localToWorld();
105 V3d scale, rot, trans, shear;
106 if (extractSHRT(localToWorldMtx, scale, shear, rot, trans, false)) {
107 ssToWsMtx.rotate(rot);
108 if (rot.length2() > FLT_EPSILON)
109 rotateVector = true;
110 }
111 }
112
113 // Loop over all the voxels in the output field ---
114
115 typename Field_T::iterator i = cc->begin();
116 typename Field_T::iterator end = cc->end();
117
118 if (rotateVector) {
119 for (; i != end; ++i) {
120 *i = mac->value(i.x, i.y, i.z) * ssToWsMtx;
121 }
122 } else {
123 for (; i != end; ++i) {
124 *i = mac->value(i.x, i.y, i.z);
125 }
126 }
127}
128
129//----------------------------------------------------------------------------//
130
131template <class Field_T, class Data_T>
132void convertCellCenteredToMAC(typename Field_T::Ptr cc,
133 typename MACField<Data_T>::Ptr mac)
134{
135 // Make sure the extents and data window match
136 if (mac->extents().min != cc->extents().min ||
137 mac->extents().max != cc->extents().max ||
138 mac->dataWindow().min != cc->dataWindow().min ||
139 mac->dataWindow().max != cc->dataWindow().max ) {
140 mac->setSize(cc->extents(), cc->dataWindow());
141 }
142
143 // Make sure mapping matches
144 if (!mac->mapping()->isIdentical(cc->mapping())) {
145 mac->setMapping(cc->mapping());
146 }
147
148 Box3i data = mac->dataWindow();
149
150 // MAC velocities are in simulation space (axis-aligned to the
151 // mapping) because the values are stored on the faces, so rotate
152 // vectors from world-space to simulation-space when transferring
153 // from cell-centered to MAC
154
155 bool rotateVector = false;
156 M44d wsToSsMtx;
159 if (mapping) {
160 M44d localToWorld = mapping->localToWorld();
161 V3d scale, rot, trans, shear;
162 if (FIELD3D_EXTRACT_SHRT(localToWorld, scale, shear, rot, trans, false)) {
163 wsToSsMtx.rotate(-rot);
164 rotateVector = true;
165 }
166 }
167
168 // Use a pointer to a field below so we can substitute it out for
169 // our intermediate, rotated field if necessary, without needing to
170 // duplicate the loops. This should be more efficient CPU-wise so
171 // we don't need to do 3 matrix multiplies per cell-centered voxel
172 // because it's used in 3 separate loops (1 per MAC face).
173 typename Field_T::Ptr src = cc;
174
175 typename Field_T::Ptr ccRotated;
176 if (rotateVector) {
177 ccRotated =
178 typename Field_T::Ptr(new Field_T);
179 ccRotated->matchDefinition(cc);
180
181 typename Field_T::const_iterator iIn = cc->cbegin();
182 typename Field_T::const_iterator endIn = cc->cend();
183 typename Field_T::iterator iOut = ccRotated->begin();
184
185 for (; iIn != endIn; ++iIn, ++iOut) {
186 *iOut = *iIn * wsToSsMtx;
187 }
188 src = ccRotated;
189 }
190
191 // Set the u edge value to their closest voxel
192 for (int k = data.min.z; k <= data.max.z; k++) {
193 for (int j = data.min.y; j <= data.max.y; j++) {
194 mac->u(data.min.x, j, k) = src->value(data.min.x, j, k).x;
195 mac->u(data.max.x + 1, j, k) = src->value(data.max.x, j, k).x;
196 }
197 }
198
199 // Set the v edge value to their closest voxel
200 for (int k = data.min.z; k <= data.max.z; k++) {
201 for (int i = data.min.x; i <= data.max.x; i++) {
202 mac->v(i, data.min.y, k) = src->value(i, data.min.y, k).y;
203 mac->v(i, data.max.y + 1, k) = src->value(i, data.max.y, k).y;
204 }
205 }
206
207 // Set the w edge value to their closest voxel
208 for (int j = data.min.y; j <= data.max.y; j++) {
209 for (int i = data.min.x; i <= data.max.x; i++) {
210 mac->w(i, j, data.min.z) = src->value(i, j, data.min.z).z;
211 mac->w(i, j, data.max.z + 1) = src->value(i, j, data.max.z).z;
212 }
213 }
214
215 // Loop over internal u values
216 for (int k = data.min.z; k <= data.max.z; ++k) {
217 for (int j = data.min.y; j <= data.max.y; ++j) {
218 for (int i = data.min.x + 1; i <= data.max.x; ++i) {
219 mac->u(i, j, k) =
220 (src->value(i, j, k).x + src->value(i - 1, j, k).x) * 0.5;
221 }
222 }
223 }
224
225 // Loop over internal v values
226 for (int k = data.min.z; k <= data.max.z; ++k) {
227 for (int j = data.min.y + 1; j <= data.max.y; ++j) {
228 for (int i = data.min.x; i <= data.max.x; ++i) {
229 mac->v(i, j, k) =
230 (src->value(i, j, k).y + src->value(i, j - 1, k).y) * 0.5;
231 }
232 }
233 }
234
235 // Loop over internal w values
236 for (int k = data.min.z + 1; k <= data.max.z; ++k) {
237 for (int j = data.min.y; j <= data.max.y; ++j) {
238 for (int i = data.min.x; i <= data.max.x; ++i) {
239 mac->w(i, j, k) =
240 (src->value(i, j, k).z + src->value(i, j, k - 1).z) * 0.5;
241 }
242 }
243 }
244}
245
246//----------------------------------------------------------------------------//
247
249
250//----------------------------------------------------------------------------//
251
252#endif // Include guard
FIELD3D_NAMESPACE_OPEN void convertMACToCellCentered(typename MACField< Data_T >::Ptr mac, typename Field_T::Ptr cc)
Converts the MAC field to a cell-centered field.
void convertCellCenteredToMAC(typename Field_T::Ptr cc, typename MACField< Data_T >::Ptr mac)
Converts the cell-centered field to a MAC field.
Contains the MACField class.
#define FIELD_DYNAMIC_CAST
Definition RefCount.h:271
Imath::V3d V3d
Definition SpiMathLib.h:74
#define FIELD3D_EXTRACT_SHRT
Definition SpiMathLib.h:93
Imath::Box3i Box3i
Definition SpiMathLib.h:77
Imath::M44d M44d
Definition SpiMathLib.h:82
void setMapping(FieldMapping::Ptr mapping)
Sets the field's mapping.
Definition Field.h:347
FieldMapping::Ptr mapping()
Returns a pointer to the mapping.
Definition Field.h:263
const Box3i & extents() const
Returns the extents of the data. This signifies the relevant area that the data exists over....
Definition Field.h:249
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Definition Field.h:253
boost::intrusive_ptr< MACField > Ptr
Definition MACField.h:101
const real_t & w(int i, int j, int k) const
Read access to value on w-facing wall.
Definition MACField.h:774
const real_t & u(int i, int j, int k) const
Read access to value on u-facing wall.
Definition MACField.h:698
virtual Data_T value(int i, int j, int k) const
Definition MACField.h:630
const real_t & v(int i, int j, int k) const
Read access to value on v-facing wall.
Definition MACField.h:736
boost::intrusive_ptr< MatrixFieldMapping > Ptr
Convenience typedef.
void setSize(const V3i &size)
Resizes the object.
Definition Field.h:913
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition ns.h:58