From 44a1160962201368f01a43c1b474c249b2c41e0c Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 12:50:34 +0300 Subject: [PATCH 01/16] Added an additional comment --- src/standalone/config_loader.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/standalone/config_loader.cc b/src/standalone/config_loader.cc index 36e33e3..b89adb5 100644 --- a/src/standalone/config_loader.cc +++ b/src/standalone/config_loader.cc @@ -152,7 +152,7 @@ update_config(AcMeshInfo* config) config->real_params[AC_G_CONST]; config->real_params[AC_sq2GM_star] = AcReal(sqrt(AcReal(2) * config->real_params[AC_GM_star])); -#if VERBOSE_PRINTING +#if VERBOSE_PRINTING // Defined in astaroth.h printf("###############################################################\n"); printf("Config dimensions recalculated:\n"); print(*config); From 7e4088924590f66c52238e5e7bfb7e7187ec2bd7 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 12:54:36 +0300 Subject: [PATCH 02/16] Grid and subgrid dimensions are now only printed if VERBOSE_PRINTING == 1 --- src/core/astaroth.cu | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/astaroth.cu b/src/core/astaroth.cu index 635bd58..9c37117 100644 --- a/src/core/astaroth.cu +++ b/src/core/astaroth.cu @@ -77,7 +77,7 @@ acCheckDeviceAvailability(void) { int device_count; // Separate from num_devices to avoid side effects ERRCHK_CUDA_ALWAYS(cudaGetDeviceCount(&device_count)); - if (device_count > 0) + if (device_count > 0) return AC_SUCCESS; else return AC_FAILURE; @@ -120,12 +120,14 @@ acInit(const AcMeshInfo& config) ERRCHK_ALWAYS(subgrid.n.y >= STENCIL_ORDER); ERRCHK_ALWAYS(subgrid.n.z >= STENCIL_ORDER); +#if VERBOSE_PRINTING // clang-format off printf("Grid m "); printInt3(grid.m); printf("\n"); printf("Grid n "); printInt3(grid.n); printf("\n"); printf("Subrid m "); printInt3(subgrid.m); printf("\n"); printf("Subrid n "); printInt3(subgrid.n); printf("\n"); // clang-format on +#endif // Initialize the devices for (int i = 0; i < num_devices; ++i) { @@ -271,8 +273,7 @@ AcResult acIntegrateStep(const int& isubstep, const AcReal& dt) { const int3 start = (int3){NGHOST, NGHOST, NGHOST}; - const int3 end = (int3){NGHOST + subgrid.n.x, NGHOST + subgrid.n.y, - NGHOST + subgrid.n.z}; + const int3 end = (int3){NGHOST + subgrid.n.x, NGHOST + subgrid.n.y, NGHOST + subgrid.n.z}; for (int i = 0; i < num_devices; ++i) { rkStep(devices[i], STREAM_PRIMARY, isubstep, start, end, dt); } From 75fb756ad4efddf6d931d32ed1353cbc82160153 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 13:16:41 +0300 Subject: [PATCH 03/16] Autoformatted with clang-format. Clang-format does not support indented defines as far as I know, so this will have to do. The alternative would be not to use autoformatting at all (or some other tool). --- include/astaroth.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/include/astaroth.h b/include/astaroth.h index 42197bc..e0ebe59 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -68,15 +68,15 @@ extern "C" { #include "user.h" #ifndef USER_PROVIDED_DEFINES - #define STENCIL_ORDER (6) - #define NGHOST (STENCIL_ORDER/2) - #define LHYDRO (1) - #define LDENSITY (1) - #define LFORCING (1) - #define LINDUCTION (1) - #define LENTROPY (1) - #define LTEMPERATURE (0) - #define LMAGNETIC LINDUCTION +#define STENCIL_ORDER (6) +#define NGHOST (STENCIL_ORDER / 2) +#define LHYDRO (1) +#define LDENSITY (1) +#define LFORCING (1) +#define LINDUCTION (1) +#define LENTROPY (1) +#define LTEMPERATURE (0) +#define LMAGNETIC LINDUCTION #endif #define AC_THERMAL_CONDUCTIVITY (AcReal(0.001)) // TODO: make an actual config parameter @@ -177,23 +177,23 @@ extern "C" { * ============================================================================= */ // clang-format off -#ifdef LHYDRO +#ifdef LHYDRO #define AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) \ FUNC(VTXBUF_UUX), \ FUNC(VTXBUF_UUY), \ - FUNC(VTXBUF_UUZ), + FUNC(VTXBUF_UUZ), #else #define AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) #endif -#ifdef LDENSITY +#ifdef LDENSITY #define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ - FUNC(VTXBUF_LNRHO), + FUNC(VTXBUF_LNRHO), #else #define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) #endif -#ifdef LENTROPY +#ifdef LENTROPY #define AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) \ FUNC(VTXBUF_ENTROPY), #else @@ -214,7 +214,7 @@ extern "C" { AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) \ AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ -//MR: Temperature must not have an additional variable slot, but should sit on the +//MR: Temperature must not have an additional variable slot, but should sit on the // same as entropy. #ifndef USER_PROVIDED #if LTEMPERATURE @@ -280,7 +280,7 @@ typedef enum { RTYPE_MAX, RTYPE_MIN, RTYPE_RMS, RTYPE_RMS_EXP, NUM_REDUCTION_TYP typedef enum { AC_FOR_INT_PARAM_TYPES(AC_GEN_ID), NUM_INT_PARAM_TYPES } AcIntParam; typedef enum { AC_FOR_REAL_PARAM_TYPES(AC_GEN_ID), NUM_REAL_PARAM_TYPES } AcRealParam; -//typedef enum { AC_FOR_VEC_PARAM_TYPES(AC_GEN_ID), NUM_VEC_PARAM_TYPES } AcVecParam; +// typedef enum { AC_FOR_VEC_PARAM_TYPES(AC_GEN_ID), NUM_VEC_PARAM_TYPES } AcVecParam; extern const char* intparam_names[]; // Defined in astaroth.cu extern const char* realparam_names[]; // Defined in astaroth.cu @@ -288,7 +288,7 @@ extern const char* realparam_names[]; // Defined in astaroth.cu typedef struct { int int_params[NUM_INT_PARAM_TYPES]; AcReal real_params[NUM_REAL_PARAM_TYPES]; - //AcReal* vec_params[NUM_VEC_PARAM_TYPES]; + // AcReal* vec_params[NUM_VEC_PARAM_TYPES]; } AcMeshInfo; /* From fc96283c37176470870b0c80f0b830f1d5688202 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 13:22:14 +0300 Subject: [PATCH 04/16] Reordered logical flags in a more logical order, density -> hydro -> induction -> entropy -> others --- include/astaroth.h | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/include/astaroth.h b/include/astaroth.h index e0ebe59..9eb78d2 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -70,13 +70,12 @@ extern "C" { #ifndef USER_PROVIDED_DEFINES #define STENCIL_ORDER (6) #define NGHOST (STENCIL_ORDER / 2) -#define LHYDRO (1) #define LDENSITY (1) -#define LFORCING (1) +#define LHYDRO (1) #define LINDUCTION (1) #define LENTROPY (1) #define LTEMPERATURE (0) -#define LMAGNETIC LINDUCTION +#define LFORCING (1) #endif #define AC_THERMAL_CONDUCTIVITY (AcReal(0.001)) // TODO: make an actual config parameter @@ -177,6 +176,13 @@ extern "C" { * ============================================================================= */ // clang-format off +#ifdef LDENSITY +#define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ + FUNC(VTXBUF_LNRHO), +#else +#define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) +#endif + #ifdef LHYDRO #define AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) \ FUNC(VTXBUF_UUX), \ @@ -186,11 +192,13 @@ extern "C" { #define AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) #endif -#ifdef LDENSITY -#define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ - FUNC(VTXBUF_LNRHO), +#ifdef LINDUCTION +#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ + FUNC(VTXBUF_AX), \ + FUNC(VTXBUF_AY), \ + FUNC(VTXBUF_AZ), #else -#define AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) +#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) #endif #ifdef LENTROPY @@ -200,15 +208,6 @@ extern "C" { #define AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) #endif -#ifdef LMAGNETIC -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ - FUNC(VTXBUF_AX), \ - FUNC(VTXBUF_AY), \ - FUNC(VTXBUF_AZ), -#else -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) -#endif - #define AC_FOR_VTXBUF_HANDLES(FUNC) AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) \ AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) \ From 8ca09668c1321ba4063e964db55d4e1923900c6c Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 13:28:52 +0300 Subject: [PATCH 05/16] Added an advance notice about LINDUCTION to be renamed to LMAGNETIC in the near future throughout the project. LMAGNETIC would be better name since he define is used to enable the magnetic field. --- include/astaroth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/astaroth.h b/include/astaroth.h index 9eb78d2..a6e0339 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -72,7 +72,7 @@ extern "C" { #define NGHOST (STENCIL_ORDER / 2) #define LDENSITY (1) #define LHYDRO (1) -#define LINDUCTION (1) +#define LINDUCTION (1) // %JP: TO BE RENAMED TO LMAGNETIC TODO #define LENTROPY (1) #define LTEMPERATURE (0) #define LFORCING (1) From 30c21ff420955b29ee0be4e0a802c518aa9f23b0 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 13:31:50 +0300 Subject: [PATCH 06/16] Formatting: defines stay indented if clang-format is turned off temporarily --- include/astaroth.h | 61 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/include/astaroth.h b/include/astaroth.h index a6e0339..e198bd0 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -67,16 +67,18 @@ extern "C" { // logical switches #include "user.h" +// clang-format off #ifndef USER_PROVIDED_DEFINES -#define STENCIL_ORDER (6) -#define NGHOST (STENCIL_ORDER / 2) -#define LDENSITY (1) -#define LHYDRO (1) -#define LINDUCTION (1) // %JP: TO BE RENAMED TO LMAGNETIC TODO -#define LENTROPY (1) -#define LTEMPERATURE (0) -#define LFORCING (1) + #define STENCIL_ORDER (6) + #define NGHOST (STENCIL_ORDER / 2) + #define LDENSITY (1) + #define LHYDRO (1) + #define LINDUCTION (1) // %JP: TO BE RENAMED TO LMAGNETIC TODO + #define LENTROPY (1) + #define LTEMPERATURE (0) + #define LFORCING (1) #endif +// clang-format on #define AC_THERMAL_CONDUCTIVITY (AcReal(0.001)) // TODO: make an actual config parameter @@ -208,22 +210,19 @@ extern "C" { #define AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) #endif +//MR: Temperature must not have an additional variable slot, but should sit on the +// same as entropy. +#if LTEMPERATURE + #define AC_FOR_TEMPERATURE_VTXBUF_HANDLES(FUNC)\ + FUNC(VTXBUF_TEMPERATURE), +#else + #define AC_FOR_TEMPERATURE_VTXBUF_HANDLES(FUNC) +#endif + #define AC_FOR_VTXBUF_HANDLES(FUNC) AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) \ AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) \ AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ - -//MR: Temperature must not have an additional variable slot, but should sit on the -// same as entropy. -#ifndef USER_PROVIDED - #if LTEMPERATURE - #define AC_FOR_TEMPERATURE_VTXBUF_HANDLES(FUNC)\ - FUNC(VTXBUF_TEMPERATURE), - #else - #define AC_FOR_TEMPERATURE_VTXBUF_HANDLES(FUNC) - #endif -#endif - // clang-format on /* @@ -231,19 +230,21 @@ extern "C" { * Single/double precision switch * ============================================================================= */ +// clang-format off #if AC_DOUBLE_PRECISION == 1 -typedef double AcReal; -typedef double3 AcReal3; -#define AC_REAL_MAX (DBL_MAX) -#define AC_REAL_MIN (DBL_MIN) -#define AC_REAL_EPSILON (DBL_EPSILON) + typedef double AcReal; + typedef double3 AcReal3; + #define AC_REAL_MAX (DBL_MAX) + #define AC_REAL_MIN (DBL_MIN) + #define AC_REAL_EPSILON (DBL_EPSILON) #else -typedef float AcReal; -typedef float3 AcReal3; -#define AC_REAL_MAX (FLT_MAX) -#define AC_REAL_MIN (FLT_MIN) -#define AC_REAL_EPSILON (FLT_EPSILON) + typedef float AcReal; + typedef float3 AcReal3; + #define AC_REAL_MAX (FLT_MAX) + #define AC_REAL_MIN (FLT_MIN) + #define AC_REAL_EPSILON (FLT_EPSILON) #endif +// clang-format on typedef struct { AcReal3 row[3]; From b694702cf85066b734bbca4ddbbe634b6133fd00 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 17:11:21 +0300 Subject: [PATCH 07/16] Removed an old comment --- include/astaroth.h | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/include/astaroth.h b/include/astaroth.h index e198bd0..88cb1bc 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -396,36 +396,4 @@ AcResult acSynchronize(void); /* End extern "C" */ #ifdef __cplusplus } -#endif - -/* - * ============================================================================= - * Notes - * ============================================================================= - */ -/* -typedef enum { - VTX_BUF_LNRHO, - VTX_BUF_UUX, - VTX_BUF_UUY, - VTX_BUF_UUZ, - NUM_VERTEX_BUFFER_HANDLES -} VertexBufferHandle - -// LNRHO etc -typedef struct { - AcReal* data; -} VertexBuffer; - -// Host -typedef struct { - VertexBuffer vertex_buffers[NUM_VERTEX_BUFFER_HANDLES]; - MeshInfo info; -} Mesh; - -// Device -typedef struct { - VertexBuffer in[NUM_VERTEX_BUFFER_HANDLES]; - VertexBuffer out[NUM_VERTEX_BUFFER_HANDLES]; -} VertexBufferArray; -*/ +#endif \ No newline at end of file From 9b45716186e58e84bffeb5a7a64f332b565cd906 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Thu, 27 Jun 2019 18:12:14 +0300 Subject: [PATCH 08/16] Modified user.h such that astaroth compiles with Pencil Code. Note that this is a temporary fix: we should ultimately set the default parameters for all the logical switches in astaroth.h and let the user redefine them at will, either with the DSL or with user.h --- include/user.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/user.h b/include/user.h index c2075b4..39fc580 100644 --- a/include/user.h +++ b/include/user.h @@ -11,6 +11,12 @@ #else #define AC_DOUBLE_PRECISION 0 #endif + + #define LINDUCTION (LMAGNETIC) // TODO set default to 0 before including user.h + #define LENTROPY (1) // TODO above + #define LFORCING (1) // TODO above + #define STENCIL_ORDER (6) // nghost is not 1, 2 or 3 (as it is not fetched from fortran yet). This causes the compilation to fail. TODO remove this line + #define USER_PROVIDED_DEFINES #endif From 0c63d55fd7c42357ec9e46860e82849517eda3bf Mon Sep 17 00:00:00 2001 From: jpekkila Date: Sat, 29 Jun 2019 10:49:15 +0300 Subject: [PATCH 09/16] Worked around a compiler bug in CUDA 9.1, which caused an "Internal Compiler Error (codegen): "there was an error in verifying the lgenfe output!". Apparently the compiler got confused by overloaded is_valid() if the input parameter was not passed as a reference in both cases. --- src/core/kernels/kernels.cuh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/kernels/kernels.cuh b/src/core/kernels/kernels.cuh index 97d0803..1ff9051 100644 --- a/src/core/kernels/kernels.cuh +++ b/src/core/kernels/kernels.cuh @@ -426,7 +426,7 @@ cross(const AcReal3& a, const AcReal3& b) } static __host__ __device__ __forceinline__ bool -is_valid(const AcReal a) +is_valid(const AcReal& a) { return !isnan(a) && !isinf(a); } @@ -546,7 +546,7 @@ normalized(const AcReal3& vec) // Sinusoidal forcing // https://arxiv.org/pdf/1704.04676.pdf // NOTE: This method of forcing is depracated. However, it will remain in here -// until a corresponding scheme exists in the new code. +// until a corresponding scheme exists in the new code. __constant__ AcReal3 forcing_vec; __constant__ AcReal forcing_phi; static __device__ __forceinline__ AcReal3 From d9be66f65f6f6efa4de753f7e0352aad5c7b35d7 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 13:40:24 +0300 Subject: [PATCH 10/16] NOTE: Renamed LINDUCTION to LMAGNETIC throughout the project. --- acc/mhd_solver/stencil_process.sps | 6 +++--- acc/pseudodisk/stencil_process_gravx.sps | 6 +++--- acc/pseudodisk/stencil_process_isotherm_gravx.sps | 4 ++-- acc/pseudodisk/stencil_process_isotherm_linegrav.sps | 4 ++-- acc/pseudodisk/stencil_process_linegrav.sps | 6 +++--- acc/samples/common_header.h | 10 +++++----- include/astaroth.h | 12 ++++++------ include/user.h | 6 +++--- src/standalone/model/model_rk3.cc | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/acc/mhd_solver/stencil_process.sps b/acc/mhd_solver/stencil_process.sps index a52f6ac..cb121a7 100644 --- a/acc/mhd_solver/stencil_process.sps +++ b/acc/mhd_solver/stencil_process.sps @@ -1,4 +1,4 @@ -#define LINDUCTION (1) +#define LMAGNETIC (1) #define LENTROPY (1) #define LTEMPERATURE (0) #define LGRAVITY (0) @@ -247,7 +247,7 @@ in Vector uu = (int3) {VTXBUF_UUX, VTXBUF_UUY, VTXBUF_UUZ}; out Vector out_uu = (int3) {VTXBUF_UUX,VTXBUF_UUY,VTXBUF_UUZ}; -#if LINDUCTION +#if LMAGNETIC in Vector aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; out Vector out_aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; #endif @@ -266,7 +266,7 @@ Kernel void solve(Scalar dt) { out_lnrho = rk3(out_lnrho, lnrho, continuity(uu, lnrho), dt); - #if LINDUCTION + #if LMAGNETIC out_aa = rk3(out_aa, aa, induction(uu, aa), dt); #endif diff --git a/acc/pseudodisk/stencil_process_gravx.sps b/acc/pseudodisk/stencil_process_gravx.sps index 32d980a..0ccb4f9 100644 --- a/acc/pseudodisk/stencil_process_gravx.sps +++ b/acc/pseudodisk/stencil_process_gravx.sps @@ -1,4 +1,4 @@ -#define LINDUCTION (1) +#define LMAGNETIC (1) #define LENTROPY (1) @@ -200,7 +200,7 @@ in Vector uu = (int3) {VTXBUF_UUX, VTXBUF_UUY, VTXBUF_UUZ}; out Vector out_uu = (int3) {VTXBUF_UUX,VTXBUF_UUY,VTXBUF_UUZ}; -#if LINDUCTION +#if LMAGNETIC in Vector aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; out Vector out_aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; #endif @@ -214,7 +214,7 @@ Kernel void solve(Scalar dt) { WRITE(out_lnrho, RK3(out_lnrho, lnrho, continuity(uu, lnrho), dt)); - #if LINDUCTION + #if LMAGNETIC WRITE(out_aa, RK3(out_aa, aa, induction(uu, aa), dt)); #endif diff --git a/acc/pseudodisk/stencil_process_isotherm_gravx.sps b/acc/pseudodisk/stencil_process_isotherm_gravx.sps index f79b7ff..9584774 100644 --- a/acc/pseudodisk/stencil_process_isotherm_gravx.sps +++ b/acc/pseudodisk/stencil_process_isotherm_gravx.sps @@ -117,7 +117,7 @@ out Scalar out_lnrho = VTXBUF_LNRHO; in Vector uu = (int3) {VTXBUF_UUX, VTXBUF_UUY, VTXBUF_UUZ}; out Vector out_uu = (int3) {VTXBUF_UUX,VTXBUF_UUY,VTXBUF_UUZ}; -#if LINDUCTION +#if LMAGNETIC in Vector aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; out Vector out_aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; #endif @@ -126,7 +126,7 @@ Kernel void solve(Scalar dt) { WRITE(out_lnrho, RK3(out_lnrho, lnrho, continuity(uu, lnrho), dt)); - #if LINDUCTION + #if LMAGNETIC WRITE(out_aa, RK3(out_aa, aa, induction(uu, aa), dt)); #endif diff --git a/acc/pseudodisk/stencil_process_isotherm_linegrav.sps b/acc/pseudodisk/stencil_process_isotherm_linegrav.sps index a2b83f1..9f90e7c 100644 --- a/acc/pseudodisk/stencil_process_isotherm_linegrav.sps +++ b/acc/pseudodisk/stencil_process_isotherm_linegrav.sps @@ -122,7 +122,7 @@ out Scalar out_lnrho = VTXBUF_LNRHO; in Vector uu = (int3) {VTXBUF_UUX, VTXBUF_UUY, VTXBUF_UUZ}; out Vector out_uu = (int3) {VTXBUF_UUX,VTXBUF_UUY,VTXBUF_UUZ}; -#if LINDUCTION +#if LMAGNETIC in Vector aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; out Vector out_aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; #endif @@ -131,7 +131,7 @@ Kernel void solve(Scalar dt) { WRITE(out_lnrho, RK3(out_lnrho, lnrho, continuity(uu, lnrho), dt)); - #if LINDUCTION + #if LMAGNETIC WRITE(out_aa, RK3(out_aa, aa, induction(uu, aa), dt)); #endif diff --git a/acc/pseudodisk/stencil_process_linegrav.sps b/acc/pseudodisk/stencil_process_linegrav.sps index ecc6c99..e42e680 100644 --- a/acc/pseudodisk/stencil_process_linegrav.sps +++ b/acc/pseudodisk/stencil_process_linegrav.sps @@ -1,4 +1,4 @@ -#define LINDUCTION (1) +#define LMAGNETIC (1) #define LENTROPY (1) @@ -205,7 +205,7 @@ in Vector uu = (int3) {VTXBUF_UUX, VTXBUF_UUY, VTXBUF_UUZ}; out Vector out_uu = (int3) {VTXBUF_UUX,VTXBUF_UUY,VTXBUF_UUZ}; -#if LINDUCTION +#if LMAGNETIC in Vector aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; out Vector out_aa = (int3) {VTXBUF_AX,VTXBUF_AY,VTXBUF_AZ}; #endif @@ -219,7 +219,7 @@ Kernel void solve(Scalar dt) { WRITE(out_lnrho, RK3(out_lnrho, lnrho, continuity(uu, lnrho), dt)); - #if LINDUCTION + #if LMAGNETIC WRITE(out_aa, RK3(out_aa, aa, induction(uu, aa), dt)); #endif diff --git a/acc/samples/common_header.h b/acc/samples/common_header.h index 14eed0c..7168873 100644 --- a/acc/samples/common_header.h +++ b/acc/samples/common_header.h @@ -76,7 +76,7 @@ extern "C" { // L-prefix inherited from the old Astaroth, no idea what it means // MV: L means a Logical switch variale, something having true of false value. #define LFORCING (0) // Note: forcing is disabled currently in the files generated by acc (compiler of our DSL) -#define LINDUCTION (1) +#define LMAGNETIC (1) #define LENTROPY (1) #define LTEMPERATURE (0) @@ -185,13 +185,13 @@ extern "C" { FUNC(VTXBUF_UUZ), \ // FUNC(VTXBUF_DYE), -#if LINDUCTION -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC)\ +#if LMAGNETIC +#define AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC)\ FUNC(VTXBUF_AX), \ FUNC(VTXBUF_AY), \ FUNC(VTXBUF_AZ), #else -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) +#define AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC) #endif #if LENTROPY @@ -210,7 +210,7 @@ extern "C" { #define AC_FOR_VTXBUF_HANDLES(FUNC)\ AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC)\ - AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC)\ + AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC)\ AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC)\ AC_FOR_TEMPERATURE_VTXBUF_HANDLES(FUNC) // clang-format on diff --git a/include/astaroth.h b/include/astaroth.h index 88cb1bc..c3d8f82 100644 --- a/include/astaroth.h +++ b/include/astaroth.h @@ -73,7 +73,7 @@ extern "C" { #define NGHOST (STENCIL_ORDER / 2) #define LDENSITY (1) #define LHYDRO (1) - #define LINDUCTION (1) // %JP: TO BE RENAMED TO LMAGNETIC TODO + #define LMAGNETIC (1) #define LENTROPY (1) #define LTEMPERATURE (0) #define LFORCING (1) @@ -194,13 +194,13 @@ extern "C" { #define AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) #endif -#ifdef LINDUCTION -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ +#ifdef LMAGNETIC +#define AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC) \ FUNC(VTXBUF_AX), \ FUNC(VTXBUF_AY), \ FUNC(VTXBUF_AZ), #else -#define AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) +#define AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC) #endif #ifdef LENTROPY @@ -222,7 +222,7 @@ extern "C" { #define AC_FOR_VTXBUF_HANDLES(FUNC) AC_FOR_HYDRO_VTXBUF_HANDLES(FUNC) \ AC_FOR_DENSITY_VTXBUF_HANDLES(FUNC) \ AC_FOR_ENTROPY_VTXBUF_HANDLES(FUNC) \ - AC_FOR_INDUCTION_VTXBUF_HANDLES(FUNC) \ + AC_FOR_MAGNETIC_VTXBUF_HANDLES(FUNC) \ // clang-format on /* @@ -396,4 +396,4 @@ AcResult acSynchronize(void); /* End extern "C" */ #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/include/user.h b/include/user.h index 39fc580..2d4e33a 100644 --- a/include/user.h +++ b/include/user.h @@ -1,3 +1,4 @@ +// clang-format off #ifdef PENCIL_ASTAROTH #include "../cparam.inc_c.h" @@ -6,17 +7,16 @@ #include "PC_moduleflags.h" #define CONFIG_PATH #define AC_MULTIGPU_ENABLED (false) - #ifdef DOUBLE_PRECISION + #ifdef DOUBLE_PRECISION #define AC_DOUBLE_PRECISION 1 #else #define AC_DOUBLE_PRECISION 0 #endif - #define LINDUCTION (LMAGNETIC) // TODO set default to 0 before including user.h #define LENTROPY (1) // TODO above #define LFORCING (1) // TODO above #define STENCIL_ORDER (6) // nghost is not 1, 2 or 3 (as it is not fetched from fortran yet). This causes the compilation to fail. TODO remove this line #define USER_PROVIDED_DEFINES #endif - +// clang-format on diff --git a/src/standalone/model/model_rk3.cc b/src/standalone/model/model_rk3.cc index 547cc63..dd04bcf 100644 --- a/src/standalone/model/model_rk3.cc +++ b/src/standalone/model/model_rk3.cc @@ -745,7 +745,7 @@ solve_alpha_step(const int step_number, const ModelScalar dt, const int i, const ModelScalar rate_of_change[NUM_VTXBUF_HANDLES] = {0}; rate_of_change[VTXBUF_LNRHO] = continuity(uu, lnrho); -#if LINDUCTION +#if LMAGNETIC const ModelVectorData aa = read_data(i, j, k, in.vertex_buffer, (int3){VTXBUF_AX, VTXBUF_AY, VTXBUF_AZ}); const ModelVector aa_res = induction(uu, aa); From a3ca6cf1327ff072e0b30717e9d9db12210ac2dd Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 13:56:05 +0300 Subject: [PATCH 11/16] Added skeletons for packing parts of the ghost zones into buffers to speed up data transfers --- src/core/device.cu | 21 +++++++++++++++++++++ src/core/device.cuh | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/src/core/device.cu b/src/core/device.cu index 6df10f7..dda8494 100644 --- a/src/core/device.cu +++ b/src/core/device.cu @@ -42,6 +42,10 @@ __constant__ Grid globalGrid; #define DEVICE_1D_COMPDOMAIN_IDX(i, j, k) ((i) + (j)*DCONST_INT(AC_nx) + (k)*DCONST_INT(AC_nxy)) #include "kernels/kernels.cuh" +#if PACKED_DATA_TRANSFERS // Defined in device.cuh +// #include "kernels/pack_unpack.cuh" +#endif + struct device_s { int id; AcMeshInfo local_config; @@ -53,6 +57,11 @@ struct device_s { VertexBufferArray vba; AcReal* reduce_scratchpad; AcReal* reduce_result; + +#if PACKED_DATA_TRANSFERS +// Declare memory for buffers needed for packed data transfers here +// AcReal* data_packing_buffer; +#endif }; AcResult @@ -154,6 +163,10 @@ createDevice(const int id, const AcMeshInfo device_config, Device* device_handle cudaMalloc(&device->reduce_scratchpad, AC_VTXBUF_COMPDOMAIN_SIZE_BYTES(device_config))); ERRCHK_CUDA_ALWAYS(cudaMalloc(&device->reduce_result, sizeof(AcReal))); +#if PACKED_DATA_TRANSFERS +// Allocate data required for packed transfers here (cudaMalloc) +#endif + // Device constants ERRCHK_CUDA_ALWAYS(cudaMemcpyToSymbol(d_mesh_info, &device_config, sizeof(device_config), 0, cudaMemcpyHostToDevice)); @@ -184,6 +197,10 @@ destroyDevice(Device device) cudaFree(device->reduce_scratchpad); cudaFree(device->reduce_result); +#if PACKED_DATA_TRANSFERS +// Free data required for packed tranfers here (cudaFree) +#endif + // Concurrency for (int i = 0; i < NUM_STREAM_TYPES; ++i) cudaStreamDestroy(device->streams[i]); @@ -373,3 +390,7 @@ loadGlobalGrid(const Device device, const Grid grid) cudaMemcpyToSymbol(globalGrid, &grid, sizeof(grid), 0, cudaMemcpyHostToDevice)); return AC_SUCCESS; } + +#if PACKED_DATA_TRANSFERS +// Functions for calling packed data transfers +#endif diff --git a/src/core/device.cuh b/src/core/device.cuh index 28dbd50..1e9becc 100644 --- a/src/core/device.cuh +++ b/src/core/device.cuh @@ -98,3 +98,8 @@ AcResult loadDeviceConstant(const Device device, const AcRealParam param, const /** */ AcResult loadGlobalGrid(const Device device, const Grid grid); + +// #define PACKED_DATA_TRANSFERS (1) %JP: placeholder for optimized ghost zone packing and transfers +#if PACKED_DATA_TRANSFERS +// Declarations used for packed data transfers +#endif From 30b7cda35c9f37b9e8d3d19605c6d7b0ff882792 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 14:42:36 +0300 Subject: [PATCH 12/16] Testing the git commands for creating feature branches and merging them back to master --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0f75b17..1e7ce72 100644 --- a/README.md +++ b/README.md @@ -121,3 +121,4 @@ Modules used when compiling the code on TIARA cluster. * openmpi/1.10.2_ic16.0 * gcc/5.3.0 * cuda/9.0 + From 11ceca4cb1d77bfc733386eb7c2ea157f1ece4aa Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 14:54:55 +0300 Subject: [PATCH 13/16] Second test commit (feature branches) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 1e7ce72..0f75b17 100644 --- a/README.md +++ b/README.md @@ -121,4 +121,3 @@ Modules used when compiling the code on TIARA cluster. * openmpi/1.10.2_ic16.0 * gcc/5.3.0 * cuda/9.0 - From 2d91df19dcb3298d843b3355295884263fb7c58e Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 16:06:15 +0300 Subject: [PATCH 14/16] Added a flowchart on how to commit to Astaroth --- doc/commitflowchart.drawio | 1 + doc/commitflowchart.png | Bin 0 -> 56130 bytes 2 files changed, 1 insertion(+) create mode 100644 doc/commitflowchart.drawio create mode 100644 doc/commitflowchart.png diff --git a/doc/commitflowchart.drawio b/doc/commitflowchart.drawio new file mode 100644 index 0000000..e62eedb --- /dev/null +++ b/doc/commitflowchart.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/doc/commitflowchart.png b/doc/commitflowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..8b6ccc2cdf79932839827873c5fd7d8d66fee1ec GIT binary patch literal 56130 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 I)Ey)LAKnekTL1t6 literal 0 HcmV?d00001 From 7dc5161056bc873073da3baf0b2c61ea979ccb20 Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 13:44:55 +0000 Subject: [PATCH 15/16] Added guidelines for contributing to the project. --- README.md | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0f75b17..62a5445 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ # Astaroth - A Multi-GPU library for generic stencil computations -Astaroth is a single-node multi-GPU library for multiphysics and other problems, which involve stencil computations in a discrete mesh. It's licenced under the terms of the GNU General Public Licence, version 3, or later (see [LICENCE.txt](https://bitbucket.org/miikkavaisala/astaroth-code/src/master/astaroth_2.0/LICENCE.txt)). Astaroth ships with a domain-specific language, that can be used to translate high-level representation of the stencil computations into a heavily inlined GPU pipeline. +Astaroth is a single-node multi-GPU library for multiphysics and other problems, which involve stencil computations in a discrete mesh. It's licenced under the terms of the GNU General Public Licence, version 3, or later (see [LICENCE.txt](https://bitbucket.org/miikkavaisala/astaroth-code/src/master/astaroth_2.0/LICENCE.txt)). Astaroth ships with a domain-specific language that can be used to translate high-level representations of various stencil operations into efficient CUDA kernels. ## System requirements NVIDIA GPU with >= 3.0 compute capability. See https://en.wikipedia.org/wiki/CUDA#GPUs_supported. -## Building (3rd party libraries) +## Building (3rd party libraries for real-time visualization) 1. `cd 3rdparty` 1. `./setup_dependencies.sh` Note: this may take some time. @@ -60,6 +60,43 @@ Run `doxygen doxyfile` in astaroth_2.0 directory. The generated files can be fou If you have clang-format, you may run `scripts/fix_style.sh`. This script will recursively fix style of all the source files down from the current working directory. The script will ask for a confirmation before making any changes. ## Directory structure +TODO + +## Contributing + +0. **Do not break existing functionality.** Do not modify the interface functions declared in astaroth.h and device.cuh in any way. Bug fixes are exceptions. If you need new functionality, create a new function. + +0. **Do not rename or redefine variables or constants declared in astaroth.h** without consulting everyone involved with the project. + +0. **Ensure that the code compiles and the automated tests pass** by running `./ac_run -t` before pushing changes to master. If you want to implement a feature that consists of multiple commits, see Managing feature branches below. + +### Managing feature branches + +0. Ensure that you're on the latest version of master. `git checkout master && git pull` + +0. Create a feature branch with `git checkout -b `, f.ex. `git checkout -b forcingtests_2019-01-01` + +0. Do your commits in that branch until your new feature works + +0. Merge master with your feature branch `git merge master` + +0. Resolve the conflicts and test that the code compiles and still works by running `./ac_run -t` + +0. If everything is OK, commit your final changes to the feature branch and merge it to master `git commit && git checkout master && git merge ` + +0. Unless you really have to keep your feature branch around for historical/other reasons, remove it from remote by calling `git push origin --delete ` + +A flowchart is available at [doc/commitflowchart.png](https://bitbucket.org/jpekkila/astaroth/src/2d91df19dcb3/doc/commitflowchart.png?at=master). + +### About branches in general + +* Unused branches should not kept around after merging them into master in order to avoid cluttering the repository. + +* `git branch -a --merged` shows a list of branches that have been merged to master and are likely not needed any more. + +* `git push origin --delete ` deletes a remote branch while `git branch -d ` deletes a local branch + +* If you think that you have messed up and lost work, run `git reflog` which lists the latests commits. All work that has been committed should be accessible with the hashes listed by this command with `git checkout `. ## Coding style. From 9a87053f2655e63fbee0daf35a04f9124d15998e Mon Sep 17 00:00:00 2001 From: jpekkila Date: Mon, 1 Jul 2019 14:08:59 +0000 Subject: [PATCH 16/16] README.md edited online with Bitbucket --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62a5445..1632b47 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ TODO 0. Resolve the conflicts and test that the code compiles and still works by running `./ac_run -t` -0. If everything is OK, commit your final changes to the feature branch and merge it to master `git commit && git checkout master && git merge ` +0. If everything is OK, commit your final changes to the feature branch and merge it to master `git commit && git checkout master && git merge && git push` 0. Unless you really have to keep your feature branch around for historical/other reasons, remove it from remote by calling `git push origin --delete `