1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3c864c5abSJames Wright 4149fb536SJames Wright #include <navierstokes.h> 5c864c5abSJames Wright 6c864c5abSJames Wright #include <petscsection.h> 7c864c5abSJames Wright #include "../qfunctions/setupgeo.h" 8c864c5abSJames Wright #include "../qfunctions/setupgeo2d.h" 9c864c5abSJames Wright 10e816a7e4SJames Wright static CeedVector *q_data_vecs; 11e816a7e4SJames Wright static CeedElemRestriction *q_data_restrictions; 12e816a7e4SJames Wright static PetscInt num_q_data_stored; 13e816a7e4SJames Wright 14e816a7e4SJames Wright /** 15e816a7e4SJames Wright @brief Get stored QData objects that match created objects, if present 16e816a7e4SJames Wright 17e816a7e4SJames Wright If created objects are not present, they are added to the storage and returned in the output 18e816a7e4SJames Wright 19e816a7e4SJames Wright Not Collective 20e816a7e4SJames Wright 21e816a7e4SJames Wright @param[in] q_data_created Vector with created QData 22e816a7e4SJames Wright @param[in] elem_restr_qd_created Restriction for created QData 23e816a7e4SJames Wright @param[out] q_data_stored Vector from storage matching QData 24e816a7e4SJames Wright @param[out] elem_restr_qd_stored Restriction from storage matching QData 25e816a7e4SJames Wright **/ 26e816a7e4SJames Wright static PetscErrorCode QDataGetStored(CeedVector q_data_created, CeedElemRestriction elem_restr_qd_created, CeedVector *q_data_stored, 27e816a7e4SJames Wright CeedElemRestriction *elem_restr_qd_stored) { 28e816a7e4SJames Wright Ceed ceed = CeedVectorReturnCeed(q_data_created); 29e816a7e4SJames Wright CeedSize created_length, stored_length; 30e816a7e4SJames Wright PetscInt q_data_stored_index = -1; 31e816a7e4SJames Wright 32e816a7e4SJames Wright PetscFunctionBeginUser; 33e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorGetLength(q_data_created, &created_length)); 34e816a7e4SJames Wright for (PetscInt i = 0; i < num_q_data_stored; i++) { 35e816a7e4SJames Wright CeedVector difference_cvec; 36e816a7e4SJames Wright CeedScalar max_difference; 37e816a7e4SJames Wright 38e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorGetLength(q_data_vecs[0], &stored_length)); 39e816a7e4SJames Wright if (created_length != stored_length) continue; 40e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorCreate(ceed, stored_length, &difference_cvec)); 41e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorCopy(q_data_vecs[i], difference_cvec)); 42e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorAXPY(difference_cvec, -1, q_data_created)); 43e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorNorm(difference_cvec, CEED_NORM_MAX, &max_difference)); 44be29160dSJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&difference_cvec)); 45e816a7e4SJames Wright if (max_difference < 100 * CEED_EPSILON) { 46e816a7e4SJames Wright q_data_stored_index = i; 47e816a7e4SJames Wright break; 48e816a7e4SJames Wright } 49e816a7e4SJames Wright } 50e816a7e4SJames Wright 51e816a7e4SJames Wright if (q_data_stored_index == -1) { 52e816a7e4SJames Wright q_data_stored_index = num_q_data_stored++; 53e816a7e4SJames Wright 54e816a7e4SJames Wright PetscCall(PetscRealloc(num_q_data_stored * sizeof(CeedVector), &q_data_vecs)); 55e816a7e4SJames Wright PetscCall(PetscRealloc(num_q_data_stored * sizeof(CeedElemRestriction), &q_data_restrictions)); 56e816a7e4SJames Wright q_data_vecs[q_data_stored_index] = NULL; // Must set to NULL for ReferenceCopy 57e816a7e4SJames Wright q_data_restrictions[q_data_stored_index] = NULL; // Must set to NULL for ReferenceCopy 58e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorReferenceCopy(q_data_created, &q_data_vecs[q_data_stored_index])); 59e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionReferenceCopy(elem_restr_qd_created, &q_data_restrictions[q_data_stored_index])); 60e816a7e4SJames Wright } 61e816a7e4SJames Wright *q_data_stored = NULL; // Must set to NULL for ReferenceCopy 62e816a7e4SJames Wright *elem_restr_qd_stored = NULL; // Must set to NULL for ReferenceCopy 63e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorReferenceCopy(q_data_vecs[q_data_stored_index], q_data_stored)); 64e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionReferenceCopy(q_data_restrictions[q_data_stored_index], elem_restr_qd_stored)); 65e816a7e4SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 66e816a7e4SJames Wright } 67e816a7e4SJames Wright 68e816a7e4SJames Wright /** 69e816a7e4SJames Wright @brief Clear stored QData objects 70e816a7e4SJames Wright **/ 71e816a7e4SJames Wright PetscErrorCode QDataClearStoredData() { 72e816a7e4SJames Wright PetscFunctionBeginUser; 73e816a7e4SJames Wright for (PetscInt i = 0; i < num_q_data_stored; i++) { 74e816a7e4SJames Wright Ceed ceed = CeedVectorReturnCeed(q_data_vecs[i]); 75e816a7e4SJames Wright 76e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_vecs[i])); 77e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&q_data_restrictions[i])); 78e816a7e4SJames Wright } 79e816a7e4SJames Wright PetscCall(PetscFree(q_data_vecs)); 80e816a7e4SJames Wright PetscCall(PetscFree(q_data_restrictions)); 81e816a7e4SJames Wright q_data_vecs = NULL; 82e816a7e4SJames Wright q_data_restrictions = NULL; 83e816a7e4SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 84e816a7e4SJames Wright } 85e816a7e4SJames Wright 86c864c5abSJames Wright /** 87c864c5abSJames Wright * @brief Get number of components of quadrature data for domain 88c864c5abSJames Wright * 89c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 90c864c5abSJames Wright * @param[out] q_data_size Number of components of quadrature data 91c864c5abSJames Wright */ 92c864c5abSJames Wright PetscErrorCode QDataGetNumComponents(DM dm, CeedInt *q_data_size) { 93c864c5abSJames Wright PetscInt num_comp_x, dim; 94c864c5abSJames Wright 95c864c5abSJames Wright PetscFunctionBeginUser; 96c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 97*bc87537dSJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 98da8b59d6SJames Wright *q_data_size = 0; 99c864c5abSJames Wright switch (dim) { 100c864c5abSJames Wright case 2: 101c864c5abSJames Wright switch (num_comp_x) { 102c864c5abSJames Wright case 2: 103c864c5abSJames Wright *q_data_size = 5; 104c864c5abSJames Wright break; 105c864c5abSJames Wright case 3: 106c864c5abSJames Wright *q_data_size = 7; 107c864c5abSJames Wright break; 108c864c5abSJames Wright } 109c864c5abSJames Wright break; 110c864c5abSJames Wright case 3: 111c864c5abSJames Wright *q_data_size = 10; 112c864c5abSJames Wright break; 113c864c5abSJames Wright } 114da8b59d6SJames Wright PetscCheck(*q_data_size, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, 115da8b59d6SJames Wright "QData not valid for DM of dimension %" PetscInt_FMT " and coordinates with dimension %" PetscInt_FMT, dim, num_comp_x); 116c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 117c864c5abSJames Wright } 118c864c5abSJames Wright 119c864c5abSJames Wright /** 120c864c5abSJames Wright * @brief Create quadrature data for domain 121c864c5abSJames Wright * 122c864c5abSJames Wright * @param[in] ceed Ceed object quadrature data will be used with 123c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 124c864c5abSJames Wright * @param[in] domain_label DMLabel that quadrature data would be used one 125c864c5abSJames Wright * @param[in] label_value Value of label 126c864c5abSJames Wright * @param[in] elem_restr_x CeedElemRestriction of the coordinates (must match `domain_label` and `label_value` selections) 127c864c5abSJames Wright * @param[in] basis_x CeedBasis of the coordinates 128c864c5abSJames Wright * @param[in] x_coord CeedVector of the coordinates 129c864c5abSJames Wright * @param[out] elem_restr_qd CeedElemRestriction of the quadrature data 130c864c5abSJames Wright * @param[out] q_data CeedVector of the quadrature data 1314aea4664SJames Wright * @param[out] q_data_size Number of components of quadrature data 132c864c5abSJames Wright */ 133c864c5abSJames Wright PetscErrorCode QDataGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedElemRestriction elem_restr_x, CeedBasis basis_x, 134c864c5abSJames Wright CeedVector x_coord, CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 13587d3884fSJeremy L Thompson CeedQFunction qf_setup = NULL; 136c864c5abSJames Wright CeedOperator op_setup; 137e816a7e4SJames Wright CeedVector q_data_created; 138e816a7e4SJames Wright CeedElemRestriction elem_restr_qd_created; 139c864c5abSJames Wright CeedInt num_comp_x; 140c864c5abSJames Wright PetscInt dim, height = 0; 141c864c5abSJames Wright 142c864c5abSJames Wright PetscFunctionBeginUser; 143c864c5abSJames Wright PetscCall(QDataGetNumComponents(dm, q_data_size)); 144c864c5abSJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x, &num_comp_x)); 145c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 146c864c5abSJames Wright switch (dim) { 147c864c5abSJames Wright case 2: 148c864c5abSJames Wright switch (num_comp_x) { 149c864c5abSJames Wright case 2: 150c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup2d, Setup2d_loc, &qf_setup)); 151c864c5abSJames Wright break; 152c864c5abSJames Wright case 3: 153c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup2D_3Dcoords, Setup2D_3Dcoords_loc, &qf_setup)); 154c864c5abSJames Wright break; 155c864c5abSJames Wright } 156c864c5abSJames Wright break; 157c864c5abSJames Wright case 3: 158c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup, Setup_loc, &qf_setup)); 159c864c5abSJames Wright break; 160c864c5abSJames Wright } 161da8b59d6SJames Wright PetscCheck(qf_setup, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "%s not valid for DM of dimension %" PetscInt_FMT, __func__, dim); 162c864c5abSJames Wright 163c864c5abSJames Wright // -- Create QFunction for quadrature data 164c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(qf_setup, 0)); 165c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup, "dx", num_comp_x * (dim - height), CEED_EVAL_GRAD)); 166c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup, "weight", 1, CEED_EVAL_WEIGHT)); 167c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup, "surface qdata", *q_data_size, CEED_EVAL_NONE)); 168c864c5abSJames Wright 169e816a7e4SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, *q_data_size, &elem_restr_qd_created)); 170e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 171c864c5abSJames Wright 172c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup, NULL, NULL, &op_setup)); 173c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE)); 174c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE)); 175e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "surface qdata", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 176c864c5abSJames Wright 177e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 178c864c5abSJames Wright 179e816a7e4SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 180e816a7e4SJames Wright 181e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 182e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 183c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup)); 184c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup)); 185c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 186c864c5abSJames Wright } 187c864c5abSJames Wright 188c864c5abSJames Wright /** 189c864c5abSJames Wright * @brief Get number of components of quadrature data for boundary of domain 190c864c5abSJames Wright * 191c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 192c864c5abSJames Wright * @param[out] q_data_size Number of components of quadrature data 193c864c5abSJames Wright */ 194c864c5abSJames Wright PetscErrorCode QDataBoundaryGetNumComponents(DM dm, CeedInt *q_data_size) { 195c864c5abSJames Wright PetscInt dim; 196c864c5abSJames Wright 197c864c5abSJames Wright PetscFunctionBeginUser; 198c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 199da8b59d6SJames Wright *q_data_size = 0; 200c864c5abSJames Wright switch (dim) { 201c864c5abSJames Wright case 2: 202c864c5abSJames Wright *q_data_size = 3; 203c864c5abSJames Wright break; 204c864c5abSJames Wright case 3: 205c864c5abSJames Wright *q_data_size = 10; 206c864c5abSJames Wright break; 207c864c5abSJames Wright } 208da8b59d6SJames Wright PetscCheck(*q_data_size, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "%s not valid for DM of dimension %" PetscInt_FMT, __func__, dim); 209c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 210c864c5abSJames Wright } 211c864c5abSJames Wright 212c864c5abSJames Wright /** 213c864c5abSJames Wright * @brief Create quadrature data for boundary of domain 214c864c5abSJames Wright * 215c864c5abSJames Wright * @param[in] ceed Ceed object quadrature data will be used with 216c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 217c864c5abSJames Wright * @param[in] domain_label DMLabel that quadrature data would be used one 218c864c5abSJames Wright * @param[in] label_value Value of label 219c864c5abSJames Wright * @param[in] elem_restr_x CeedElemRestriction of the coordinates (must match `domain_label` and `label_value` selections) 220c864c5abSJames Wright * @param[in] basis_x CeedBasis of the coordinates 221c864c5abSJames Wright * @param[in] x_coord CeedVector of the coordinates 222c864c5abSJames Wright * @param[out] elem_restr_qd CeedElemRestriction of the quadrature data 223c864c5abSJames Wright * @param[out] q_data CeedVector of the quadrature data 2244aea4664SJames Wright * @param[out] q_data_size Number of components of quadrature data 225c864c5abSJames Wright */ 226c864c5abSJames Wright PetscErrorCode QDataBoundaryGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedElemRestriction elem_restr_x, CeedBasis basis_x, 227c864c5abSJames Wright CeedVector x_coord, CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 22887d3884fSJeremy L Thompson CeedQFunction qf_setup_sur = NULL; 229c864c5abSJames Wright CeedOperator op_setup_sur; 230e816a7e4SJames Wright CeedVector q_data_created; 231e816a7e4SJames Wright CeedElemRestriction elem_restr_qd_created; 232c864c5abSJames Wright CeedInt num_comp_x; 233c864c5abSJames Wright PetscInt dim, height = 1; 234c864c5abSJames Wright 235c864c5abSJames Wright PetscFunctionBeginUser; 236c864c5abSJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, q_data_size)); 237c864c5abSJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x, &num_comp_x)); 238c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 239c864c5abSJames Wright switch (dim) { 240c864c5abSJames Wright case 2: 241c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundary2d, SetupBoundary2d_loc, &qf_setup_sur)); 242c864c5abSJames Wright break; 243c864c5abSJames Wright case 3: 244c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundary, SetupBoundary_loc, &qf_setup_sur)); 245c864c5abSJames Wright break; 246c864c5abSJames Wright } 247da8b59d6SJames Wright PetscCheck(qf_setup_sur, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "%s not valid for DM of dimension %" PetscInt_FMT, __func__, dim); 248c864c5abSJames Wright 249c864c5abSJames Wright // -- Create QFunction for quadrature data 250c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(qf_setup_sur, 0)); 251c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx", num_comp_x * (dim - height), CEED_EVAL_GRAD)); 252c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "weight", 1, CEED_EVAL_WEIGHT)); 253c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup_sur, "surface qdata", *q_data_size, CEED_EVAL_NONE)); 254c864c5abSJames Wright 255e816a7e4SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, *q_data_size, &elem_restr_qd_created)); 256e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 257c864c5abSJames Wright 258c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup_sur, NULL, NULL, &op_setup_sur)); 259c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE)); 260c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE)); 261e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "surface qdata", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 262c864c5abSJames Wright 263e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup_sur, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 264c864c5abSJames Wright 265e816a7e4SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 266e816a7e4SJames Wright 267e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 268e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 269c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup_sur)); 270c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup_sur)); 271c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 272c864c5abSJames Wright } 2738c85b835SJames Wright 2748c85b835SJames Wright /** 2758c85b835SJames Wright * @brief Get number of components of quadrature data for boundary of domain 2768c85b835SJames Wright * 2778c85b835SJames Wright * @param[in] dm DM where quadrature data would be used 2788c85b835SJames Wright * @param[out] q_data_size Number of components of quadrature data 2798c85b835SJames Wright */ 2808c85b835SJames Wright PetscErrorCode QDataBoundaryGradientGetNumComponents(DM dm, CeedInt *q_data_size) { 2818c85b835SJames Wright PetscInt dim; 2828c85b835SJames Wright 2838c85b835SJames Wright PetscFunctionBeginUser; 2848c85b835SJames Wright PetscCall(DMGetDimension(dm, &dim)); 285da8b59d6SJames Wright *q_data_size = 0; 2868c85b835SJames Wright switch (dim) { 287da8b59d6SJames Wright case 2: 288da8b59d6SJames Wright *q_data_size = 7; 289da8b59d6SJames Wright break; 2908c85b835SJames Wright case 3: 2918c85b835SJames Wright *q_data_size = 13; 2928c85b835SJames Wright break; 2938c85b835SJames Wright } 294da8b59d6SJames Wright PetscCheck(*q_data_size, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "%s not valid for DM of dimension %" PetscInt_FMT, __func__, dim); 2958c85b835SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2968c85b835SJames Wright } 2978c85b835SJames Wright 2988c85b835SJames Wright /** 2998c85b835SJames Wright @brief Compute `CeedOperator` surface gradient QData 3008c85b835SJames Wright 3018c85b835SJames Wright Collective across MPI processes. 3028c85b835SJames Wright 3038c85b835SJames Wright @param[in] ceed `Ceed` object 3048c85b835SJames Wright @param[in] dm `DMPlex` grid 3058c85b835SJames Wright @param[in] domain_label `DMLabel` for surface 3068c85b835SJames Wright @param[in] label_value `DMPlex` label value for surface 3078c85b835SJames Wright @param[in] x_coord `CeedVector` for coordinates 30800dbc7b1SJames Wright @param[out] elem_restr_qd `CeedElemRestriction` for QData 3098c85b835SJames Wright @param[out] q_data `CeedVector` holding QData 3108c85b835SJames Wright @param[out] q_data_size Number of QData components per quadrature point 3118c85b835SJames Wright **/ 3128c85b835SJames Wright PetscErrorCode QDataBoundaryGradientGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedVector x_coord, 31300dbc7b1SJames Wright CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 3148c85b835SJames Wright PetscInt dim; 3158c85b835SJames Wright const PetscInt height_cell = 0, height_face = 1; 3168c85b835SJames Wright CeedInt num_comp_x; 317f17df9b6SJames Wright CeedElemRestriction elem_restr_x_cell, elem_restr_x_face, elem_restr_qd_created; 318f17df9b6SJames Wright CeedVector q_data_created; 3198c85b835SJames Wright CeedBasis basis_x_cell_to_face, basis_x_face; 320da8b59d6SJames Wright CeedQFunction qf_setup_sur = NULL; 3218c85b835SJames Wright CeedOperator op_setup_sur; 3228c85b835SJames Wright 3238c85b835SJames Wright PetscFunctionBeginUser; 3248c85b835SJames Wright PetscCall(CreateCoordinateBasisFromPlex(ceed, dm, domain_label, label_value, height_face, &basis_x_face)); 3258c85b835SJames Wright PetscCall(DMPlexCeedBasisCellToFaceCoordinateCreate(ceed, dm, domain_label, label_value, label_value, &basis_x_cell_to_face)); 32600dbc7b1SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height_cell, &elem_restr_x_cell)); 3278c85b835SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height_face, &elem_restr_x_face)); 3288c85b835SJames Wright 3298c85b835SJames Wright PetscCall(QDataBoundaryGradientGetNumComponents(dm, q_data_size)); 330f17df9b6SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height_face, *q_data_size, &elem_restr_qd_created)); 331f17df9b6SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 3328c85b835SJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x_face, &num_comp_x)); 3338c85b835SJames Wright 334da8b59d6SJames Wright PetscCall(DMGetDimension(dm, &dim)); 335da8b59d6SJames Wright switch (dim) { 336da8b59d6SJames Wright case 2: 337da8b59d6SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup2DBoundaryGradient, Setup2DBoundaryGradient_loc, &qf_setup_sur)); 338da8b59d6SJames Wright break; 339da8b59d6SJames Wright case 3: 3408c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundaryGradient, SetupBoundaryGradient_loc, &qf_setup_sur)); 341da8b59d6SJames Wright break; 342da8b59d6SJames Wright } 343da8b59d6SJames Wright PetscCheck(qf_setup_sur, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "%s not valid for DM of dimension %" PetscInt_FMT, __func__, dim); 344da8b59d6SJames Wright 3458c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx/dX cell", num_comp_x * (dim - height_cell), CEED_EVAL_GRAD)); 3468c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx/dX face", num_comp_x * (dim - height_face), CEED_EVAL_GRAD)); 3478c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "weight", 1, CEED_EVAL_WEIGHT)); 3488c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup_sur, "q data", *q_data_size, CEED_EVAL_NONE)); 3498c85b835SJames Wright 3508c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup_sur, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup_sur)); 35100dbc7b1SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx/dX cell", elem_restr_x_cell, basis_x_cell_to_face, CEED_VECTOR_ACTIVE)); 3528c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx/dX face", elem_restr_x_face, basis_x_face, CEED_VECTOR_ACTIVE)); 3538c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "weight", CEED_ELEMRESTRICTION_NONE, basis_x_face, CEED_VECTOR_NONE)); 354f17df9b6SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "q data", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 3558c85b835SJames Wright 356f17df9b6SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup_sur, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 357f17df9b6SJames Wright 358f17df9b6SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 3598c85b835SJames Wright 3608c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup_sur)); 3618c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup_sur)); 362f17df9b6SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 363f17df9b6SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 3648c85b835SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x_face)); 36500dbc7b1SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x_cell)); 3668c85b835SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x_face)); 3678c85b835SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x_cell_to_face)); 3688c85b835SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 3698c85b835SJames Wright } 370