DDC 0.14.0
Loading...
Searching...
No Matches
examples/uniform_heat_equation.cpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
6#include <cmath>
7#include <cstddef>
8#include <iomanip>
9#include <iostream>
10#include <string>
11#include <tuple>
12#include <utility>
13
14#include <ddc/ddc.hpp>
15
16#include <Kokkos_Core.hpp>
18
20struct X
21{
22};
24
26struct DDimX : ddc::UniformPointSampling<X>
27{
28};
30
32struct Y
33{
34};
35struct DDimY : ddc::UniformPointSampling<Y>
36{
37};
39
41struct T
42{
43};
44struct DDimT : ddc::UniformPointSampling<T>
45{
46};
48
56template <class ChunkType>
57void display(double time, ChunkType temp)
58{
59 double const mean_temp
60 = ddc::host_transform_reduce(temp.domain(), 0., ddc::reducer::sum<double>(), temp)
61 / temp.domain().size();
62 std::cout << std::fixed << std::setprecision(3);
63 std::cout << "At t = " << time << ",\n";
64 std::cout << " * mean temperature = " << mean_temp << "\n";
65 ddc::ChunkSpan const temp_slice
66 = temp[ddc::get_domain<DDimY>(temp).front() + ddc::get_domain<DDimY>(temp).size() / 2];
67 std::cout << " * temperature[y:" << ddc::get_domain<DDimY>(temp).size() / 2 << "] = {";
69 std::cout << std::setw(6) << temp_slice(ix);
70 });
71 std::cout << " }\n" << std::flush;
72}
74
75int main(int argc, char** argv)
76{
77 Kokkos::ScopeGuard const kokkos_scope(argc, argv);
78 ddc::ScopeGuard const ddc_scope(argc, argv);
79
82 double const x_start = -1.;
83 double const x_end = 1.;
84 std::size_t const nb_x_points = 10;
85 double const kx = .01;
88 double const y_start = -1.;
89 double const y_end = 1.;
90 std::size_t const nb_y_points = 100;
91 double const ky = .002;
94 double const start_time = 0.;
95 double const end_time = 10.;
97 std::ptrdiff_t const t_output_period = 10;
99
101 ddc::DiscreteVector<DDimX> const gwx(1);
103
105 auto const [x_domain, ghosted_x_domain, x_pre_ghost, x_post_ghost]
106 = ddc::init_discrete_space<DDimX>(DDimX::init_ghosted<DDimX>(
107 ddc::Coordinate<X>(x_start),
108 ddc::Coordinate<X>(x_end),
109 ddc::DiscreteVector<DDimX>(nb_x_points),
110 gwx));
112
115 x_post_mirror(x_post_ghost.front() - x_domain.extents(), x_post_ghost.extents());
117 x_pre_mirror(x_pre_ghost.front() + x_domain.extents(), x_pre_ghost.extents());
119
121 ddc::DiscreteVector<DDimY> const gwy(1);
122
123 auto const [y_domain, ghosted_y_domain, y_pre_ghost, y_post_ghost]
124 = ddc::init_discrete_space<DDimY>(DDimY::init_ghosted<DDimY>(
125 ddc::Coordinate<Y>(y_start),
126 ddc::Coordinate<Y>(y_end),
127 ddc::DiscreteVector<DDimY>(nb_y_points),
128 gwy));
129
131 y_post_mirror(y_post_ghost.front() - y_domain.extents(), y_post_ghost.extents());
132
134 y_pre_mirror(y_pre_ghost.front() + y_domain.extents(), y_pre_ghost.extents());
136
138 double const dx = ddc::step<DDimX>();
139 double const dy = ddc::step<DDimY>();
140 double const invdx2 = 1. / (dx * dx);
141 double const invdy2 = 1. / (dy * dy);
142
143 ddc::Coordinate<T> const dt(.5 / (kx * invdx2 + ky * invdy2));
145
147 ddc::DiscreteVector<DDimT> const nb_time_steps(std::ceil((end_time - start_time) / dt) + .2);
148
149 ddc::DiscreteDomain<DDimT> const time_domain
150 = ddc::init_discrete_space<DDimT>(DDimT::init<DDimT>(
151 ddc::Coordinate<T>(start_time),
152 ddc::Coordinate<T>(end_time),
153 nb_time_steps + 1));
155
157 ddc::Chunk ghosted_last_temp(
158 "ghosted_last_temp",
159 ddc::DiscreteDomain<DDimX, DDimY>(ghosted_x_domain, ghosted_y_domain),
161
162 ddc::Chunk ghosted_next_temp(
163 "ghosted_next_temp",
164 ddc::DiscreteDomain<DDimX, DDimY>(ghosted_x_domain, ghosted_y_domain),
167
169 ddc::ChunkSpan const ghosted_initial_temp = ghosted_last_temp.span_view();
171
174 ddc::DiscreteDomain<DDimX, DDimY>(x_domain, y_domain),
175 KOKKOS_LAMBDA(ddc::DiscreteElement<DDimX, DDimY> const ixy) {
176 double const x = ddc::coordinate(ddc::DiscreteElement<DDimX>(ixy));
177 double const y = ddc::coordinate(ddc::DiscreteElement<DDimY>(ixy));
178 ghosted_initial_temp(ixy) = 9.999 * ((x * x + y * y) < 0.25);
179 });
181
183 ddc::Chunk ghosted_temp = ddc::create_mirror(ghosted_last_temp.span_cview());
185
187 ddc::parallel_deepcopy(ghosted_temp, ghosted_last_temp);
189
191 display(ddc::coordinate(time_domain.front()), ghosted_temp[x_domain][y_domain]);
193
195 ddc::DiscreteElement<DDimT> last_output_iter = time_domain.front();
197
199 for (ddc::DiscreteElement<DDimT> const iter :
200 time_domain.remove_first(ddc::DiscreteVector<DDimT>(1))) {
202
204 for (ddc::DiscreteVectorElement ix = 0; ix < x_pre_ghost.extents().value(); ++ix) {
206 ghosted_last_temp[x_pre_ghost[ix]][y_domain],
207 ghosted_last_temp[x_pre_mirror[ix]][y_domain]);
208 }
209 for (ddc::DiscreteVectorElement ix = 0; ix < x_post_ghost.extents().value(); ++ix) {
211 ghosted_last_temp[x_post_ghost[ix]][y_domain],
212 ghosted_last_temp[x_post_mirror[ix]][y_domain]);
213 }
214 for (ddc::DiscreteVectorElement iy = 0; iy < y_pre_ghost.extents().value(); ++iy) {
216 ghosted_last_temp[x_domain][y_pre_ghost[iy]],
217 ghosted_last_temp[x_domain][y_pre_mirror[iy]]);
218 }
219 for (ddc::DiscreteVectorElement iy = 0; iy < y_post_ghost.extents().value(); ++iy) {
221 ghosted_last_temp[x_domain][y_post_ghost[iy]],
222 ghosted_last_temp[x_domain][y_post_mirror[iy]]);
223 }
225
227 ddc::ChunkSpan const next_temp(
228 ghosted_next_temp[ddc::DiscreteDomain<DDimX, DDimY>(x_domain, y_domain)]);
229 ddc::ChunkSpan const last_temp(ghosted_last_temp.span_cview());
231
234 next_temp.domain(),
235 KOKKOS_LAMBDA(ddc::DiscreteElement<DDimX, DDimY> const ixy) {
236 ddc::DiscreteElement<DDimX> const ix(ixy);
237 ddc::DiscreteElement<DDimY> const iy(ixy);
238 double const dt = ddc::step<DDimT>();
239
240 next_temp(ix, iy) = last_temp(ix, iy);
241 next_temp(ix, iy) += kx * dt
242 * (last_temp(ix + 1, iy) - 2.0 * last_temp(ix, iy)
243 + last_temp(ix - 1, iy))
244 * invdx2;
245
246 next_temp(ix, iy) += ky * dt
247 * (last_temp(ix, iy + 1) - 2.0 * last_temp(ix, iy)
248 + last_temp(ix, iy - 1))
249 * invdy2;
250 });
252
254 if (iter - last_output_iter >= t_output_period) {
255 last_output_iter = iter;
256 ddc::parallel_deepcopy(ghosted_temp, ghosted_next_temp);
257 display(ddc::coordinate(iter),
258 ghosted_temp[ddc::DiscreteDomain<DDimX, DDimY>(x_domain, y_domain)]);
259 }
261
263 std::swap(ghosted_last_temp, ghosted_next_temp);
265 }
266
268 if (last_output_iter < time_domain.back()) {
269 ddc::parallel_deepcopy(ghosted_temp, ghosted_last_temp);
270 display(ddc::coordinate(time_domain.back()),
271 ghosted_temp[ddc::DiscreteDomain<DDimX, DDimY>(x_domain, y_domain)]);
272 }
274}
KOKKOS_FUNCTION constexpr size_type size() const noexcept
KOKKOS_FUNCTION constexpr span_type span_view() const
KOKKOS_FUNCTION constexpr discrete_element_type front() const noexcept
KOKKOS_FUNCTION constexpr discrete_element_type back() const noexcept
A DiscreteElement identifies an element of the discrete dimension.
A DiscreteVector is a vector in the discrete dimension.
UniformPointSampling models a uniform discretization of the provided continuous dimension.
The top-level namespace of DDC.
auto parallel_deepcopy(ChunkDst &&dst, ChunkSrc &&src)
Copy the content of a borrowed chunk into another.
T host_transform_reduce(Support const &domain, T neutral, BinaryReductionOp &&reduce, UnaryTransformOp &&transform) noexcept
A reduction over a nD domain in serial.
KOKKOS_FUNCTION Coordinate< typename DDims::continuous_dimension_type... > coordinate(DiscreteElement< DDims... > const &c)
void init_discrete_space(Args &&... args)
Initialize (emplace) a global singleton discrete space.
void host_for_each(Support const &domain, Functor &&f) noexcept
iterates over a nD domain in serial
Definition for_each.hpp:73
detail::TaggedVector< CoordinateElement, CDims... > Coordinate
A Coordinate represents a coordinate in the continuous space.
std::ptrdiff_t DiscreteVectorElement
A DiscreteVectorElement is a scalar that represents the difference between two coordinates.
void parallel_for_each(std::string const &label, ExecSpace const &execution_space, Support const &domain, Functor &&f) noexcept
iterates over a nD domain using a given Kokkos execution space
auto create_mirror(Space const &space, ChunkSpan< ElementType, Support, Layout, MemorySpace > const &src)