DDC 0.1.0
Loading...
Searching...
No Matches
spline_builder_2d.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <cstddef>
8#include <optional>
9#include <type_traits>
10
11#include <ddc/ddc.hpp>
12
13#include "spline_builder.hpp"
14
15namespace ddc {
16
17/**
18 * @brief A class for creating a 2D spline approximation of a function.
19 *
20 * A class which contains an operator () which can be used to build a 2D spline approximation
21 * of a function. A 2D spline approximation uses a cross-product between two 1D SplineBuilder.
22 *
23 * @see SplineBuilder
24 */
25template <
26 class ExecSpace,
27 class MemorySpace,
28 class BSpline1,
29 class BSpline2,
30 class IDimI1,
31 class IDimI2,
32 ddc::BoundCond BcLower1,
33 ddc::BoundCond BcUpper1,
34 ddc::BoundCond BcLower2,
35 ddc::BoundCond BcUpper2,
36 ddc::SplineSolver Solver,
37 class... IDimX>
39{
40public:
41 /// @brief The type of the Kokkos execution space used by this class.
42 using exec_space = ExecSpace;
43
44 /// @brief The type of the Kokkos memory space used by this class.
45 using memory_space = MemorySpace;
46
47 /// @brief The type of the SplineBuilder used by this class to spline-approximate along first dimension.
48 using builder_type1 = ddc::SplineBuilder<
49 ExecSpace,
50 MemorySpace,
51 BSpline1,
52 IDimI1,
53 BcLower1,
54 BcUpper1,
55 Solver,
56 IDimX...>;
57
58 /// @brief The type of the SplineBuilder used by this class to spline-approximate along second dimension.
59 using builder_type2 = ddc::SplineBuilder<
60 ExecSpace,
61 MemorySpace,
62 BSpline2,
63 IDimI2,
64 BcLower2,
65 BcUpper2,
66 Solver,
67 std::conditional_t<std::is_same_v<IDimX, IDimI1>, BSpline1, IDimX>...>;
68
69 /// @brief The type of the SplineBuilder used by this class to spline-approximate the second-dimension-derivatives along first dimension.
70 using builder_deriv_type1 = ddc::SplineBuilder<
71 ExecSpace,
72 MemorySpace,
73 BSpline1,
74 IDimI1,
75 BcLower1,
76 BcUpper1,
77 Solver,
78 std::conditional_t<
79 std::is_same_v<IDimX, IDimI2>,
80 typename builder_type2::deriv_type,
81 IDimX>...>;
82
83 /// @brief The type of the first interpolation continuous dimension.
84 using continuous_dimension_type1 = typename builder_type1::continuous_dimension_type;
85
86 /// @brief The type of the second interpolation continuous dimension.
87 using continuous_dimension_type2 = typename builder_type2::continuous_dimension_type;
88
89 /// @brief The type of the first interpolation discrete dimension.
90 using interpolation_discrete_dimension_type1 =
91 typename builder_type1::interpolation_discrete_dimension_type;
92
93 /// @brief The type of the second interpolation discrete dimension.
94 using interpolation_discrete_dimension_type2 =
95 typename builder_type2::interpolation_discrete_dimension_type;
96
97 /// @brief The type of the B-splines in the first dimension.
98 using bsplines_type1 = typename builder_type1::bsplines_type;
99
100 /// @brief The type of the B-splines in the second dimension.
101 using bsplines_type2 = typename builder_type2::bsplines_type;
102
103 /// @brief The type of the Deriv domain on boundaries in the first dimension.
104 using deriv_type1 = typename builder_type1::deriv_type;
105
106 /// @brief The type of the Deriv domain on boundaries in the second dimension.
107 using deriv_type2 = typename builder_type2::deriv_type;
108
109 /// @brief The type of the domain for the interpolation mesh in the first dimension.
110 using interpolation_domain_type1 =
111 typename builder_type1::interpolation_discrete_dimension_type;
112
113 /// @brief The type of the domain for the interpolation mesh in the second dimension.
114 using interpolation_domain_type2 =
115 typename builder_type2::interpolation_discrete_dimension_type;
116
117 /// @brief The type of the domain for the interpolation mesh in the 2D dimension.
118 using interpolation_domain_type = ddc::DiscreteDomain<
119 interpolation_discrete_dimension_type1,
120 interpolation_discrete_dimension_type2>;
121
122 /// @brief The type of the whole domain representing interpolation points.
123 using batched_interpolation_domain_type = ddc::DiscreteDomain<IDimX...>;
124
125 /**
126 * @brief The type of the batch domain (obtained by removing the dimensions of interest
127 * from the whole domain).
128 *
129 * Example: For batched_interpolation_domain_type = DiscreteDomain<X,Y,Z> and dimensions of interest X and Y,
130 * this is DiscreteDomain<Z>.
131 */
132 using batch_domain_type = ddc::remove_dims_of_t<
133 batched_interpolation_domain_type,
134 interpolation_discrete_dimension_type1,
135 interpolation_discrete_dimension_type2>;
136
137 /**
138 * @brief The type of the whole spline domain (cartesian product of 2D spline domain
139 * and batch domain) preserving the order of dimensions.
140 *
141 * Example: For batched_interpolation_domain_type = DiscreteDomain<X,Y,Z> and dimensions of interest X and Y
142 * (associated to B-splines tags BSplinesX and BSplinesY), this is DiscreteDomain<BSplinesX, BSplinesY, Z>
143 */
144 using batched_spline_domain_type
145 = ddc::detail::convert_type_seq_to_discrete_domain_t<ddc::type_seq_replace_t<
146 ddc::detail::TypeSeq<IDimX...>,
147 ddc::detail::TypeSeq<
148 interpolation_discrete_dimension_type1,
149 interpolation_discrete_dimension_type2>,
150 ddc::detail::TypeSeq<bsplines_type1, bsplines_type2>>>;
151
152 /**
153 * @brief The type of the whole Derivs domain (cartesian product of the 1D Deriv domain
154 * and the associated batch domain) in the first dimension, preserving the order of dimensions.
155 *
156 * Example: For batched_interpolation_domain_type = DiscreteDomain<X,Y,Z> and dimensions of interest X and Y,
157 * this is DiscreteDomain<Deriv<X>, Y, Z>.
158 */
159 using batched_derivs_domain_type1 = typename builder_type1::batched_derivs_domain_type;
160
161 /**
162 * @brief The type of the whole Derivs domain (cartesian product of the 1D Deriv domain
163 * and the associated batch domain) in the second dimension, preserving the order of dimensions.
164 *
165 * Example: For batched_interpolation_domain_type = DiscreteDomain<X,Y,Z> and dimensions of interest X and Y,
166 * this is DiscreteDomain<X, Deriv<Y>, Z>.
167 */
168 using batched_derivs_domain_type2 = ddc::replace_dim_of_t<
169 batched_interpolation_domain_type,
170 interpolation_discrete_dimension_type2,
171 deriv_type2>;
172
173 /**
174 * @brief The type of the whole Derivs domain (cartesian product of the 2D Deriv domain
175 * and the batch domain) in the second dimension, preserving the order of dimensions.
176 *
177 * Example: For batched_interpolation_domain_type = DiscreteDomain<X,Y,Z> and dimensions of interest X and Y,
178 * this is DiscreteDomain<Deriv<X>, Deriv<Y>, Z>.
179 */
180 using batched_derivs_domain_type
181 = ddc::detail::convert_type_seq_to_discrete_domain_t<ddc::type_seq_replace_t<
182 ddc::detail::TypeSeq<IDimX...>,
183 ddc::detail::TypeSeq<
184 interpolation_discrete_dimension_type1,
185 interpolation_discrete_dimension_type2>,
186 ddc::detail::TypeSeq<deriv_type1, deriv_type2>>>;
187
188private:
189 builder_type1 m_spline_builder1;
190 builder_deriv_type1 m_spline_builder_deriv1;
191 builder_type2 m_spline_builder2;
192
193public:
194 /**
195 * @brief Build a SplineBuilder2D acting on batched_interpolation_domain.
196 *
197 * @param batched_interpolation_domain The domain on which the interpolation points are defined.
198 *
199 * @param cols_per_chunk A parameter used by the slicer (internal to the solver) to define the size
200 * of a chunk of right-hand-sides of the linear problem to be computed in parallel (chunks are treated
201 * by the linear solver one-after-the-other).
202 * This value is optional. If no value is provided then the default value is chosen by the requested solver.
203 *
204 * @param preconditioner_max_block_size A parameter used by the slicer (internal to the solver) to
205 * define the size of a block used by the Block-Jacobi preconditioner.
206 * This value is optional. If no value is provided then the default value is chosen by the requested solver.
207 *
208 * @see SplinesLinearProblemSparse
209 */
210 explicit SplineBuilder2D(
211 batched_interpolation_domain_type const& batched_interpolation_domain,
212 std::optional<std::size_t> cols_per_chunk = std::nullopt,
213 std::optional<unsigned int> preconditioner_max_block_size = std::nullopt)
214 : m_spline_builder1(
215 batched_interpolation_domain,
216 cols_per_chunk,
217 preconditioner_max_block_size)
218 , m_spline_builder_deriv1(
219 ddc::replace_dim_of<interpolation_discrete_dimension_type2, deriv_type2>(
220 m_spline_builder1.batched_interpolation_domain(),
221 ddc::DiscreteDomain<deriv_type2>(
222 ddc::DiscreteElement<deriv_type2>(1),
223 ddc::DiscreteVector<deriv_type2>(bsplines_type2::degree() / 2))))
224 , m_spline_builder2(
225 m_spline_builder1.batched_spline_domain(),
226 cols_per_chunk,
227 preconditioner_max_block_size)
228 {
229 }
230
231 /// @brief Copy-constructor is deleted.
232 SplineBuilder2D(SplineBuilder2D const& x) = delete;
233
234 /**
235 * @brief Move-constructs.
236 *
237 * @param x An rvalue to another SplineBuilder2D.
238 */
239 SplineBuilder2D(SplineBuilder2D&& x) = default;
240
241 /// @brief Destructs.
242 ~SplineBuilder2D() = default;
243
244 /// @brief Copy-assignment is deleted.
245 SplineBuilder2D& operator=(SplineBuilder2D const& x) = delete;
246
247 /** @brief Move-assigns.
248 *
249 * @param x An rvalue to another SplineBuilder.
250 * @return A reference to this object.
251 */
253
254 /**
255 * @brief Get the domain for the 2D interpolation mesh used by this class.
256 *
257 * This is 2D because it is defined along the dimensions of interest.
258 *
259 * @return The 2D domain for the interpolation mesh.
260 */
261 interpolation_domain_type interpolation_domain() const noexcept
262 {
263 return ddc::DiscreteDomain<interpolation_domain_type1, interpolation_domain_type2>(
264 m_spline_builder1.interpolation_domain(),
265 m_spline_builder2.interpolation_domain());
266 }
267
268 /**
269 * @brief Get the whole domain representing interpolation points.
270 *
271 * Values of the function must be provided on this domain in order
272 * to build a spline representation of the function (cartesian product of 2D interpolation_domain and batch_domain).
273 *
274 * @return The domain for the interpolation mesh.
275 */
276 batched_interpolation_domain_type batched_interpolation_domain() const noexcept
277 {
278 return m_spline_builder1.batched_interpolation_domain();
279 }
280
281 /**
282 * @brief Get the batch domain.
283 *
284 * Obtained by removing the dimensions of interest from the whole interpolation domain.
285 *
286 * @return The batch domain.
287 */
288 batch_domain_type batch_domain() const noexcept
289 {
291 }
292
293 /**
294 * @brief Get the 2D domain on which spline coefficients are defined.
295 *
296 * The 2D spline domain corresponding to the dimensions of interest.
297 *
298 * @return The 2D domain for the spline coefficients.
299 */
300 ddc::DiscreteDomain<bsplines_type1, bsplines_type2> spline_domain() const noexcept
301 {
302 return ddc::DiscreteDomain<bsplines_type1, bsplines_type2>(
303 ddc::discrete_space<bsplines_type1>().full_domain(),
304 ddc::discrete_space<bsplines_type2>().full_domain());
305 }
306
307 /**
308 * @brief Get the whole domain on which spline coefficients are defined.
309 *
310 * Spline approximations (spline-transformed functions) are computed on this domain.
311 *
312 * @return The domain for the spline coefficients.
313 */
314 batched_spline_domain_type batched_spline_domain() const noexcept
315 {
316 return ddc::replace_dim_of<interpolation_discrete_dimension_type1, bsplines_type1>(
317 ddc::replace_dim_of<
318 interpolation_discrete_dimension_type2,
321 }
322
323 /**
324 * @brief Compute a 2D spline approximation of a function.
325 *
326 * Use the values of a function (defined on
327 * SplineBuilder2D::batched_interpolation_domain) and the derivatives of the
328 * function at the boundaries (in the case of BoundCond::HERMITE only)
329 * to calculate a 2D spline approximation of this function.
330 *
331 * The spline approximation is stored as a ChunkSpan of coefficients
332 * associated with B-splines.
333 *
334 * @param[out] spline
335 * The coefficients of the spline computed by this SplineBuilder.
336 * @param[in] vals
337 * The values of the function at the interpolation mesh.
338 * @param[in] derivs_min1
339 * The values of the derivatives at the lower boundary in the first dimension.
340 * @param[in] derivs_max1
341 * The values of the derivatives at the upper boundary in the first dimension.
342 * @param[in] derivs_min2
343 * The values of the derivatives at the lower boundary in the second dimension.
344 * @param[in] derivs_max2
345 * The values of the derivatives at the upper boundary in the second dimension.
346 * @param[in] mixed_derivs_min1_min2
347 * The values of the the cross-derivatives at the lower boundary in the first dimension
348 * and the lower boundary in the second dimension.
349 * @param[in] mixed_derivs_max1_min2
350 * The values of the the cross-derivatives at the upper boundary in the first dimension
351 * and the lower boundary in the second dimension.
352 * @param[in] mixed_derivs_min1_max2
353 * The values of the the cross-derivatives at the lower boundary in the first dimension
354 * and the upper boundary in the second dimension.
355 * @param[in] mixed_derivs_max1_max2
356 * The values of the the cross-derivatives at the upper boundary in the first dimension
357 * and the upper boundary in the second dimension.
358 */
359 template <class Layout>
360 void operator()(
361 ddc::ChunkSpan<double, batched_spline_domain_type, Layout, memory_space> spline,
362 ddc::ChunkSpan<double const, batched_interpolation_domain_type, Layout, memory_space>
363 vals,
364 std::optional<
365 ddc::ChunkSpan<double const, batched_derivs_domain_type1, Layout, memory_space>>
366 derivs_min1
367 = std::nullopt,
368 std::optional<
369 ddc::ChunkSpan<double const, batched_derivs_domain_type1, Layout, memory_space>>
370 derivs_max1
371 = std::nullopt,
372 std::optional<
373 ddc::ChunkSpan<double const, batched_derivs_domain_type2, Layout, memory_space>>
374 derivs_min2
375 = std::nullopt,
376 std::optional<
377 ddc::ChunkSpan<double const, batched_derivs_domain_type2, Layout, memory_space>>
378 derivs_max2
379 = std::nullopt,
380 std::optional<
381 ddc::ChunkSpan<double const, batched_derivs_domain_type, Layout, memory_space>>
382 mixed_derivs_min1_min2
383 = std::nullopt,
384 std::optional<
385 ddc::ChunkSpan<double const, batched_derivs_domain_type, Layout, memory_space>>
386 mixed_derivs_max1_min2
387 = std::nullopt,
388 std::optional<
389 ddc::ChunkSpan<double const, batched_derivs_domain_type, Layout, memory_space>>
390 mixed_derivs_min1_max2
391 = std::nullopt,
392 std::optional<
393 ddc::ChunkSpan<double const, batched_derivs_domain_type, Layout, memory_space>>
394 mixed_derivs_max1_max2
395 = std::nullopt) const;
396};
397
398
399template <
400 class ExecSpace,
401 class MemorySpace,
402 class BSpline1,
403 class BSpline2,
404 class IDimI1,
405 class IDimI2,
411 class... IDimX>
412template <class Layout>
413void SplineBuilder2D<
414 ExecSpace,
415 MemorySpace,
416 BSpline1,
417 BSpline2,
418 IDimI1,
419 IDimI2,
420 BcLower1,
421 BcUpper1,
422 BcLower2,
423 BcUpper2,
424 Solver,
425 IDimX...>::
426operator()(
427 ddc::ChunkSpan<double, batched_spline_domain_type, Layout, memory_space> spline,
428 ddc::ChunkSpan<double const, batched_interpolation_domain_type, Layout, memory_space> vals,
429 std::optional<ddc::ChunkSpan<
430 double const,
431 batched_derivs_domain_type1,
432 Layout,
433 memory_space>> const derivs_min1,
434 std::optional<ddc::ChunkSpan<
435 double const,
436 batched_derivs_domain_type1,
437 Layout,
438 memory_space>> const derivs_max1,
439 std::optional<ddc::ChunkSpan<
440 double const,
441 batched_derivs_domain_type2,
442 Layout,
443 memory_space>> const derivs_min2,
444 std::optional<ddc::ChunkSpan<
445 double const,
446 batched_derivs_domain_type2,
447 Layout,
448 memory_space>> const derivs_max2,
449 std::optional<ddc::ChunkSpan<
450 double const,
451 batched_derivs_domain_type,
452 Layout,
453 memory_space>> const mixed_derivs_min1_min2,
454 std::optional<ddc::ChunkSpan<
455 double const,
456 batched_derivs_domain_type,
457 Layout,
458 memory_space>> const mixed_derivs_max1_min2,
459 std::optional<ddc::ChunkSpan<
460 double const,
461 batched_derivs_domain_type,
462 Layout,
463 memory_space>> const mixed_derivs_min1_max2,
464 std::optional<ddc::ChunkSpan<
465 double const,
466 batched_derivs_domain_type,
467 Layout,
468 memory_space>> const mixed_derivs_max1_max2) const
469{
470 // TODO: perform computations along dimension 1 on different streams ?
471 // Spline1-approximate derivs_min2 (to spline1_deriv_min)
472 ddc::Chunk spline1_deriv_min_alloc(
473 m_spline_builder_deriv1.batched_spline_domain(),
474 ddc::KokkosAllocator<double, MemorySpace>());
475 auto spline1_deriv_min = spline1_deriv_min_alloc.span_view();
476 auto spline1_deriv_min_opt = std::optional(spline1_deriv_min.span_cview());
477 if constexpr (BcLower2 == ddc::BoundCond::HERMITE) {
478 m_spline_builder_deriv1(
479 spline1_deriv_min,
480 *derivs_min2,
481 mixed_derivs_min1_min2,
482 mixed_derivs_max1_min2);
483 } else {
484 spline1_deriv_min_opt = std::nullopt;
485 }
486
487 // Spline1-approximate vals (to spline1)
488 ddc::Chunk spline1_alloc(
489 m_spline_builder1.batched_spline_domain(),
490 ddc::KokkosAllocator<double, MemorySpace>());
491 ddc::ChunkSpan const spline1 = spline1_alloc.span_view();
492
493 m_spline_builder1(spline1, vals, derivs_min1, derivs_max1);
494
495 // Spline1-approximate derivs_max2 (to spline1_deriv_max)
496 ddc::Chunk spline1_deriv_max_alloc(
497 m_spline_builder_deriv1.batched_spline_domain(),
498 ddc::KokkosAllocator<double, MemorySpace>());
499 auto spline1_deriv_max = spline1_deriv_max_alloc.span_view();
500 auto spline1_deriv_max_opt = std::optional(spline1_deriv_max.span_cview());
501 if constexpr (BcUpper2 == ddc::BoundCond::HERMITE) {
502 m_spline_builder_deriv1(
503 spline1_deriv_max,
504 *derivs_max2,
505 mixed_derivs_min1_max2,
506 mixed_derivs_max1_max2);
507 } else {
508 spline1_deriv_max_opt = std::nullopt;
509 }
510
511 // Spline2-approximate spline1
512 m_spline_builder2(spline, spline1.span_cview(), spline1_deriv_min_opt, spline1_deriv_max_opt);
513}
514
515} // namespace ddc
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
A class for creating a 2D spline approximation of a function.
SplineBuilder2D(SplineBuilder2D const &x)=delete
Copy-constructor is deleted.
ddc::DiscreteDomain< bsplines_type1, bsplines_type2 > spline_domain() const noexcept
Get the 2D domain on which spline coefficients are defined.
SplineBuilder2D(batched_interpolation_domain_type const &batched_interpolation_domain, std::optional< std::size_t > cols_per_chunk=std::nullopt, std::optional< unsigned int > preconditioner_max_block_size=std::nullopt)
Build a SplineBuilder2D acting on batched_interpolation_domain.
batched_interpolation_domain_type batched_interpolation_domain() const noexcept
Get the whole domain representing interpolation points.
batched_spline_domain_type batched_spline_domain() const noexcept
Get the whole domain on which spline coefficients are defined.
SplineBuilder2D & operator=(SplineBuilder2D const &x)=delete
Copy-assignment is deleted.
void operator()(ddc::ChunkSpan< double, batched_spline_domain_type, Layout, memory_space > spline, ddc::ChunkSpan< double const, batched_interpolation_domain_type, Layout, memory_space > vals, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type1, Layout, memory_space > > derivs_min1=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type1, Layout, memory_space > > derivs_max1=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type2, Layout, memory_space > > derivs_min2=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type2, Layout, memory_space > > derivs_max2=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type, Layout, memory_space > > mixed_derivs_min1_min2=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type, Layout, memory_space > > mixed_derivs_max1_min2=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type, Layout, memory_space > > mixed_derivs_min1_max2=std::nullopt, std::optional< ddc::ChunkSpan< double const, batched_derivs_domain_type, Layout, memory_space > > mixed_derivs_max1_max2=std::nullopt) const
Compute a 2D spline approximation of a function.
~SplineBuilder2D()=default
Destructs.
interpolation_domain_type interpolation_domain() const noexcept
Get the domain for the 2D interpolation mesh used by this class.
batch_domain_type batch_domain() const noexcept
Get the batch domain.
SplineBuilder2D & operator=(SplineBuilder2D &&x)=default
Move-assigns.
SplineBuilder2D(SplineBuilder2D &&x)=default
Move-constructs.
A class for creating a spline approximation of a function.
The top-level namespace of DDC.
BoundCond
An enum representing a spline boundary condition.
@ HERMITE
Hermite boundary condition.
SplineSolver
An enum determining the backend solver of a SplineBuilder or SplineBuilder2d.