diff --git a/backends/cuda-gen/ceed-cuda-gen-qfunction.c b/backends/cuda-gen/ceed-cuda-gen-qfunction.c index e9b7be79e1..f574488071 100644 --- a/backends/cuda-gen/ceed-cuda-gen-qfunction.c +++ b/backends/cuda-gen/ceed-cuda-gen-qfunction.c @@ -49,72 +49,6 @@ static int CeedQFunctionDestroy_Cuda_gen(CeedQFunction qf) { return CEED_ERROR_SUCCESS; } -//------------------------------------------------------------------------------ -// Load QFunction -//------------------------------------------------------------------------------ -static int loadCudaFunction(CeedQFunction qf, char *c_src_file) { - int ierr; - Ceed ceed; - CeedQFunctionGetCeed(qf, &ceed); - CeedQFunction_Cuda_gen *data; - ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); - - // Find source file - char *cuda_file; - ierr = CeedCalloc(CUDA_MAX_PATH, &cuda_file); CeedChkBackend(ierr); - memcpy(cuda_file, c_src_file, strlen(c_src_file)); - const char *last_dot = strrchr(cuda_file, '.'); - if (!last_dot) - return CeedError(ceed, CEED_ERROR_BACKEND, "Cannot find file's extension!"); - const size_t cuda_path_len = last_dot - cuda_file; - strncpy(&cuda_file[cuda_path_len], ".h", 3); - - // Open source file - FILE *fp; - long lSize; - char *buffer; - fp = fopen (cuda_file, "rb"); - if (!fp) - // LCOV_EXCL_START - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't open the Cuda file for the QFunction."); - // LCOV_EXCL_STOP - - // Compute size of source file - fseek(fp, 0L, SEEK_END); - lSize = ftell(fp); - rewind(fp); - - // Allocate memory for entire content - ierr = CeedCalloc(lSize+1, &buffer); CeedChkBackend(ierr); - - // Copy the file into the buffer - if (1 != fread(buffer, lSize, 1, fp)) { - // LCOV_EXCL_START - fclose(fp); - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't read the Cuda file for the QFunction."); - // LCOV_EXCL_STOP - } - - // Append typedef and save source string - // FIXME: the magic number 16 should be defined somewhere... - char *fields_string = - "typedef struct { const CeedScalar* inputs[16]; CeedScalar* outputs[16]; } Fields_Cuda_gen;"; - ierr = CeedMalloc(1 + strlen(fields_string) + strlen(buffer), - &data->qFunctionSource); CeedChkBackend(ierr); - memcpy(data->qFunctionSource, fields_string, strlen(fields_string)); - memcpy(data->qFunctionSource + strlen(fields_string), buffer, - strlen(buffer) + 1); - - // Cleanup - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - fclose(fp); - ierr = CeedFree(&cuda_file); CeedChkBackend(ierr); - return CEED_ERROR_SUCCESS; -} - //------------------------------------------------------------------------------ // Create QFunction //------------------------------------------------------------------------------ @@ -126,15 +60,16 @@ int CeedQFunctionCreate_Cuda_gen(CeedQFunction qf) { ierr = CeedCalloc(1, &data); CeedChkBackend(ierr); ierr = CeedQFunctionSetData(qf, data); CeedChkBackend(ierr); - char *source; - ierr = CeedQFunctionGetSourcePath(qf, &source); CeedChkBackend(ierr); - const char *funname = strrchr(source, ':') + 1; - data->qFunctionName = (char *)funname; - const int filenamelen = funname - source; - char filename[filenamelen]; - memcpy(filename, source, filenamelen - 1); - filename[filenamelen - 1] = '\0'; - ierr = loadCudaFunction(qf, filename); CeedChkBackend(ierr); + // Read QFunction source + ierr = CeedQFunctionGetKernelName(qf, &data->qFunctionName); + CeedChkBackend(ierr); + ierr = CeedQFunctionLoadSourceToBuffer(qf, &data->qFunctionSource); + CeedChkBackend(ierr); + if (!data->qFunctionSource) + // LCOV_EXCL_START + return CeedError(ceed, CEED_ERROR_UNSUPPORTED, + "/gpu/cuda/gen backend requires QFunction source code file"); + // LCOV_EXCL_STOP ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Cuda_gen); CeedChkBackend(ierr); diff --git a/backends/cuda/ceed-cuda-qfunction.c b/backends/cuda/ceed-cuda-qfunction.c index 59e7d1f336..292a88d22a 100644 --- a/backends/cuda/ceed-cuda-qfunction.c +++ b/backends/cuda/ceed-cuda-qfunction.c @@ -110,67 +110,6 @@ static int CeedQFunctionSetCUDAUserFunction_Cuda(CeedQFunction qf, return CEED_ERROR_SUCCESS; } -//------------------------------------------------------------------------------ -// Load QFunction source file -//------------------------------------------------------------------------------ -static int CeedCudaLoadQFunction(CeedQFunction qf, char *c_src_file) { - int ierr; - Ceed ceed; - CeedQFunctionGetCeed(qf, &ceed); - - // Find source file - char *cuda_file; - ierr = CeedCalloc(CUDA_MAX_PATH, &cuda_file); CeedChkBackend(ierr); - memcpy(cuda_file, c_src_file, strlen(c_src_file)); - const char *last_dot = strrchr(cuda_file, '.'); - if (!last_dot) - // LCOV_EXCL_START - return CeedError(ceed, CEED_ERROR_BACKEND, "Cannot find file's extension!"); - // LCOV_EXCL_STOP - const size_t cuda_path_len = last_dot - cuda_file; - strncpy(&cuda_file[cuda_path_len], ".h", 3); - - // Open source file - FILE *fp; - long lSize; - char *buffer; - fp = fopen (cuda_file, "rb"); - if (!fp) - // LCOV_EXCL_START - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't open the Cuda file for the QFunction."); - // LCOV_EXCL_STOP - - // Compute size of source - fseek(fp, 0L, SEEK_END); - lSize = ftell(fp); - rewind(fp); - - // Allocate memory for entire content - ierr = CeedCalloc(lSize+1, &buffer); CeedChkBackend(ierr); - - // Copy the file into the buffer - if(1 != fread(buffer, lSize, 1, fp)) { - // LCOV_EXCL_START - fclose(fp); - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't read the Cuda file for the QFunction."); - // LCOV_EXCL_STOP - } - - // Cleanup - fclose(fp); - ierr = CeedFree(&cuda_file); CeedChkBackend(ierr); - - // Save QFunction source - CeedQFunction_Cuda *data; - ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); - data->qFunctionSource = buffer; - data->qFunction = NULL; - return CEED_ERROR_SUCCESS; -} - //------------------------------------------------------------------------------ // Create QFunction //------------------------------------------------------------------------------ @@ -182,24 +121,11 @@ int CeedQFunctionCreate_Cuda(CeedQFunction qf) { ierr = CeedCalloc(1, &data); CeedChkBackend(ierr); ierr = CeedQFunctionSetData(qf, data); CeedChkBackend(ierr); - // Read source - char *source; - ierr = CeedQFunctionGetSourcePath(qf, &source); CeedChkBackend(ierr); - // Empty source path indicates user must supply Q-Function - if (source[0] != '\0') { - const char *funname = strrchr(source, ':') + 1; - data->qFunctionName = (char *)funname; - const int filenamelen = funname - source; - char filename[filenamelen]; - memcpy(filename, source, filenamelen - 1); - filename[filenamelen - 1] = '\0'; - ierr = CeedCudaLoadQFunction(qf, filename); CeedChkBackend(ierr); - } else { - data->module = NULL; - data->qFunctionName = ""; - data->qFunctionSource = ""; - data->qFunction = NULL; - } + // Read QFunction source + ierr = CeedQFunctionGetKernelName(qf, &data->qFunctionName); + CeedChkBackend(ierr); + ierr = CeedQFunctionLoadSourceToBuffer(qf, &data->qFunctionSource); + CeedChkBackend(ierr); // Register backend functions ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", diff --git a/backends/cuda/ceed-cuda.c b/backends/cuda/ceed-cuda.c index ae508bd015..f78fdd7323 100644 --- a/backends/cuda/ceed-cuda.c +++ b/backends/cuda/ceed-cuda.c @@ -135,7 +135,7 @@ int CeedRunKernelCuda(Ceed ceed, CUfunction kernel, const int gridSize, return CeedError(ceed, CEED_ERROR_BACKEND, "CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES: max_threads_per_block %d on block size (%d,%d,%d), shared_size %d, num_regs %d", max_threads_per_block, blockSize, 1, 1, shared_size_bytes, num_regs); - } else CeedChk_Cu(ceed, result); + } else CeedChk_Cu(ceed, result); // NOLINT return CEED_ERROR_SUCCESS; } diff --git a/backends/hip-gen/ceed-hip-gen-qfunction.c b/backends/hip-gen/ceed-hip-gen-qfunction.c index eae8708b3a..c33f4564e6 100644 --- a/backends/hip-gen/ceed-hip-gen-qfunction.c +++ b/backends/hip-gen/ceed-hip-gen-qfunction.c @@ -49,70 +49,6 @@ static int CeedQFunctionDestroy_Hip_gen(CeedQFunction qf) { return CEED_ERROR_SUCCESS; } -//------------------------------------------------------------------------------ -// Load QFunction -//------------------------------------------------------------------------------ -static int loadHipFunction(CeedQFunction qf, char *c_src_file) { - int ierr; - Ceed ceed; - CeedQFunctionGetCeed(qf, &ceed); - CeedQFunction_Hip_gen *data; - ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); - - // Find source file - char *hip_file; - ierr = CeedCalloc(HIP_MAX_PATH, &hip_file); CeedChkBackend(ierr); - memcpy(hip_file, c_src_file, strlen(c_src_file)); - const char *last_dot = strrchr(hip_file, '.'); - if (!last_dot) - return CeedError(ceed, 1, "Cannot find file's extension!"); - const size_t hip_path_len = last_dot - hip_file; - strncpy(&hip_file[hip_path_len], ".h", 3); - - // Open source file - FILE *fp; - long lSize; - char *buffer; - fp = fopen (hip_file, "rb"); - if (!fp) - // LCOV_EXCL_START - return CeedError(ceed, 1, "Couldn't open the Hip file for the QFunction."); - // LCOV_EXCL_STOP - - // Compute size of source file - fseek(fp, 0L, SEEK_END); - lSize = ftell(fp); - rewind(fp); - - // Allocate memory for entire content - ierr = CeedCalloc(lSize+1, &buffer); CeedChkBackend(ierr); - - // Copy the file into the buffer - if (1 != fread(buffer, lSize, 1, fp)) { - // LCOV_EXCL_START - fclose(fp); - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - return CeedError(ceed, 1, "Couldn't read the Hip file for the QFunction."); - // LCOV_EXCL_STOP - } - - // Append typedef and save source string - // FIXME: the magic number 16 should be defined somewhere... - char *fields_string = - "typedef struct { const CeedScalar* inputs[16]; CeedScalar* outputs[16]; } Fields_Hip_gen;"; - ierr = CeedMalloc(1 + strlen(fields_string) + strlen(buffer), - &data->qFunctionSource); CeedChkBackend(ierr); - memcpy(data->qFunctionSource, fields_string, strlen(fields_string)); - memcpy(data->qFunctionSource + strlen(fields_string), buffer, - strlen(buffer) + 1); - - // Cleanup - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - fclose(fp); - ierr = CeedFree(&hip_file); CeedChkBackend(ierr); - return CEED_ERROR_SUCCESS; -} - //------------------------------------------------------------------------------ // Create QFunction //------------------------------------------------------------------------------ @@ -124,15 +60,16 @@ int CeedQFunctionCreate_Hip_gen(CeedQFunction qf) { ierr = CeedCalloc(1, &data); CeedChkBackend(ierr); ierr = CeedQFunctionSetData(qf, data); CeedChkBackend(ierr); - char *source; - ierr = CeedQFunctionGetSourcePath(qf, &source); CeedChkBackend(ierr); - const char *funname = strrchr(source, ':') + 1; - data->qFunctionName = (char *)funname; - const int filenamelen = funname - source; - char filename[filenamelen]; - memcpy(filename, source, filenamelen - 1); - filename[filenamelen - 1] = '\0'; - ierr = loadHipFunction(qf, filename); CeedChkBackend(ierr); + // Read QFunction source + ierr = CeedQFunctionGetKernelName(qf, &data->qFunctionName); + CeedChkBackend(ierr); + ierr = CeedQFunctionLoadSourceToBuffer(qf, &data->qFunctionSource); + CeedChkBackend(ierr); + if (!data->qFunctionSource) + // LCOV_EXCL_START + return CeedError(ceed, CEED_ERROR_UNSUPPORTED, + "/gpu/hip/gen backend requires QFunction source code file"); + // LCOV_EXCL_STOP ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Hip_gen); CeedChkBackend(ierr); diff --git a/backends/hip/ceed-hip-qfunction.c b/backends/hip/ceed-hip-qfunction.c index 5c07a2890c..5d227741f4 100644 --- a/backends/hip/ceed-hip-qfunction.c +++ b/backends/hip/ceed-hip-qfunction.c @@ -100,66 +100,6 @@ static int CeedQFunctionDestroy_Hip(CeedQFunction qf) { return CEED_ERROR_SUCCESS; } -//------------------------------------------------------------------------------ -// Load QFunction source file -//------------------------------------------------------------------------------ -static int CeedHipLoadQFunction(CeedQFunction qf, char *c_src_file) { - int ierr; - Ceed ceed; - CeedQFunctionGetCeed(qf, &ceed); - - // Find source file - char *hip_file; - ierr = CeedCalloc(HIP_MAX_PATH, &hip_file); CeedChkBackend(ierr); - memcpy(hip_file, c_src_file, strlen(c_src_file)); - const char *last_dot = strrchr(hip_file, '.'); - if (!last_dot) - // LCOV_EXCL_START - return CeedError(ceed, CEED_ERROR_BACKEND, "Cannot find file's extension!"); - // LCOV_EXCL_STOP - const size_t hip_path_len = last_dot - hip_file; - strncpy(&hip_file[hip_path_len], ".h", 3); - - // Open source file - FILE *fp; - long lSize; - char *buffer; - fp = fopen (hip_file, "rb"); - if (!fp) - // LCOV_EXCL_START - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't open the Hip file for the QFunction."); - // LCOV_EXCL_STOP - - // Compute size of source - fseek(fp, 0L, SEEK_END); - lSize = ftell(fp); - rewind(fp); - - // Allocate memory for entire content - ierr = CeedCalloc(lSize+1, &buffer); CeedChkBackend(ierr); - - // Copy the file into the buffer - if(1!=fread(buffer, lSize, 1, fp)) { - // LCOV_EXCL_START - fclose(fp); - ierr = CeedFree(&buffer); CeedChkBackend(ierr); - return CeedError(ceed, CEED_ERROR_BACKEND, - "Couldn't read the Hip file for the QFunction."); - // LCOV_EXCL_STOP - } - - // Cleanup - fclose(fp); - ierr = CeedFree(&hip_file); CeedChkBackend(ierr); - - // Save QFunction source - CeedQFunction_Hip *data; - ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); - data->qFunctionSource = buffer; - return CEED_ERROR_SUCCESS; -} - //------------------------------------------------------------------------------ // Create QFunction //------------------------------------------------------------------------------ @@ -174,16 +114,11 @@ int CeedQFunctionCreate_Hip(CeedQFunction qf) { ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); CeedChkBackend(ierr); - // Read source - char *source; - ierr = CeedQFunctionGetSourcePath(qf, &source); CeedChkBackend(ierr); - const char *funname = strrchr(source, ':') + 1; - data->qFunctionName = (char *)funname; - const int filenamelen = funname - source; - char filename[filenamelen]; - memcpy(filename, source, filenamelen - 1); - filename[filenamelen - 1] = '\0'; - ierr = CeedHipLoadQFunction(qf, filename); CeedChkBackend(ierr); + // Read QFunction source + ierr = CeedQFunctionGetKernelName(qf, &data->qFunctionName); + CeedChkBackend(ierr); + ierr = CeedQFunctionLoadSourceToBuffer(qf, &data->qFunctionSource); + CeedChkBackend(ierr); // Register backend functions ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", diff --git a/doc/sphinx/source/releasenotes.md b/doc/sphinx/source/releasenotes.md index 9f48ac5397..0cfd6e00d0 100644 --- a/doc/sphinx/source/releasenotes.md +++ b/doc/sphinx/source/releasenotes.md @@ -16,10 +16,14 @@ for each release of libCEED. - Promote {c:func} `CeedOperatorCheckReady`to the public API to facilitate interactive interfaces. - Warning added when compiling OCCA backend to alert users that this backend is experimental. - `ceed-backend.h`, `ceed-hash.h`, and `ceed-khash.h` removed. Users should use `ceed/backend.h`, `ceed/hash.h`, and `ceed/khash.h`. +- Added {c:func} `CeedQFunctionGetKernelName`; refactored {c:func} `CeedQFunctionGetSourcePath` to exclude function kernel name. ### New features - `CeedScalar` can now be set as `float` or `double` at compile time. +- Added JiT utilities in `ceed/jit-tools.h` to reduce duplicated code in GPU backends. +- Added support for JiT of QFunctions with `#include "relative/path/local-file.h"` statements for additional local files. Note that files included with `""` are searched relative to the current file first, then by compiler paths (as with `<>` includes). To use this feature, one should adhere to relative paths only, not compiler flags like `-I`, which the JiT will not be aware of. +- Remove need to guard library headers in QFunction source for code generation backends. ### Maintainability diff --git a/examples/fluids/qfunctions/advection.h b/examples/fluids/qfunctions/advection.h index 5b2476f33b..cc0d3c3920 100644 --- a/examples/fluids/qfunctions/advection.h +++ b/examples/fluids/qfunctions/advection.h @@ -20,9 +20,7 @@ #ifndef advection_h #define advection_h -#ifndef __CUDACC__ -# include -#endif +#include #ifndef setup_context_struct #define setup_context_struct diff --git a/examples/fluids/qfunctions/advection2d.h b/examples/fluids/qfunctions/advection2d.h index a80c6f2158..876635d464 100644 --- a/examples/fluids/qfunctions/advection2d.h +++ b/examples/fluids/qfunctions/advection2d.h @@ -20,9 +20,7 @@ #ifndef advection2d_h #define advection2d_h -#ifndef __CUDACC__ -# include -#endif +#include #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/examples/fluids/qfunctions/densitycurrent.h b/examples/fluids/qfunctions/densitycurrent.h index 545ea712af..cc350bb26e 100644 --- a/examples/fluids/qfunctions/densitycurrent.h +++ b/examples/fluids/qfunctions/densitycurrent.h @@ -24,9 +24,7 @@ #ifndef densitycurrent_h #define densitycurrent_h -#ifndef __CUDACC__ -# include -#endif +#include #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/examples/fluids/qfunctions/eulervortex.h b/examples/fluids/qfunctions/eulervortex.h index 31cd1fff49..488639b429 100644 --- a/examples/fluids/qfunctions/eulervortex.h +++ b/examples/fluids/qfunctions/eulervortex.h @@ -25,9 +25,7 @@ #ifndef eulervortex_h #define eulervortex_h -#ifndef __CUDACC__ -# include -#endif +#include #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/examples/fluids/qfunctions/mass.h b/examples/fluids/qfunctions/mass.h index f9a4420e7c..7629b4ff1b 100644 --- a/examples/fluids/qfunctions/mass.h +++ b/examples/fluids/qfunctions/mass.h @@ -20,9 +20,7 @@ #ifndef mass_h #define mass_h -#ifndef __CUDACC__ -# include -#endif +#include // ***************************************************************************** // This QFunction applies the mass matrix to five interlaced fields. diff --git a/examples/fluids/qfunctions/setupgeo.h b/examples/fluids/qfunctions/setupgeo.h index 1110feda70..7153243c05 100644 --- a/examples/fluids/qfunctions/setupgeo.h +++ b/examples/fluids/qfunctions/setupgeo.h @@ -20,9 +20,7 @@ #ifndef setup_geo_h #define setup_geo_h -#ifndef __CUDACC__ -# include -#endif +#include // ***************************************************************************** // This QFunction sets up the geometric factors required for integration and diff --git a/examples/fluids/qfunctions/setupgeo2d.h b/examples/fluids/qfunctions/setupgeo2d.h index 170fcc7fd1..e69cf8a2a7 100644 --- a/examples/fluids/qfunctions/setupgeo2d.h +++ b/examples/fluids/qfunctions/setupgeo2d.h @@ -20,9 +20,7 @@ #ifndef setup_geo_2d_h #define setup_geo_2d_h -#ifndef __CUDACC__ -# include -#endif +#include // ***************************************************************************** // This QFunction sets up the geometric factors required for integration and diff --git a/examples/nek/bps/bps.h b/examples/nek/bps/bps.h index d8736350f9..fbe4e1c8a0 100644 --- a/examples/nek/bps/bps.h +++ b/examples/nek/bps/bps.h @@ -17,9 +17,7 @@ #ifndef bps_h #define bps_h -#ifndef __CUDACC__ -# include -#endif +#include #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/examples/petsc/qfunctions/area/areacube.h b/examples/petsc/qfunctions/area/areacube.h index b64cdfe0e7..5d384f05ad 100644 --- a/examples/petsc/qfunctions/area/areacube.h +++ b/examples/petsc/qfunctions/area/areacube.h @@ -20,9 +20,7 @@ #ifndef areacube_h #define areacube_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factor required for integration when diff --git a/examples/petsc/qfunctions/area/areasphere.h b/examples/petsc/qfunctions/area/areasphere.h index 99bb8e4cc8..f900422770 100644 --- a/examples/petsc/qfunctions/area/areasphere.h +++ b/examples/petsc/qfunctions/area/areasphere.h @@ -20,9 +20,7 @@ #ifndef areasphere_h #define areasphere_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factor required for integration when diff --git a/examples/petsc/qfunctions/bps/bp1.h b/examples/petsc/qfunctions/bps/bp1.h index bf8d11cf82..e2da8fd0c5 100644 --- a/examples/petsc/qfunctions/bps/bp1.h +++ b/examples/petsc/qfunctions/bps/bp1.h @@ -20,9 +20,7 @@ #ifndef bp1_h #define bp1_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factors required to apply the diff --git a/examples/petsc/qfunctions/bps/bp1sphere.h b/examples/petsc/qfunctions/bps/bp1sphere.h index d1bf8c3c49..f04cfc57d9 100644 --- a/examples/petsc/qfunctions/bps/bp1sphere.h +++ b/examples/petsc/qfunctions/bps/bp1sphere.h @@ -20,9 +20,7 @@ #ifndef bp1sphere_h #define bp1sphere_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factors required for integration and diff --git a/examples/petsc/qfunctions/bps/bp2.h b/examples/petsc/qfunctions/bps/bp2.h index 0142a1a5f5..edd70afffa 100644 --- a/examples/petsc/qfunctions/bps/bp2.h +++ b/examples/petsc/qfunctions/bps/bp2.h @@ -20,9 +20,7 @@ #ifndef bp2_h #define bp2_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the rhs and true solution for the problem diff --git a/examples/petsc/qfunctions/bps/bp2sphere.h b/examples/petsc/qfunctions/bps/bp2sphere.h index 801677d2ad..2ac875938b 100644 --- a/examples/petsc/qfunctions/bps/bp2sphere.h +++ b/examples/petsc/qfunctions/bps/bp2sphere.h @@ -20,9 +20,7 @@ #ifndef bp2sphere_h #define bp2sphere_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the rhs and true solution for the problem diff --git a/examples/petsc/qfunctions/bps/bp3.h b/examples/petsc/qfunctions/bps/bp3.h index 8adca2aacf..315e9d6915 100644 --- a/examples/petsc/qfunctions/bps/bp3.h +++ b/examples/petsc/qfunctions/bps/bp3.h @@ -20,9 +20,7 @@ #ifndef bp3_h #define bp3_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factors required to apply the diff --git a/examples/petsc/qfunctions/bps/bp3sphere.h b/examples/petsc/qfunctions/bps/bp3sphere.h index 88eed6cd0e..059f5928f6 100644 --- a/examples/petsc/qfunctions/bps/bp3sphere.h +++ b/examples/petsc/qfunctions/bps/bp3sphere.h @@ -20,9 +20,7 @@ #ifndef bp3sphere_h #define bp3sphere_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the geometric factors required for integration and diff --git a/examples/petsc/qfunctions/bps/bp4.h b/examples/petsc/qfunctions/bps/bp4.h index 61713a55a6..23b1140310 100644 --- a/examples/petsc/qfunctions/bps/bp4.h +++ b/examples/petsc/qfunctions/bps/bp4.h @@ -20,9 +20,7 @@ #ifndef bp4_h #define bp4_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the rhs and true solution for the problem diff --git a/examples/petsc/qfunctions/bps/bp4sphere.h b/examples/petsc/qfunctions/bps/bp4sphere.h index 1cb1dc3689..f196cff4e6 100644 --- a/examples/petsc/qfunctions/bps/bp4sphere.h +++ b/examples/petsc/qfunctions/bps/bp4sphere.h @@ -20,9 +20,7 @@ #ifndef bp4sphere_h #define bp4sphere_h -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // This QFunction sets up the rhs and true solution for the problem diff --git a/examples/solids/qfunctions/constant-force.h b/examples/solids/qfunctions/constant-force.h index 547fc182ab..695cf50974 100644 --- a/examples/solids/qfunctions/constant-force.h +++ b/examples/solids/qfunctions/constant-force.h @@ -20,9 +20,7 @@ #ifndef CONSTANT_H #define CONSTANT_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/finite-strain-mooney-rivlin-initial-1.h b/examples/solids/qfunctions/finite-strain-mooney-rivlin-initial-1.h index b58f8c7d75..07abf372c6 100644 --- a/examples/solids/qfunctions/finite-strain-mooney-rivlin-initial-1.h +++ b/examples/solids/qfunctions/finite-strain-mooney-rivlin-initial-1.h @@ -20,9 +20,7 @@ #ifndef ELAS_FSInitialMR1_H #define ELAS_FSInitialMR1_H -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // Mooney-Rivlin context diff --git a/examples/solids/qfunctions/finite-strain-neo-hookean-current-1.h b/examples/solids/qfunctions/finite-strain-neo-hookean-current-1.h index 5abb3c8429..6cd75e478e 100644 --- a/examples/solids/qfunctions/finite-strain-neo-hookean-current-1.h +++ b/examples/solids/qfunctions/finite-strain-neo-hookean-current-1.h @@ -20,9 +20,7 @@ #ifndef ELAS_FSCurrentNH1_H #define ELAS_FSCurrentNH1_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/finite-strain-neo-hookean-current-2.h b/examples/solids/qfunctions/finite-strain-neo-hookean-current-2.h index 3c69a6055d..6feb2fe3c5 100644 --- a/examples/solids/qfunctions/finite-strain-neo-hookean-current-2.h +++ b/examples/solids/qfunctions/finite-strain-neo-hookean-current-2.h @@ -20,9 +20,7 @@ #ifndef ELAS_FSCurrentNH2_H #define ELAS_FSCurrentNH2_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/finite-strain-neo-hookean-initial-1.h b/examples/solids/qfunctions/finite-strain-neo-hookean-initial-1.h index b2ad027e63..907b9d8e57 100644 --- a/examples/solids/qfunctions/finite-strain-neo-hookean-initial-1.h +++ b/examples/solids/qfunctions/finite-strain-neo-hookean-initial-1.h @@ -20,9 +20,7 @@ #ifndef ELAS_FSInitialNH1_H #define ELAS_FSInitialNH1_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/finite-strain-neo-hookean-initial-2.h b/examples/solids/qfunctions/finite-strain-neo-hookean-initial-2.h index 2c5d0164b1..61e3c040a4 100644 --- a/examples/solids/qfunctions/finite-strain-neo-hookean-initial-2.h +++ b/examples/solids/qfunctions/finite-strain-neo-hookean-initial-2.h @@ -20,9 +20,7 @@ #ifndef ELAS_FSInitialNH2_H #define ELAS_FSInitialNH2_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/linear.h b/examples/solids/qfunctions/linear.h index d40b401f61..b37fa74331 100644 --- a/examples/solids/qfunctions/linear.h +++ b/examples/solids/qfunctions/linear.h @@ -20,9 +20,7 @@ #ifndef ELAS_LINEAR_H #define ELAS_LINEAR_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/manufactured-force.h b/examples/solids/qfunctions/manufactured-force.h index 3295d3708b..9bd6d577c0 100644 --- a/examples/solids/qfunctions/manufactured-force.h +++ b/examples/solids/qfunctions/manufactured-force.h @@ -20,9 +20,7 @@ #ifndef MANUFACTURED_H #define MANUFACTURED_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/examples/solids/qfunctions/manufactured-true.h b/examples/solids/qfunctions/manufactured-true.h index 2b1cc1dca9..92172a11bf 100644 --- a/examples/solids/qfunctions/manufactured-true.h +++ b/examples/solids/qfunctions/manufactured-true.h @@ -20,9 +20,7 @@ #ifndef MANUFACTURED_TRUE_H #define MANUFACTURED_TRUE_H -#ifndef __CUDACC__ -# include -#endif +#include // ----------------------------------------------------------------------------- // True solution for linear elasticity manufactured solution diff --git a/examples/solids/qfunctions/small-strain-neo-hookean.h b/examples/solids/qfunctions/small-strain-neo-hookean.h index a41d59cff8..cadd6a1253 100644 --- a/examples/solids/qfunctions/small-strain-neo-hookean.h +++ b/examples/solids/qfunctions/small-strain-neo-hookean.h @@ -20,9 +20,7 @@ #ifndef ELAS_SS_NH_H #define ELAS_SS_NH_H -#ifndef __CUDACC__ -# include -#endif +#include #ifndef PHYSICS_STRUCT #define PHYSICS_STRUCT diff --git a/include/ceed-impl.h b/include/ceed-impl.h index 82ba9bb836..917cc8ae70 100644 --- a/include/ceed-impl.h +++ b/include/ceed-impl.h @@ -239,7 +239,9 @@ struct CeedQFunction_private { CeedInt num_input_fields, num_output_fields; CeedQFunctionUser function; const char *source_path; - const char *qf_name; + const char *kernel_name; + const char *gallery_name; + bool is_gallery; bool is_identity; bool is_fortran; bool is_immutable; diff --git a/include/ceed/backend.h b/include/ceed/backend.h index 042d0e7ecf..bb4c7382a7 100644 --- a/include/ceed/backend.h +++ b/include/ceed/backend.h @@ -192,7 +192,9 @@ CEED_EXTERN int CeedQFunctionGetVectorLength(CeedQFunction qf, CEED_EXTERN int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *num_input_fields, CeedInt *num_output_fields); -CEED_EXTERN int CeedQFunctionGetSourcePath(CeedQFunction qf, char **source); +CEED_EXTERN int CeedQFunctionGetKernelName(CeedQFunction qf, char **kernel_name); +CEED_EXTERN int CeedQFunctionGetSourcePath(CeedQFunction qf, char **source_path); +CEED_EXTERN int CeedQFunctionLoadSourceToBuffer(CeedQFunction qf, char **source_buffer); CEED_EXTERN int CeedQFunctionGetUserFunction(CeedQFunction qf, CeedQFunctionUser *f); CEED_EXTERN int CeedQFunctionGetContext(CeedQFunction qf, diff --git a/include/ceed/jit-tools.h b/include/ceed/jit-tools.h new file mode 100644 index 0000000000..48b6deda49 --- /dev/null +++ b/include/ceed/jit-tools.h @@ -0,0 +1,24 @@ +/// Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at +/// the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights +/// reserved. See files LICENSE and NOTICE for details. +/// +/// This file is part of CEED, a collection of benchmarks, miniapps, software +/// libraries and APIs for efficient high-order finite element and spectral +/// element discretizations for exascale applications. For more information and +/// source code availability see http://github.com/ceed. +/// +/// The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, +/// a collaborative effort of two U.S. Department of Energy organizations (Office +/// of Science and the National Nuclear Security Administration) responsible for +/// the planning and preparation of a capable exascale ecosystem, including +/// software, applications, hardware, advanced system engineering and early +/// testbed platforms, in support of the nation's exascale computing imperative. + +#ifndef _ceed_jit_h +#define _ceed_jit_h + +#include + +CEED_EXTERN int CeedLoadSourceToBuffer(Ceed ceed, const char *source_file_path, char **buffer); + +#endif diff --git a/interface/ceed-jit-tools.c b/interface/ceed-jit-tools.c new file mode 100644 index 0000000000..8a073e8c8e --- /dev/null +++ b/interface/ceed-jit-tools.c @@ -0,0 +1,167 @@ +// Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at +// the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights +// reserved. See files LICENSE and NOTICE for details. +// +// This file is part of CEED, a collection of benchmarks, miniapps, software +// libraries and APIs for efficient high-order finite element and spectral +// element discretizations for exascale applications. For more information and +// source code availability see http://github.com/ceed. +// +// The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, +// a collaborative effort of two U.S. Department of Energy organizations (Office +// of Science and the National Nuclear Security Administration) responsible for +// the planning and preparation of a capable exascale ecosystem, including +// software, applications, hardware, advanced system engineering and early +// testbed platforms, in support of the nation's exascale computing imperative. + +#include +#include +#include +#include +#include +#include + +/** + @brief Load source file into initalized string buffer, including full text + of local files in place of `#include "local.h"` + + @param ceed A Ceed object for error handling + @param[in] source_file_path Absolute path to source file + @param[out] buffer String buffer for source file contents + + @return An error code: 0 - success, otherwise - failure + + @ref Backend +**/ +static inline int CeedLoadSourceToInitalizedBuffer(Ceed ceed, + const char *source_file_path, char **buffer) { + int ierr; + FILE *source_file; + long file_size, file_offset = 0; + char *temp_buffer; + + // Debug + CeedDebug256(ceed, 1, "---------- Ceed JiT ----------\n"); + CeedDebug256(ceed, 1, "Current source file: "); + CeedDebug256(ceed, 255, "%s\n", source_file_path); + CeedDebug256(ceed, 1, "Current buffer:\n"); + CeedDebug256(ceed, 255, "%s\n", *buffer); + + // Read file to temporary buffer + source_file = fopen(source_file_path, "rb"); + if (!source_file) + // LCOV_EXCL_START + return CeedError(ceed, CEED_ERROR_MAJOR, "Couldn't open source file: %s", + source_file_path); + // LCOV_EXCL_STOP + // -- Compute size of source + fseek(source_file, 0L, SEEK_END); + file_size = ftell(source_file); + rewind(source_file); + // -- Allocate memory for entire source file + ierr = CeedCalloc(file_size + 1, &temp_buffer); CeedChk(ierr); + // -- Copy the file into the buffer + if (1 != fread(temp_buffer, file_size, 1, source_file)) { + // LCOV_EXCL_START + fclose(source_file); + ierr = CeedFree(&temp_buffer); CeedChk(ierr); + return CeedError(ceed, CEED_ERROR_MAJOR, "Couldn't read source file: %s", + source_file_path); + // LCOV_EXCL_STOP + } + fclose(source_file); + + // Search for headers to include + const char *first_hash = strchr(temp_buffer, '#'); + while (first_hash) { + // -- Check for 'include' keyword + const char *next_e = strchr(first_hash, 'e'); + char keyword[8] = ""; + if (next_e) + strncpy(keyword, &next_e[-6], 7); + bool is_hash_include = !strcmp(keyword, "include"); + // ---- Spaces allowed in '# include ' + if (next_e) + for (CeedInt i = 1; first_hash - next_e + i < -6; i++) + is_hash_include &= first_hash[i] == ' '; + if (is_hash_include) { + // -- Copy into buffer all preceding # + long current_size = strlen(*buffer); + long copy_size = first_hash - &temp_buffer[file_offset]; + ierr = CeedRealloc(current_size + copy_size + 2, buffer); CeedChk(ierr); + strncpy(&(*buffer)[current_size], "\n", 2); + strncpy(&(*buffer)[current_size + 1], &temp_buffer[file_offset], copy_size); + strncpy(&(*buffer)[current_size + copy_size], "", 1); + // -- Load local "header.h" + char *next_quote = strchr(first_hash, '"'); + char *next_new_line = strchr(first_hash, '\n'); + bool is_local_header = is_hash_include && next_quote + && (next_new_line - next_quote > 0); + if (is_local_header) { + // ---- Build source path + char *include_source_path; + long root_length = strrchr(source_file_path, '/') - source_file_path; + long include_file_name_len = strchr(&next_quote[1], '"') - next_quote - 1; + ierr = CeedCalloc(root_length + include_file_name_len + 2, + &include_source_path); CeedChk(ierr); + strncpy(include_source_path, source_file_path, root_length + 1); + strncpy(&include_source_path[root_length + 1], &next_quote[1], + include_file_name_len); + strncpy(&include_source_path[root_length + include_file_name_len + 1], "", 1); + // ---- Recursive call to load source to buffer + ierr = CeedLoadSourceToInitalizedBuffer(ceed, include_source_path, buffer); + CeedChk(ierr); + ierr = CeedFree(&include_source_path); CeedChk(ierr); + } + file_offset = strchr(first_hash, '\n') - temp_buffer + 1; + } + // -- Next hash + first_hash = strchr(&first_hash[1], '#'); + } + // Copy rest of source file into buffer + long current_size = strlen(*buffer); + long copy_size = strlen(&temp_buffer[file_offset]); + ierr = CeedRealloc(current_size + copy_size + 2, buffer); CeedChk(ierr); + strncpy(&(*buffer)[current_size], "\n", 2); + strncpy(&(*buffer)[current_size + 1], &temp_buffer[file_offset], copy_size); + strncpy(&(*buffer)[current_size + copy_size + 1], "", 1); + + // Cleanup + ierr = CeedFree(&temp_buffer); CeedChk(ierr); + + // Debug + CeedDebug256(ceed, 1, "---------- Ceed JiT ----------\n"); + CeedDebug256(ceed, 1, "Current source file: "); + CeedDebug256(ceed, 255, "%s\n", source_file_path); + CeedDebug256(ceed, 1, "Final buffer:\n"); + CeedDebug256(ceed, 255, "%s\n", *buffer); + + return CEED_ERROR_SUCCESS; +} + +/** + @brief Initalize and load source file into string buffer, including full text + of local files in place of `#include "local.h"`. + Note: Caller is responsible for freeing the string buffer with `CeedFree()`. + + @param ceed A Ceed object for error handling + @param[in] source_file_path Absolute path to source file + @param[out] buffer String buffer for source file contents + + @return An error code: 0 - success, otherwise - failure + + @ref Backend +**/ +int CeedLoadSourceToBuffer(Ceed ceed, const char *source_file_path, + char **buffer) { + int ierr; + + // Initalize buffer + ierr = CeedCalloc(1, buffer); CeedChk(ierr); + + // Load to initalized buffer + ierr = CeedLoadSourceToInitalizedBuffer(ceed, source_file_path, buffer); + CeedChk(ierr); + + return CEED_ERROR_SUCCESS; +} diff --git a/interface/ceed-qfunction.c b/interface/ceed-qfunction.c index 243bca96ff..b917091972 100644 --- a/interface/ceed-qfunction.c +++ b/interface/ceed-qfunction.c @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #include /// @file @@ -210,18 +212,60 @@ int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *num_input, return CEED_ERROR_SUCCESS; } +/** + @brief Get the name of the user function for a CeedQFunction + + @param qf CeedQFunction + @param[out] kernel_name Variable to store source path string + + @return An error code: 0 - success, otherwise - failure + + @ref Backend +**/ +int CeedQFunctionGetKernelName(CeedQFunction qf, char **kernel_name) { + *kernel_name = (char *) qf->kernel_name; + return CEED_ERROR_SUCCESS; +} + /** @brief Get the source path string for a CeedQFunction - @param qf CeedQFunction - @param[out] source Variable to store source path string + @param qf CeedQFunction + @param[out] source_path Variable to store source path string @return An error code: 0 - success, otherwise - failure @ref Backend **/ -int CeedQFunctionGetSourcePath(CeedQFunction qf, char **source) { - *source = (char *) qf->source_path; +int CeedQFunctionGetSourcePath(CeedQFunction qf, char **source_path) { + *source_path = (char *) qf->source_path; + return CEED_ERROR_SUCCESS; +} + +/** + @brief Initalize and load QFunction source file into string buffer, including + full text of local files in place of `#include "local.h"`. + The `buffer` is set to `NULL` if there is no QFunction source file. + Note: Caller is responsible for freeing the string buffer with `CeedFree()`. + + @param qf CeedQFunction + @param[out] buffer String buffer for source file contents + + @return An error code: 0 - success, otherwise - failure + + @ref Backend +**/ +int CeedQFunctionLoadSourceToBuffer(CeedQFunction qf, char **source_buffer) { + int ierr; + char *source_path; + + ierr = CeedQFunctionGetSourcePath(qf, &source_path); CeedChk(ierr); + *source_buffer = NULL; + if (source_path) { + ierr = CeedLoadSourceToBuffer(qf->ceed, source_path, source_buffer); + CeedChk(ierr); + } + return CEED_ERROR_SUCCESS; } @@ -378,7 +422,7 @@ int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, CeedQFunctionUser f, const char *source, CeedQFunction *qf) { int ierr; - char *source_copy; + char *source_copy, *kernel_name_copy; if (!ceed->QFunctionCreate) { Ceed delegate; @@ -395,6 +439,14 @@ int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, return CEED_ERROR_SUCCESS; } + if (strlen(source) && !strrchr(source, ':'))\ + // LCOV_EXCL_START + return CeedError(ceed, CEED_ERROR_INCOMPLETE, + "Provided path to source does not include function name. " + "Provided: \"%s\"\nRequired: \"\\abs_path\\file.h:function_name\"", + source); + // LCOV_EXCL_STOP + ierr = CeedCalloc(1, qf); CeedChk(ierr); (*qf)->ceed = ceed; ierr = CeedReference(ceed); CeedChk(ierr); @@ -402,10 +454,18 @@ int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, (*qf)->vec_length = vec_length; (*qf)->is_identity = false; (*qf)->function = f; - size_t slen = strlen(source) + 1; - ierr = CeedMalloc(slen, &source_copy); CeedChk(ierr); - memcpy(source_copy, source, slen); - (*qf)->source_path = source_copy; + if (strlen(source)) { + const char *kernel_name = strrchr(source, ':') + 1; + size_t kernel_name_len = strlen(kernel_name); + ierr = CeedCalloc(kernel_name_len + 1, &kernel_name_copy); CeedChk(ierr); + strncpy(kernel_name_copy, kernel_name, kernel_name_len); + (*qf)->kernel_name = kernel_name_copy; + + size_t source_len = strlen(source) - kernel_name_len - 1; + ierr = CeedCalloc(source_len + 1, &source_copy); CeedChk(ierr); + strncpy(source_copy, source, source_len); + (*qf)->source_path = source_copy; + } ierr = CeedCalloc(16, &(*qf)->input_fields); CeedChk(ierr); ierr = CeedCalloc(16, &(*qf)->output_fields); CeedChk(ierr); ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); @@ -462,7 +522,8 @@ int CeedQFunctionCreateInteriorByName(Ceed ceed, const char *name, size_t slen = strlen(name) + 1; ierr = CeedMalloc(slen, &name_copy); CeedChk(ierr); memcpy(name_copy, name, slen); - (*qf)->qf_name = name_copy; + (*qf)->gallery_name = name_copy; + (*qf)->is_gallery = true; return CEED_ERROR_SUCCESS; } @@ -705,7 +766,8 @@ int CeedQFunctionView(CeedQFunction qf, FILE *stream) { int ierr; fprintf(stream, "%sCeedQFunction %s\n", - qf->qf_name ? "Gallery " : "User ", qf->qf_name ? qf->qf_name : ""); + qf->is_gallery ? "Gallery " : "User ", + qf->is_gallery ? qf->gallery_name : qf->kernel_name); fprintf(stream, " %d Input Field%s:\n", qf->num_input_fields, qf->num_input_fields>1 ? "s" : ""); @@ -805,7 +867,8 @@ int CeedQFunctionDestroy(CeedQFunction *qf) { ierr = CeedQFunctionContextDestroy(&(*qf)->ctx); CeedChk(ierr); ierr = CeedFree(&(*qf)->source_path); CeedChk(ierr); - ierr = CeedFree(&(*qf)->qf_name); CeedChk(ierr); + ierr = CeedFree(&(*qf)->gallery_name); CeedChk(ierr); + ierr = CeedFree(&(*qf)->kernel_name); CeedChk(ierr); ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); ierr = CeedFree(qf); CeedChk(ierr); return CEED_ERROR_SUCCESS; diff --git a/python/tests/output/test_402.out b/python/tests/output/test_402.out index 25e5598be1..38bb67d83f 100644 --- a/python/tests/output/test_402.out +++ b/python/tests/output/test_402.out @@ -1,4 +1,4 @@ -User CeedQFunction +User CeedQFunction setup_mass 2 Input Fields: Input Field [0]: Name: "w" @@ -14,7 +14,7 @@ User CeedQFunction Size: 1 EvalMode: "none" -User CeedQFunction +User CeedQFunction apply_mass 2 Input Fields: Input Field [0]: Name: "qdata" diff --git a/tests/output/t402-qfunction-f.out b/tests/output/t402-qfunction-f.out index becc45ef47..be66f7e3c0 100644 --- a/tests/output/t402-qfunction-f.out +++ b/tests/output/t402-qfunction-f.out @@ -1,4 +1,4 @@ -User CeedQFunction +User CeedQFunction setup 1 Input Field: Input Field [0]: Name: "w" @@ -9,7 +9,7 @@ User CeedQFunction Name: "qdata" Size: 1 EvalMode: "none" -User CeedQFunction +User CeedQFunction mass 2 Input Fields: Input Field [0]: Name: "qdata" diff --git a/tests/output/t402-qfunction.out b/tests/output/t402-qfunction.out index becc45ef47..be66f7e3c0 100644 --- a/tests/output/t402-qfunction.out +++ b/tests/output/t402-qfunction.out @@ -1,4 +1,4 @@ -User CeedQFunction +User CeedQFunction setup 1 Input Field: Input Field [0]: Name: "w" @@ -9,7 +9,7 @@ User CeedQFunction Name: "qdata" Size: 1 EvalMode: "none" -User CeedQFunction +User CeedQFunction mass 2 Input Fields: Input Field [0]: Name: "qdata" diff --git a/tests/t406-qfunction-helper.h b/tests/t406-qfunction-helper.h new file mode 100644 index 0000000000..80b33c521e --- /dev/null +++ b/tests/t406-qfunction-helper.h @@ -0,0 +1,28 @@ +// Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. +// All Rights reserved. See files LICENSE and NOTICE for details. +// +// This file is part of CEED, a collection of benchmarks, miniapps, software +// libraries and APIs for efficient high-order finite element and spectral +// element discretizations for exascale applications. For more information and +// source code availability see http://github.com/ceed. +// +// The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, +// a collaborative effort of two U.S. Department of Energy organizations (Office +// of Science and the National Nuclear Security Administration) responsible for +// the planning and preparation of a capable exascale ecosystem, including +// software, applications, hardware, advanced system engineering and early +// testbed platforms, in support of the nation's exascale computing imperative. + +#ifndef _helper_h +#define _helper_h + +CEED_QFUNCTION_HELPER CeedScalar times_two(CeedScalar x) { + return 2 * x; +} + +CEED_QFUNCTION_HELPER CeedScalar times_three(CeedScalar x) { + return 3 * x; +} + +#endif diff --git a/tests/t406-qfunction.c b/tests/t406-qfunction.c new file mode 100644 index 0000000000..95a026b5e9 --- /dev/null +++ b/tests/t406-qfunction.c @@ -0,0 +1,74 @@ +/// @file +/// Test QFunction helper macro +/// \test Test QFunction helper macro +#include +#include +#include +#include +#include "t406-qfunction.h" + +int main(int argc, char **argv) { + Ceed ceed; + CeedVector in[16], out[16]; + CeedVector Q_data, W, U, V; + CeedQFunction qf_setup, qf_mass; + CeedInt Q = 8; + const CeedScalar *vv; + CeedScalar w[Q], u[Q], v[Q]; + + CeedInit(argv[1], &ceed); + + CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup); + CeedQFunctionAddInput(qf_setup, "w", 1, CEED_EVAL_WEIGHT); + CeedQFunctionAddOutput(qf_setup, "qdata", 1, CEED_EVAL_NONE); + + CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass); + CeedQFunctionAddInput(qf_mass, "qdata", 1, CEED_EVAL_NONE); + CeedQFunctionAddInput(qf_mass, "u", 1, CEED_EVAL_INTERP); + CeedQFunctionAddOutput(qf_mass, "v", 1, CEED_EVAL_INTERP); + + for (CeedInt i=0; i 1E3*CEED_EPSILON) + // LCOV_EXCL_START + printf("[%d] v %f != vv %f\n",i, 5*v[i]*sqrt(2.), vv[i]); + // LCOV_EXCL_STOP + CeedVectorRestoreArrayRead(V, &vv); + + CeedVectorDestroy(&W); + CeedVectorDestroy(&U); + CeedVectorDestroy(&V); + CeedVectorDestroy(&Q_data); + CeedQFunctionDestroy(&qf_setup); + CeedQFunctionDestroy(&qf_mass); + CeedDestroy(&ceed); + return 0; +} diff --git a/tests/t406-qfunction.h b/tests/t406-qfunction.h new file mode 100644 index 0000000000..9200616151 --- /dev/null +++ b/tests/t406-qfunction.h @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. +// Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. +// All Rights reserved. See files LICENSE and NOTICE for details. +// +// This file is part of CEED, a collection of benchmarks, miniapps, software +// libraries and APIs for efficient high-order finite element and spectral +// element discretizations for exascale applications. For more information and +// source code availability see http://github.com/ceed. +// +// The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, +// a collaborative effort of two U.S. Department of Energy organizations (Office +// of Science and the National Nuclear Security Administration) responsible for +// the planning and preparation of a capable exascale ecosystem, including +// software, applications, hardware, advanced system engineering and early +// testbed platforms, in support of the nation's exascale computing imperative. + +// Note: intentionally testing strange spacing in '#include's +#include +# include "t406-qfunction-helper.h" + +CEED_QFUNCTION(setup)(void *ctx, const CeedInt Q, const CeedScalar *const *in, + CeedScalar *const *out) { + const CeedScalar *w = in[0]; + CeedScalar *q_data = out[0]; + for (CeedInt i=0; i