@@ -18,10 +18,9 @@ namespace ndtbl {
1818 * memory.
1919 *
2020 * The storage layout is point-major in row-major grid order:
21- * `point0.field0, point0.field1, ..., point1.field0, ...`
22- * where the last grid axis varies fastest before stepping to the next field
23- * tuple.
24- * so that one prepared interpolation query can accumulate all fields together.
21+ * `point0.field0, point0.field1, ..., point1.field0, ...` where the last grid
22+ * axis varies fastest before stepping to the next field tuple. One prepared
23+ * interpolation stencil can accumulate all fields together.
2524 */
2625template <class Value , std::size_t Dim>
2726class FieldGroup
@@ -137,34 +136,37 @@ class FieldGroup
137136 * @brief Evaluate all fields using a previously prepared interpolation
138137 * stencil.
139138 *
140- * @param prepared Prepared query to reuse across fields.
139+ * @tparam Stencil Fixed-size interpolation stencil type.
140+ * @param stencil Prepared stencil to reuse across fields.
141141 * @return Interpolated field values in storage order.
142- * @see Grid::prepare
143- * @see evaluate_all(const std::array<double, Dim>&)
142+ * @see Grid::prepare_linear
143+ * @see Grid::prepare_cubic
144+ * @see evaluate_all_linear(const std::array<double, Dim>&)
144145 */
145- std::vector<Value> evaluate_all (const PreparedQuery<Dim>& prepared) const
146+ template <class Stencil >
147+ std::vector<Value> evaluate_all (const Stencil& stencil) const
146148 {
147149 std::vector<Value> results (field_count (), Value (0 ));
148- evaluate_all_into (prepared , results.data ());
150+ evaluate_all_into (stencil , results.data ());
149151 return results;
150152 }
151153
152154 /* *
153155 * @brief Evaluate all fields using a previously prepared interpolation
154156 * stencil into caller-provided storage.
155157 *
156- * @param prepared Prepared query to reuse across fields.
158+ * @tparam Stencil Fixed-size interpolation stencil type.
159+ * @param stencil Prepared stencil to reuse across fields.
157160 * @param results Output buffer with space for `field_count()` values.
158- * @see evaluate_all(const PreparedQuery<Dim> &)
161+ * @see evaluate_all(const Stencil &)
159162 */
160- void evaluate_all_into ( const PreparedQuery<Dim>& prepared,
161- Value* results) const
163+ template < class Stencil >
164+ void evaluate_all_into ( const Stencil& stencil, Value* results) const
162165 {
163166 std::fill (results, results + field_count (), Value (0 ));
164- for (std::size_t corner = 0 ; corner < PreparedQuery<Dim>::corners;
165- ++corner) {
166- const double weight = prepared.weight (corner);
167- const std::size_t base = prepared.point_index (corner) * field_count ();
167+ for (std::size_t point = 0 ; point < Stencil::points; ++point) {
168+ const double weight = stencil.weight (point);
169+ const std::size_t base = stencil.point_index (point) * field_count ();
168170 for (std::size_t field = 0 ; field < field_count (); ++field) {
169171 results[field] +=
170172 static_cast <Value>(weight * interleaved_values_[base + field]);
@@ -173,34 +175,73 @@ class FieldGroup
173175 }
174176
175177 /* *
176- * @brief Evaluate all fields directly from query coordinates.
178+ * @brief Evaluate all fields directly from query coordinates using
179+ * multilinear interpolation.
177180 *
178181 * @param coordinates Query coordinates in grid axis order.
179182 * @return Interpolated field values in storage order.
180183 * @param policy Bounds handling behavior for out-of-domain coordinates.
181- * @see evaluate_all(const PreparedQuery<Dim> &)
184+ * @see evaluate_all(const Stencil &)
182185 */
183- std::vector<Value> evaluate_all (
186+ std::vector<Value> evaluate_all_linear (
184187 const std::array<double , Dim>& coordinates,
185188 bounds_policy policy = bounds_policy::clamp) const
186189 {
187- return evaluate_all (grid_.prepare (coordinates, policy));
190+ return evaluate_all (grid_.prepare_linear (coordinates, policy));
188191 }
189192
190193 /* *
191- * @brief Evaluate all fields directly from query coordinates into
192- * caller-provided storage.
194+ * @brief Evaluate all fields directly from query coordinates using
195+ * multilinear interpolation into caller-provided storage.
193196 *
194197 * @param coordinates Query coordinates in grid axis order.
195198 * @param results Output buffer with space for `field_count()` values.
196199 * @param policy Bounds handling behavior for out-of-domain coordinates.
197- * @see evaluate_all_into(const PreparedQuery<Dim> &, Value*)
200+ * @see evaluate_all_into(const Stencil &, Value*)
198201 */
199- void evaluate_all_into (const std::array<double , Dim>& coordinates,
200- Value* results,
201- bounds_policy policy = bounds_policy::clamp) const
202+ void evaluate_all_linear_into (
203+ const std::array<double , Dim>& coordinates,
204+ Value* results,
205+ bounds_policy policy = bounds_policy::clamp) const
206+ {
207+ evaluate_all_into (grid_.prepare_linear (coordinates, policy), results);
208+ }
209+
210+ /* *
211+ * @brief Evaluate all fields directly from query coordinates using local
212+ * cubic interpolation.
213+ *
214+ * Cubic interpolation uses four support points per axis and is therefore
215+ * intended for experiments where the additional cost and possible overshoot
216+ * are acceptable.
217+ *
218+ * @param coordinates Query coordinates in grid axis order.
219+ * @param policy Bounds handling behavior for out-of-domain coordinates.
220+ * @return Cubically interpolated field values in storage order.
221+ * @see Grid::prepare_cubic
222+ */
223+ std::vector<Value> evaluate_all_cubic (
224+ const std::array<double , Dim>& coordinates,
225+ bounds_policy policy = bounds_policy::clamp) const
226+ {
227+ return evaluate_all (grid_.prepare_cubic (coordinates, policy));
228+ }
229+
230+ /* *
231+ * @brief Evaluate all fields directly from query coordinates using local
232+ * cubic interpolation into caller-provided storage.
233+ *
234+ * @param coordinates Query coordinates in grid axis order.
235+ * @param results Output buffer with space for `field_count()` values.
236+ * @param policy Bounds handling behavior for out-of-domain coordinates.
237+ * @see evaluate_all_cubic
238+ */
239+ void evaluate_all_cubic_into (
240+ const std::array<double , Dim>& coordinates,
241+ Value* results,
242+ bounds_policy policy = bounds_policy::clamp) const
202243 {
203- evaluate_all_into (grid_.prepare (coordinates, policy), results);
244+ evaluate_all_into (grid_.prepare_cubic (coordinates, policy), results);
204245 }
205246
206247private:
0 commit comments