1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
340d80af1SJames Wright #pragma once
440d80af1SJames Wright
540d80af1SJames Wright #include <ceed.h>
6519781aeSJames Wright #include <petsc-ceed.h>
740d80af1SJames Wright #include <petscdm.h>
840d80af1SJames Wright
940d80af1SJames Wright /**
1040d80af1SJames Wright @brief Copy the reference to a `Vec`.
1140d80af1SJames Wright Note: If `vec_copy` is non-null, it is assumed to be a valid pointer to a `Vec` and `VecDestroy()` will be called.
1240d80af1SJames Wright
1340d80af1SJames Wright Collective across MPI processes.
1440d80af1SJames Wright
1540d80af1SJames Wright @param[in] vec `Vec` to reference
1640d80af1SJames Wright @param[out] vec_copy Copy of reference
1740d80af1SJames Wright
1840d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
1940d80af1SJames Wright **/
VecReferenceCopy(Vec vec,Vec * vec_copy)2040d80af1SJames Wright static inline PetscErrorCode VecReferenceCopy(Vec vec, Vec *vec_copy) {
2140d80af1SJames Wright PetscFunctionBeginUser;
2240d80af1SJames Wright PetscCall(PetscObjectReference((PetscObject)vec));
2340d80af1SJames Wright PetscCall(VecDestroy(vec_copy));
2440d80af1SJames Wright *vec_copy = vec;
2540d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
2640d80af1SJames Wright }
2740d80af1SJames Wright
2840d80af1SJames Wright /**
2940d80af1SJames Wright @brief Copy the reference to a `DM`.
3040d80af1SJames Wright Note: If `dm_copy` is non-null, it is assumed to be a valid pointer to a `DM` and `DMDestroy()` will be called.
3140d80af1SJames Wright
3240d80af1SJames Wright Collective across MPI processes.
3340d80af1SJames Wright
3440d80af1SJames Wright @param[in] dm `DM` to reference
3540d80af1SJames Wright @param[out] dm_copy Copy of reference
3640d80af1SJames Wright
3740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
3840d80af1SJames Wright **/
DMReferenceCopy(DM dm,DM * dm_copy)3940d80af1SJames Wright static inline PetscErrorCode DMReferenceCopy(DM dm, DM *dm_copy) {
4040d80af1SJames Wright PetscFunctionBeginUser;
4140d80af1SJames Wright PetscCall(PetscObjectReference((PetscObject)dm));
4240d80af1SJames Wright PetscCall(DMDestroy(dm_copy));
4340d80af1SJames Wright *dm_copy = dm;
4440d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
4540d80af1SJames Wright }
4640d80af1SJames Wright
4740d80af1SJames Wright /**
4840d80af1SJames Wright @brief Translate PetscMemType to CeedMemType
4940d80af1SJames Wright
5040d80af1SJames Wright @param[in] mem_type PetscMemType
5140d80af1SJames Wright
5240d80af1SJames Wright @return Equivalent CeedMemType
5340d80af1SJames Wright **/
MemTypePetscToCeed(PetscMemType mem_type)5440d80af1SJames Wright static inline CeedMemType MemTypePetscToCeed(PetscMemType mem_type) { return PetscMemTypeDevice(mem_type) ? CEED_MEM_DEVICE : CEED_MEM_HOST; }
5540d80af1SJames Wright
5640d80af1SJames Wright /**
5740d80af1SJames Wright @brief Translate array of `PetscInt` to `CeedInt`.
58f89fad55SJames Wright If the types differ, `array_ceed` is freed with `free()` and `array_petsc` is allocated with `malloc()`.
5940d80af1SJames Wright Caller is responsible for freeing `array_ceed` with `PetscFree()`.
6040d80af1SJames Wright
6140d80af1SJames Wright Not collective across MPI processes.
6240d80af1SJames Wright
6340d80af1SJames Wright @param[in] num_entries Number of array entries
6440d80af1SJames Wright @param[in,out] array_petsc Array of `PetscInt`
6540d80af1SJames Wright @param[out] array_ceed Array of `CeedInt`
6640d80af1SJames Wright
6740d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
6840d80af1SJames Wright **/
IntArrayCeedToPetsc(PetscCount num_entries,CeedInt ** array_ceed,PetscInt ** array_petsc)69ed5c6999SJames Wright static inline PetscErrorCode IntArrayCeedToPetsc(PetscCount num_entries, CeedInt **array_ceed, PetscInt **array_petsc) {
7040d80af1SJames Wright const CeedInt int_c = 0;
7140d80af1SJames Wright const PetscInt int_p = 0;
7240d80af1SJames Wright
7340d80af1SJames Wright PetscFunctionBeginUser;
7440d80af1SJames Wright if (sizeof(int_c) == sizeof(int_p)) {
7540d80af1SJames Wright *array_petsc = (PetscInt *)*array_ceed;
7640d80af1SJames Wright } else {
7740d80af1SJames Wright *array_petsc = malloc(num_entries * sizeof(PetscInt));
7840d80af1SJames Wright for (PetscInt i = 0; i < num_entries; i++) (*array_petsc)[i] = (*array_ceed)[i];
7940d80af1SJames Wright free(*array_ceed);
8040d80af1SJames Wright }
8140d80af1SJames Wright *array_ceed = NULL;
8240d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
8340d80af1SJames Wright }
8440d80af1SJames Wright
8540d80af1SJames Wright /**
8640d80af1SJames Wright @brief Translate array of `PetscInt` to `CeedInt`.
8740d80af1SJames Wright If the types differ, `array_petsc` is freed with `PetscFree()` and `array_ceed` is allocated with `PetscMalloc1()`.
8840d80af1SJames Wright Caller is responsible for freeing `array_ceed` with `PetscFree()`.
8940d80af1SJames Wright
9040d80af1SJames Wright Not collective across MPI processes.
9140d80af1SJames Wright
9240d80af1SJames Wright @param[in] num_entries Number of array entries
9340d80af1SJames Wright @param[in,out] array_petsc Array of `PetscInt`
9440d80af1SJames Wright @param[out] array_ceed Array of `CeedInt`
9540d80af1SJames Wright
9640d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
9740d80af1SJames Wright **/
IntArrayPetscToCeed(PetscCount num_entries,PetscInt ** array_petsc,CeedInt ** array_ceed)98ed5c6999SJames Wright static inline PetscErrorCode IntArrayPetscToCeed(PetscCount num_entries, PetscInt **array_petsc, CeedInt **array_ceed) {
9940d80af1SJames Wright const CeedInt int_c = 0;
10040d80af1SJames Wright const PetscInt int_p = 0;
10140d80af1SJames Wright
10240d80af1SJames Wright PetscFunctionBeginUser;
10340d80af1SJames Wright if (sizeof(int_c) == sizeof(int_p)) {
10440d80af1SJames Wright *array_ceed = (CeedInt *)*array_petsc;
10540d80af1SJames Wright } else {
10640d80af1SJames Wright PetscCall(PetscMalloc1(num_entries, array_ceed));
10740d80af1SJames Wright for (PetscInt i = 0; i < num_entries; i++) (*array_ceed)[i] = (*array_petsc)[i];
10840d80af1SJames Wright PetscCall(PetscFree(*array_petsc));
10940d80af1SJames Wright }
11040d80af1SJames Wright *array_petsc = NULL;
11140d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
11240d80af1SJames Wright }
11340d80af1SJames Wright
11440d80af1SJames Wright /**
11540d80af1SJames Wright @brief Transfer array from PETSc `Vec` to `CeedVector`.
11640d80af1SJames Wright
11740d80af1SJames Wright Collective across MPI processes.
11840d80af1SJames Wright
11940d80af1SJames Wright @param[in] X_petsc PETSc `Vec`
12040d80af1SJames Wright @param[out] mem_type PETSc `MemType`
12140d80af1SJames Wright @param[out] x_ceed `CeedVector`
12240d80af1SJames Wright
12340d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
12440d80af1SJames Wright **/
VecPetscToCeed(Vec X_petsc,PetscMemType * mem_type,CeedVector x_ceed)12540d80af1SJames Wright static inline PetscErrorCode VecPetscToCeed(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) {
12640d80af1SJames Wright PetscScalar *x;
12740d80af1SJames Wright
12840d80af1SJames Wright PetscFunctionBeginUser;
12940d80af1SJames Wright PetscCall(VecGetArrayAndMemType(X_petsc, &x, mem_type));
13040d80af1SJames Wright PetscCallCeed(CeedVectorReturnCeed(x_ceed), CeedVectorSetArray(x_ceed, MemTypePetscToCeed(*mem_type), CEED_USE_POINTER, x));
13140d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
13240d80af1SJames Wright }
13340d80af1SJames Wright
13440d80af1SJames Wright /**
13540d80af1SJames Wright @brief Transfer array from `CeedVector` to PETSc `Vec`.
13640d80af1SJames Wright
13740d80af1SJames Wright Collective across MPI processes.
13840d80af1SJames Wright
13940d80af1SJames Wright @param[in] x_ceed `CeedVector`
14040d80af1SJames Wright @param[in] mem_type PETSc `MemType`
14140d80af1SJames Wright @param[out] X_petsc PETSc `Vec`
14240d80af1SJames Wright
14340d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
14440d80af1SJames Wright **/
VecCeedToPetsc(CeedVector x_ceed,PetscMemType mem_type,Vec X_petsc)14540d80af1SJames Wright static inline PetscErrorCode VecCeedToPetsc(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) {
14640d80af1SJames Wright PetscScalar *x;
14740d80af1SJames Wright
14840d80af1SJames Wright PetscFunctionBeginUser;
14940d80af1SJames Wright PetscCallCeed(CeedVectorReturnCeed(x_ceed), CeedVectorTakeArray(x_ceed, MemTypePetscToCeed(mem_type), &x));
15040d80af1SJames Wright PetscCall(VecRestoreArrayAndMemType(X_petsc, &x));
15140d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
15240d80af1SJames Wright }
15340d80af1SJames Wright
15440d80af1SJames Wright /**
15540d80af1SJames Wright @brief Transfer read only array from PETSc `Vec` to `CeedVector`.
15640d80af1SJames Wright
15740d80af1SJames Wright Collective across MPI processes.
15840d80af1SJames Wright
15940d80af1SJames Wright @param[in] X_petsc PETSc `Vec`
16040d80af1SJames Wright @param[out] mem_type PETSc `MemType`
16140d80af1SJames Wright @param[out] x_ceed `CeedVector`
16240d80af1SJames Wright
16340d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
16440d80af1SJames Wright **/
VecReadPetscToCeed(Vec X_petsc,PetscMemType * mem_type,CeedVector x_ceed)16540d80af1SJames Wright static inline PetscErrorCode VecReadPetscToCeed(Vec X_petsc, PetscMemType *mem_type, CeedVector x_ceed) {
16640d80af1SJames Wright PetscScalar *x;
16740d80af1SJames Wright
16840d80af1SJames Wright PetscFunctionBeginUser;
16940d80af1SJames Wright PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, mem_type));
17040d80af1SJames Wright PetscCallCeed(CeedVectorReturnCeed(x_ceed), CeedVectorSetArray(x_ceed, MemTypePetscToCeed(*mem_type), CEED_USE_POINTER, x));
17140d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
17240d80af1SJames Wright }
17340d80af1SJames Wright
17440d80af1SJames Wright /**
17540d80af1SJames Wright @brief Transfer read only array from `CeedVector` to PETSc `Vec`.
17640d80af1SJames Wright
17740d80af1SJames Wright Collective across MPI processes.
17840d80af1SJames Wright
17940d80af1SJames Wright @param[in] x_ceed `CeedVector`
18040d80af1SJames Wright @param[in] mem_type PETSc `MemType`
18140d80af1SJames Wright @param[out] X_petsc PETSc `Vec`
18240d80af1SJames Wright
18340d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
18440d80af1SJames Wright **/
VecReadCeedToPetsc(CeedVector x_ceed,PetscMemType mem_type,Vec X_petsc)18540d80af1SJames Wright static inline PetscErrorCode VecReadCeedToPetsc(CeedVector x_ceed, PetscMemType mem_type, Vec X_petsc) {
18640d80af1SJames Wright PetscScalar *x;
18740d80af1SJames Wright
18840d80af1SJames Wright PetscFunctionBeginUser;
18940d80af1SJames Wright PetscCallCeed(CeedVectorReturnCeed(x_ceed), CeedVectorTakeArray(x_ceed, MemTypePetscToCeed(mem_type), &x));
19040d80af1SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x));
19140d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
19240d80af1SJames Wright }
19340d80af1SJames Wright
19440d80af1SJames Wright /**
19540d80af1SJames Wright @brief Copy PETSc `Vec` data into `CeedVector`
19640d80af1SJames Wright
19740d80af1SJames Wright @param[in] X_petsc PETSc `Vec`
19840d80af1SJames Wright @param[out] x_ceed `CeedVector`
19940d80af1SJames Wright
20040d80af1SJames Wright @return An error code: 0 - success, otherwise - failure
20140d80af1SJames Wright **/
VecCopyPetscToCeed(Vec X_petsc,CeedVector x_ceed)20240d80af1SJames Wright static inline PetscErrorCode VecCopyPetscToCeed(Vec X_petsc, CeedVector x_ceed) {
20340d80af1SJames Wright PetscScalar *x;
20440d80af1SJames Wright PetscMemType mem_type;
20540d80af1SJames Wright PetscInt X_size;
20640d80af1SJames Wright CeedSize x_size;
20740d80af1SJames Wright Ceed ceed;
20840d80af1SJames Wright
20940d80af1SJames Wright PetscFunctionBeginUser;
21040d80af1SJames Wright PetscCall(CeedVectorGetCeed(x_ceed, &ceed));
21140d80af1SJames Wright PetscCall(VecGetLocalSize(X_petsc, &X_size));
21240d80af1SJames Wright PetscCallCeed(ceed, CeedVectorGetLength(x_ceed, &x_size));
21340d80af1SJames Wright PetscCheck(X_size == x_size, PETSC_COMM_WORLD, PETSC_ERR_ARG_SIZ, "X_petsc (%" PetscInt_FMT ") and x_ceed (%" CeedSize_FMT ") must be same size",
21440d80af1SJames Wright X_size, x_size);
21540d80af1SJames Wright
21640d80af1SJames Wright PetscCall(VecGetArrayReadAndMemType(X_petsc, (const PetscScalar **)&x, &mem_type));
21740d80af1SJames Wright PetscCallCeed(ceed, CeedVectorSetArray(x_ceed, MemTypePetscToCeed(mem_type), CEED_COPY_VALUES, x));
21840d80af1SJames Wright PetscCall(VecRestoreArrayReadAndMemType(X_petsc, (const PetscScalar **)&x));
219519781aeSJames Wright PetscCheck(CeedDestroy(&ceed) == CEED_ERROR_SUCCESS, PetscObjectComm((PetscObject)X_petsc), PETSC_ERR_LIB, "Destroying Ceed object failed");
22040d80af1SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
22140d80af1SJames Wright }
22240d80af1SJames Wright
22340d80af1SJames Wright /**
22440d80af1SJames Wright @brief Return the quadrature size from the eval mode, dimension, and number of components
22540d80af1SJames Wright
22640d80af1SJames Wright @param[in] eval_mode The basis evaluation mode
22740d80af1SJames Wright @param[in] dim The basis dimension
22840d80af1SJames Wright @param[in] num_components The basis number of components
22940d80af1SJames Wright
23040d80af1SJames Wright @return The maximum of the two integers
23140d80af1SJames Wright
23240d80af1SJames Wright **/
GetCeedQuadratureSize(CeedEvalMode eval_mode,CeedInt dim,CeedInt num_components)23340d80af1SJames Wright static inline CeedInt GetCeedQuadratureSize(CeedEvalMode eval_mode, CeedInt dim, CeedInt num_components) {
23440d80af1SJames Wright switch (eval_mode) {
23540d80af1SJames Wright case CEED_EVAL_INTERP:
23640d80af1SJames Wright return num_components;
23740d80af1SJames Wright case CEED_EVAL_GRAD:
23840d80af1SJames Wright return dim * num_components;
23940d80af1SJames Wright default:
24040d80af1SJames Wright return -1;
24140d80af1SJames Wright }
24240d80af1SJames Wright }
24340d80af1SJames Wright
24440d80af1SJames Wright /**
24540d80af1SJames Wright @brief Convert from DMPolytopeType to CeedElemTopology
24640d80af1SJames Wright
24740d80af1SJames Wright @param[in] cell_type DMPolytopeType for the cell
24840d80af1SJames Wright
24940d80af1SJames Wright @return CeedElemTopology, or 0 if no equivelent CeedElemTopology was found
25040d80af1SJames Wright **/
PolytopeTypePetscToCeed(DMPolytopeType cell_type)25140d80af1SJames Wright static inline CeedElemTopology PolytopeTypePetscToCeed(DMPolytopeType cell_type) {
25240d80af1SJames Wright switch (cell_type) {
25340d80af1SJames Wright case DM_POLYTOPE_TRIANGLE:
25440d80af1SJames Wright return CEED_TOPOLOGY_TRIANGLE;
25540d80af1SJames Wright case DM_POLYTOPE_QUADRILATERAL:
25640d80af1SJames Wright return CEED_TOPOLOGY_QUAD;
25740d80af1SJames Wright case DM_POLYTOPE_TETRAHEDRON:
25840d80af1SJames Wright return CEED_TOPOLOGY_TET;
25940d80af1SJames Wright case DM_POLYTOPE_HEXAHEDRON:
26040d80af1SJames Wright return CEED_TOPOLOGY_HEX;
26140d80af1SJames Wright default:
26240d80af1SJames Wright return 0;
26340d80af1SJames Wright }
26440d80af1SJames Wright }
265ed5c6999SJames Wright
266ed5c6999SJames Wright /**
267ed5c6999SJames Wright @brief Get default `MatType` for a given `VecType`
268ed5c6999SJames Wright
269ed5c6999SJames Wright Not collective across MPI processes.
270ed5c6999SJames Wright
271ed5c6999SJames Wright @param[in] vec_type `VecType` to check
272ed5c6999SJames Wright @param[out] mat_type Default `MatType` for `VecType`
273ed5c6999SJames Wright
274ed5c6999SJames Wright @return An error code: 0 - success, otherwise - failure
275ed5c6999SJames Wright **/
DefaultMatTypeFromVecType(VecType vec_type,MatType * mat_type)276ed5c6999SJames Wright static inline PetscErrorCode DefaultMatTypeFromVecType(VecType vec_type, MatType *mat_type) {
277ed5c6999SJames Wright PetscFunctionBeginUser;
278ed5c6999SJames Wright if (strstr(vec_type, VECCUDA)) *mat_type = MATAIJCUSPARSE;
279ed5c6999SJames Wright else if (strstr(vec_type, VECHIP)) *mat_type = MATAIJHIPSPARSE;
280ed5c6999SJames Wright else if (strstr(vec_type, VECKOKKOS)) *mat_type = MATAIJKOKKOS;
281ed5c6999SJames Wright else *mat_type = MATAIJ;
282ed5c6999SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
283ed5c6999SJames Wright }
284ed5c6999SJames Wright
285ed5c6999SJames Wright /**
286ed5c6999SJames Wright @brief Get the default `PetscMemType` for a `Mat`
287ed5c6999SJames Wright
288ed5c6999SJames Wright Not collective across MPI processes.
289ed5c6999SJames Wright
290ed5c6999SJames Wright @param[in] mat `Mat` to get `PetscMemType` for
291ed5c6999SJames Wright @param[out] mem_type Current default `PetscMemType` for @a mat
292ed5c6999SJames Wright
293ed5c6999SJames Wright @return An error code: 0 - success, otherwise - failure
294ed5c6999SJames Wright **/
MatGetMemTypeFromVecType(Mat mat,PetscMemType * mem_type)295*2da92326SJames Wright static inline PetscErrorCode MatGetMemTypeFromVecType(Mat mat, PetscMemType *mem_type) {
296ed5c6999SJames Wright PetscBool bound;
297ed5c6999SJames Wright
298ed5c6999SJames Wright PetscFunctionBeginUser;
299ed5c6999SJames Wright *mem_type = PETSC_MEMTYPE_HOST;
300ed5c6999SJames Wright PetscCall(MatBoundToCPU(mat, &bound));
301ed5c6999SJames Wright if (!bound) {
302ed5c6999SJames Wright VecType vec_type;
303ed5c6999SJames Wright
304ed5c6999SJames Wright PetscCall(MatGetVecType(mat, &vec_type));
305ed5c6999SJames Wright if (strstr(vec_type, VECCUDA)) *mem_type = PETSC_MEMTYPE_CUDA;
306ed5c6999SJames Wright else if (strstr(vec_type, VECHIP)) *mem_type = PETSC_MEMTYPE_HIP;
307ed5c6999SJames Wright else if (strstr(vec_type, VECKOKKOS)) *mem_type = PETSC_MEMTYPE_KOKKOS;
308ed5c6999SJames Wright }
309ed5c6999SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
310ed5c6999SJames Wright }
311