Skip to content

Commit 4825fae

Browse files
committed
Enable Kokkos OpenACC build
1 parent f02431e commit 4825fae

5 files changed

+228
-140
lines changed

cpp-mdspan/CMakeLists.txt

+31-5
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ endif()
106106
# Users can set FETCHCONTENT_SOURCE_DIR_KOKKOS
107107
# to a local path to Kokkos, to override automatic downloading.
108108

109+
set(Kokkos_ENABLE_SERIAL ON CACHE INTERNAL "")
110+
set(Kokkos_ENABLE_OPENACC ON CACHE INTERNAL "")
111+
109112
FetchContent_Declare(
110113
Kokkos
111114
GIT_REPOSITORY https://github.com/kokkos/kokkos.git
@@ -181,13 +184,36 @@ target_compile_options(miniWeather_serial PRIVATE
181184
)
182185

183186
if (kokkos_POPULATED)
184-
add_executable(miniWeather_kokkos miniWeather_mdspan.cpp miniWeather_common.cpp)
185-
target_include_directories(miniWeather_kokkos PRIVATE "${PROJECT_SOURCE_DIR}")
187+
add_executable(miniWeather_kokkos_serial miniWeather_mdspan.cpp miniWeather_common.cpp)
188+
target_include_directories(miniWeather_kokkos_serial PRIVATE "${PROJECT_SOURCE_DIR}")
189+
190+
target_link_libraries(miniWeather_kokkos_serial PRIVATE Kokkos::kokkos)
191+
target_compile_definitions(miniWeather_kokkos_serial PRIVATE MINIWEATHER_KOKKOS)
192+
target_compile_definitions(miniWeather_kokkos_serial PRIVATE MINIWEATHER_KOKKOS_SERIAL)
193+
194+
# We got mdspan from Kokkos.
195+
target_compile_options(miniWeather_kokkos_serial PRIVATE
196+
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
197+
-Wall>
198+
$<$<CXX_COMPILER_ID:MSVC>:
199+
/W4>
200+
)
201+
endif()
202+
203+
# FIXME (mfh 2025/04/04) Figure out how to pass OpenACC flags to Kokkos.
204+
if (kokkos_POPULATED AND OpenACC_FOUND)
205+
set(Kokkos_ENABLE_OPENACC ON)
206+
207+
add_executable(miniWeather_kokkos_openacc miniWeather_mdspan.cpp miniWeather_common.cpp)
208+
target_include_directories(miniWeather_kokkos_openacc PRIVATE "${PROJECT_SOURCE_DIR}")
209+
210+
target_link_libraries(miniWeather_kokkos_openacc PRIVATE Kokkos::kokkos)
211+
target_compile_definitions(miniWeather_kokkos_openacc PRIVATE MINIWEATHER_KOKKOS)
212+
target_compile_definitions(miniWeather_kokkos_openacc PRIVATE MINIWEATHER_KOKKOS_OPENACC)
186213

187-
target_link_libraries(miniWeather_kokkos PRIVATE Kokkos::kokkos)
188-
target_compile_definitions(miniWeather_kokkos PRIVATE MINIWEATHER_KOKKOS)
189214
# We got mdspan from Kokkos.
190-
target_compile_options(miniWeather_kokkos PRIVATE
215+
target_link_libraries(miniWeather_kokkos_openacc PRIVATE OpenACC::OpenACC_CXX)
216+
target_compile_options(miniWeather_kokkos_openacc PRIVATE
191217
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
192218
-Wall>
193219
$<$<CXX_COMPILER_ID:MSVC>:

cpp-mdspan/miniWeather_common.cpp

+3-96
Original file line numberDiff line numberDiff line change
@@ -10,102 +10,9 @@ make_unique_array_1d(host_memory_space, int X) {
1010
return std::make_unique<double[]>(X);
1111
}
1212

13-
test_case injection(double x , double z) {
14-
auto [hr, ht] = hydro_const_theta(z);
15-
double r = 0.0;
16-
double t = 0.0;
17-
double u = 0.0;
18-
double w = 0.0;
19-
return {r, u, w, t, hr, ht};
20-
}
21-
22-
test_case density_current(double x , double z) {
23-
auto [hr, ht] = hydro_const_theta(z);
24-
double r = 0.0;
25-
double t = sample_ellipse_cosine(x, z, -20.0, xlen/2, 5000.0, 4000.0, 2000.0);
26-
double u = 0.0;
27-
double w = 0.0;
28-
return {r, u, w, t, hr, ht};
29-
}
30-
31-
test_case gravity_waves(double x, double z) {
32-
auto [hr, ht] = hydro_const_bvfreq(z, 0.02);
33-
double r = 0.0;
34-
double t = 0.0;
35-
double u = 15.0;
36-
double w = 0.0;
37-
return {r, u, w, t, hr, ht};
38-
}
39-
40-
test_case thermal(double x, double z) {
41-
auto [hr, ht] = hydro_const_theta(z);
42-
double r = 0.0;
43-
double t = sample_ellipse_cosine(x, z, 3.0, xlen/2,2000.0, 2000.0, 2000.0);
44-
double u = 0.0;
45-
double w = 0.0;
46-
return {r, u, w, t, hr, ht};
47-
}
48-
49-
test_case collision(double x , double z) {
50-
auto [hr, ht] = hydro_const_theta(z);
51-
double r = 0.0;
52-
double t = 0.0;
53-
double u = 0.0;
54-
double w = 0.0;
55-
t = t + sample_ellipse_cosine(x, z, 20.0, xlen/2,2000.0, 2000.0, 2000.0);
56-
t = t + sample_ellipse_cosine(x, z, -20.0, xlen/2,8000.0, 2000.0, 2000.0);
57-
return {r, u, w, t, hr, ht};
58-
}
59-
60-
test_case get_test_case(int data_spec, double x_, double z_) {
61-
if (data_spec == DATA_SPEC_COLLISION ) { return collision(x_, z_); }
62-
if (data_spec == DATA_SPEC_THERMAL ) { return thermal(x_, z_); }
63-
if (data_spec == DATA_SPEC_GRAVITY_WAVES ) { return gravity_waves(x_, z_); }
64-
if (data_spec == DATA_SPEC_DENSITY_CURRENT) { return density_current(x_, z_); }
65-
if (data_spec == DATA_SPEC_INJECTION ) { return injection(x_, z_); }
66-
assert(false);
67-
return test_case{};
68-
}
69-
70-
r_t_pair hydro_const_theta(double z) {
71-
const double theta0 = 300.; //Background potential temperature
72-
const double exner0 = 1.; //Surface-level Exner pressure
73-
double p,exner,rt;
74-
//Establish hydrostatic balance first using Exner pressure
75-
double t = theta0; //Potential Temperature at z
76-
exner = exner0 - grav * z / (cp * theta0); //Exner pressure at z
77-
p = p0 * pow(exner,(cp/rd)); //Pressure at z
78-
rt = pow((p / C0),(1. / gamm)); //rho*theta at z
79-
double r = rt / t; //Density at z
80-
81-
return {r, t};
82-
}
83-
84-
r_t_pair hydro_const_bvfreq(double z, double bv_freq0) {
85-
const double theta0 = 300.; //Background potential temperature
86-
const double exner0 = 1.; //Surface-level Exner pressure
87-
double p, exner, rt;
88-
double t = theta0 * exp( bv_freq0*bv_freq0 / grav * z ); //Pot temp at z
89-
exner = exner0 - grav*grav / (cp * bv_freq0*bv_freq0) * (t - theta0) / (t * theta0); //Exner pressure at z
90-
p = p0 * pow(exner,(cp/rd)); //Pressure at z
91-
rt = pow((p / C0), (1. / gamm)); //rho*theta at z
92-
double r = rt / t; //Density at z
93-
94-
return {r, t};
95-
}
96-
97-
double sample_ellipse_cosine( double x , double z , double amp , double x0 , double z0 , double xrad , double zrad ) {
98-
double dist;
99-
//Compute distance from bubble center
100-
dist = sqrt( ((x-x0)/xrad)*((x-x0)/xrad) + ((z-z0)/zrad)*((z-z0)/zrad) ) * pi / 2.0;
101-
//If the distance from bubble center is less than the radius, create a cos**2 profile
102-
if (dist <= pi / 2.0) {
103-
return amp * pow(cos(dist), 2.0);
104-
} else {
105-
return 0.;
106-
}
107-
}
108-
10913
void finalize() {
14+
#if defined(MINIWEATHER_KOKKOS)
15+
Kokkos::finalize();
16+
#endif
11017
(void) MPI_Finalize();
11118
}

cpp-mdspan/miniWeather_common.hpp

+124-31
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
#include "mdspan/mdspan.hpp"
2121
#include "unique_mdarray.hpp"
2222

23+
#if defined(MINIWEATHER_KOKKOS)
24+
# include "Kokkos_Core.hpp"
25+
# define MINIWEATHER_INLINE_FUNCTION KOKKOS_INLINE_FUNCTION
26+
#else
27+
# define MINIWEATHER_INLINE_FUNCTION inline
28+
#endif
29+
2330
constexpr double pi = 3.14159265358979323846264338327; //Pi
2431
constexpr double grav = 9.8; //Gravitational acceleration (m / s^2)
2532
constexpr double cp = 1004.; //Specific heat of dry air at constant pressure
@@ -251,6 +258,64 @@ struct init_result {
251258
global_arrays<MemorySpace> arrays;
252259
};
253260

261+
struct r_t_pair {
262+
double r;
263+
double t;
264+
};
265+
266+
// Establish hydrostatic balance using constant potential temperature
267+
// (thermally neutral atmosphere)
268+
// z is the input coordinate
269+
// r and t are the output background hydrostatic density and potential temperature
270+
MINIWEATHER_INLINE_FUNCTION
271+
r_t_pair hydro_const_theta(double z) {
272+
const double theta0 = 300.; //Background potential temperature
273+
const double exner0 = 1.; //Surface-level Exner pressure
274+
double p,exner,rt;
275+
//Establish hydrostatic balance first using Exner pressure
276+
double t = theta0; //Potential Temperature at z
277+
exner = exner0 - grav * z / (cp * theta0); //Exner pressure at z
278+
p = p0 * pow(exner,(cp/rd)); //Pressure at z
279+
rt = pow((p / C0),(1. / gamm)); //rho*theta at z
280+
double r = rt / t; //Density at z
281+
282+
return {r, t};
283+
}
284+
285+
//Establish hydrostatic balance using constant Brunt-Vaisala frequency
286+
//z is the input coordinate
287+
//bv_freq0 is the constant Brunt-Vaisala frequency
288+
//r and t are the output background hydrostatic density and potential temperature
289+
MINIWEATHER_INLINE_FUNCTION
290+
r_t_pair hydro_const_bvfreq(double z, double bv_freq0) {
291+
const double theta0 = 300.; //Background potential temperature
292+
const double exner0 = 1.; //Surface-level Exner pressure
293+
double p, exner, rt;
294+
double t = theta0 * exp( bv_freq0*bv_freq0 / grav * z ); //Pot temp at z
295+
exner = exner0 - grav*grav / (cp * bv_freq0*bv_freq0) * (t - theta0) / (t * theta0); //Exner pressure at z
296+
p = p0 * pow(exner,(cp/rd)); //Pressure at z
297+
rt = pow((p / C0), (1. / gamm)); //rho*theta at z
298+
double r = rt / t; //Density at z
299+
300+
return {r, t};
301+
}
302+
303+
//Sample from an ellipse of a specified center, radius, and amplitude at a specified location
304+
//x and z are input coordinates
305+
//amp,x0,z0,xrad,zrad are input amplitude, center, and radius of the ellipse
306+
MINIWEATHER_INLINE_FUNCTION
307+
double sample_ellipse_cosine( double x , double z , double amp , double x0 , double z0 , double xrad , double zrad ) {
308+
double dist;
309+
//Compute distance from bubble center
310+
dist = sqrt( ((x-x0)/xrad)*((x-x0)/xrad) + ((z-z0)/zrad)*((z-z0)/zrad) ) * pi / 2.0;
311+
//If the distance from bubble center is less than the radius, create a cos**2 profile
312+
if (dist <= pi / 2.0) {
313+
return amp * pow(cos(dist), 2.0);
314+
} else {
315+
return 0.;
316+
}
317+
}
318+
254319
struct test_case {
255320
double r;
256321
double u;
@@ -265,43 +330,71 @@ struct test_case {
265330
// hr and ht are output background hydrostatic density and potential temperature at that location.
266331

267332
//This test case is initially balanced but injects fast, cold air from the left boundary near the model top
268-
test_case injection(double x, double z);
333+
MINIWEATHER_INLINE_FUNCTION
334+
test_case injection(double x , double z) {
335+
auto [hr, ht] = hydro_const_theta(z);
336+
double r = 0.0;
337+
double t = 0.0;
338+
double u = 0.0;
339+
double w = 0.0;
340+
return {r, u, w, t, hr, ht};
341+
}
269342

270343
//Initialize a density current (falling cold thermal that propagates along the model bottom)
271-
test_case density_current(double x, double z);
272-
273-
test_case gravity_waves(double x, double z);
344+
MINIWEATHER_INLINE_FUNCTION
345+
test_case density_current(double x , double z) {
346+
auto [hr, ht] = hydro_const_theta(z);
347+
double r = 0.0;
348+
double t = sample_ellipse_cosine(x, z, -20.0, xlen/2, 5000.0, 4000.0, 2000.0);
349+
double u = 0.0;
350+
double w = 0.0;
351+
return {r, u, w, t, hr, ht};
352+
}
353+
354+
MINIWEATHER_INLINE_FUNCTION
355+
test_case gravity_waves(double x, double z) {
356+
auto [hr, ht] = hydro_const_bvfreq(z, 0.02);
357+
double r = 0.0;
358+
double t = 0.0;
359+
double u = 15.0;
360+
double w = 0.0;
361+
return {r, u, w, t, hr, ht};
362+
}
274363

275364
//Rising thermal
276-
test_case thermal(double x, double z);
365+
MINIWEATHER_INLINE_FUNCTION
366+
test_case thermal(double x, double z) {
367+
auto [hr, ht] = hydro_const_theta(z);
368+
double r = 0.0;
369+
double t = sample_ellipse_cosine(x, z, 3.0, xlen/2,2000.0, 2000.0, 2000.0);
370+
double u = 0.0;
371+
double w = 0.0;
372+
return {r, u, w, t, hr, ht};
373+
}
277374

278375
//Colliding thermals
279-
test_case collision(double x, double z);
280-
281-
test_case get_test_case(int data_spec, double x_, double z_);
282-
283-
struct r_t_pair {
284-
double r;
285-
double t;
286-
};
287-
288-
// Establish hydrostatic balance using constant potential temperature
289-
// (thermally neutral atmosphere)
290-
// z is the input coordinate
291-
// r and t are the output background hydrostatic density and potential temperature
292-
r_t_pair hydro_const_theta(double z);
293-
294-
//Establish hydrostatic balance using constant Brunt-Vaisala frequency
295-
//z is the input coordinate
296-
//bv_freq0 is the constant Brunt-Vaisala frequency
297-
//r and t are the output background hydrostatic density and potential temperature
298-
r_t_pair hydro_const_bvfreq(double z, double bv_freq0);
299-
300-
//Sample from an ellipse of a specified center, radius, and amplitude at a specified location
301-
//x and z are input coordinates
302-
//amp,x0,z0,xrad,zrad are input amplitude, center, and radius of the ellipse
303-
double sample_ellipse_cosine(double x, double z, double amp, double x0, double z0,
304-
double xrad, double zrad);
376+
MINIWEATHER_INLINE_FUNCTION
377+
test_case collision(double x , double z) {
378+
auto [hr, ht] = hydro_const_theta(z);
379+
double r = 0.0;
380+
double t = 0.0;
381+
double u = 0.0;
382+
double w = 0.0;
383+
t = t + sample_ellipse_cosine(x, z, 20.0, xlen/2,2000.0, 2000.0, 2000.0);
384+
t = t + sample_ellipse_cosine(x, z, -20.0, xlen/2,8000.0, 2000.0, 2000.0);
385+
return {r, u, w, t, hr, ht};
386+
}
387+
388+
MINIWEATHER_INLINE_FUNCTION
389+
test_case get_test_case(int data_spec, double x, double z) {
390+
if (data_spec == DATA_SPEC_COLLISION ) { return collision(x, z); }
391+
if (data_spec == DATA_SPEC_THERMAL ) { return thermal(x, z); }
392+
if (data_spec == DATA_SPEC_GRAVITY_WAVES ) { return gravity_waves(x, z); }
393+
if (data_spec == DATA_SPEC_DENSITY_CURRENT) { return density_current(x, z); }
394+
if (data_spec == DATA_SPEC_INJECTION ) { return injection(x, z); }
395+
assert(false);
396+
return test_case{};
397+
}
305398

306399
struct reduction_result {
307400
double mass;

cpp-mdspan/miniWeather_generic_algs.hpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#pragma once
22

33
#include "miniWeather_common.hpp"
4+
#if defined(MINIWEATHER_KOKKOS)
5+
# include "Kokkos_Core.hpp"
6+
#endif
47

58
// Perform a single time step.
69
// Time steps are dimensionally split and
@@ -87,7 +90,9 @@ init_result<MemorySpace> init(
8790
int *argc , char ***argv)
8891
{
8992
(void) MPI_Init(argc,argv);
90-
93+
#if defined(MINIWEATHER_KOKKOS)
94+
Kokkos::initialize(*argc, *argv);
95+
#endif
9196
/////////////////////////////////////////////////////////////
9297
// BEGIN MPI DUMMY SECTION
9398
// TODO: (1) GET NUMBER OF MPI RANKS
@@ -205,6 +210,3 @@ reduction_result reductions(
205210
.te = glob[1]
206211
};
207212
}
208-
209-
210-

0 commit comments

Comments
 (0)