xref: /honee/include/petsc-ceed-utils.h (revision 2da92326014e054fa14489fdbd6cf7d1e81da829)
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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 **/
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