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)); 97c864c5abSJames Wright { // Get number of coordinate components 98c864c5abSJames Wright DM dm_coord; 99c864c5abSJames Wright PetscSection section_coord; 100c864c5abSJames Wright PetscInt field = 0; // Default field has the coordinates 1014aea4664SJames Wright 102c864c5abSJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 103c864c5abSJames Wright PetscCall(DMGetLocalSection(dm_coord, §ion_coord)); 104c864c5abSJames Wright PetscCall(PetscSectionGetFieldComponents(section_coord, field, &num_comp_x)); 105c864c5abSJames Wright } 106c864c5abSJames Wright switch (dim) { 107c864c5abSJames Wright case 2: 108c864c5abSJames Wright switch (num_comp_x) { 109c864c5abSJames Wright case 2: 110c864c5abSJames Wright *q_data_size = 5; 111c864c5abSJames Wright break; 112c864c5abSJames Wright case 3: 113c864c5abSJames Wright *q_data_size = 7; 114c864c5abSJames Wright break; 115c864c5abSJames Wright default: 116c864c5abSJames Wright SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, 117c864c5abSJames Wright "QData not valid for DM of dimension %" PetscInt_FMT " and coordinates with dimension %" PetscInt_FMT, dim, num_comp_x); 118c864c5abSJames Wright break; 119c864c5abSJames Wright } 120c864c5abSJames Wright break; 121c864c5abSJames Wright case 3: 122c864c5abSJames Wright *q_data_size = 10; 123c864c5abSJames Wright break; 124c864c5abSJames Wright default: 125c864c5abSJames Wright SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, 126c864c5abSJames Wright "QData not valid for DM of dimension %" PetscInt_FMT " and coordinates with dimension %" PetscInt_FMT, dim, num_comp_x); 127c864c5abSJames Wright break; 128c864c5abSJames Wright } 129c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 130c864c5abSJames Wright } 131c864c5abSJames Wright 132c864c5abSJames Wright /** 133c864c5abSJames Wright * @brief Create quadrature data for domain 134c864c5abSJames Wright * 135c864c5abSJames Wright * @param[in] ceed Ceed object quadrature data will be used with 136c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 137c864c5abSJames Wright * @param[in] domain_label DMLabel that quadrature data would be used one 138c864c5abSJames Wright * @param[in] label_value Value of label 139c864c5abSJames Wright * @param[in] elem_restr_x CeedElemRestriction of the coordinates (must match `domain_label` and `label_value` selections) 140c864c5abSJames Wright * @param[in] basis_x CeedBasis of the coordinates 141c864c5abSJames Wright * @param[in] x_coord CeedVector of the coordinates 142c864c5abSJames Wright * @param[out] elem_restr_qd CeedElemRestriction of the quadrature data 143c864c5abSJames Wright * @param[out] q_data CeedVector of the quadrature data 1444aea4664SJames Wright * @param[out] q_data_size Number of components of quadrature data 145c864c5abSJames Wright */ 146c864c5abSJames Wright PetscErrorCode QDataGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedElemRestriction elem_restr_x, CeedBasis basis_x, 147c864c5abSJames Wright CeedVector x_coord, CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 14887d3884fSJeremy L Thompson CeedQFunction qf_setup = NULL; 149c864c5abSJames Wright CeedOperator op_setup; 150e816a7e4SJames Wright CeedVector q_data_created; 151e816a7e4SJames Wright CeedElemRestriction elem_restr_qd_created; 152c864c5abSJames Wright CeedInt num_comp_x; 153c864c5abSJames Wright PetscInt dim, height = 0; 154c864c5abSJames Wright 155c864c5abSJames Wright PetscFunctionBeginUser; 156c864c5abSJames Wright PetscCall(QDataGetNumComponents(dm, q_data_size)); 157c864c5abSJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x, &num_comp_x)); 158c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 159c864c5abSJames Wright switch (dim) { 160c864c5abSJames Wright case 2: 161c864c5abSJames Wright switch (num_comp_x) { 162c864c5abSJames Wright case 2: 163c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup2d, Setup2d_loc, &qf_setup)); 164c864c5abSJames Wright break; 165c864c5abSJames Wright case 3: 166c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup2D_3Dcoords, Setup2D_3Dcoords_loc, &qf_setup)); 167c864c5abSJames Wright break; 168c864c5abSJames Wright } 169c864c5abSJames Wright break; 170c864c5abSJames Wright case 3: 171c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, Setup, Setup_loc, &qf_setup)); 172c864c5abSJames Wright break; 173c864c5abSJames Wright } 174c864c5abSJames Wright 175c864c5abSJames Wright // -- Create QFunction for quadrature data 176c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(qf_setup, 0)); 177c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup, "dx", num_comp_x * (dim - height), CEED_EVAL_GRAD)); 178c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup, "weight", 1, CEED_EVAL_WEIGHT)); 179c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup, "surface qdata", *q_data_size, CEED_EVAL_NONE)); 180c864c5abSJames Wright 181e816a7e4SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, *q_data_size, &elem_restr_qd_created)); 182e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 183c864c5abSJames Wright 184c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup, NULL, NULL, &op_setup)); 185c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE)); 186c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE)); 187e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup, "surface qdata", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 188c864c5abSJames Wright 189e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 190c864c5abSJames Wright 191e816a7e4SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 192e816a7e4SJames Wright 193e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 194e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 195c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup)); 196c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup)); 197c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 198c864c5abSJames Wright } 199c864c5abSJames Wright 200c864c5abSJames Wright /** 201c864c5abSJames Wright * @brief Get number of components of quadrature data for boundary of domain 202c864c5abSJames Wright * 203c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 204c864c5abSJames Wright * @param[out] q_data_size Number of components of quadrature data 205c864c5abSJames Wright */ 206c864c5abSJames Wright PetscErrorCode QDataBoundaryGetNumComponents(DM dm, CeedInt *q_data_size) { 207c864c5abSJames Wright PetscInt dim; 208c864c5abSJames Wright 209c864c5abSJames Wright PetscFunctionBeginUser; 210c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 211c864c5abSJames Wright switch (dim) { 212c864c5abSJames Wright case 2: 213c864c5abSJames Wright *q_data_size = 3; 214c864c5abSJames Wright break; 215c864c5abSJames Wright case 3: 216c864c5abSJames Wright *q_data_size = 10; 217c864c5abSJames Wright break; 218c864c5abSJames Wright default: 219c864c5abSJames Wright SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "QDataBoundary not valid for DM of dimension %" PetscInt_FMT, dim); 220c864c5abSJames Wright break; 221c864c5abSJames Wright } 222c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 223c864c5abSJames Wright } 224c864c5abSJames Wright 225c864c5abSJames Wright /** 226c864c5abSJames Wright * @brief Create quadrature data for boundary of domain 227c864c5abSJames Wright * 228c864c5abSJames Wright * @param[in] ceed Ceed object quadrature data will be used with 229c864c5abSJames Wright * @param[in] dm DM where quadrature data would be used 230c864c5abSJames Wright * @param[in] domain_label DMLabel that quadrature data would be used one 231c864c5abSJames Wright * @param[in] label_value Value of label 232c864c5abSJames Wright * @param[in] elem_restr_x CeedElemRestriction of the coordinates (must match `domain_label` and `label_value` selections) 233c864c5abSJames Wright * @param[in] basis_x CeedBasis of the coordinates 234c864c5abSJames Wright * @param[in] x_coord CeedVector of the coordinates 235c864c5abSJames Wright * @param[out] elem_restr_qd CeedElemRestriction of the quadrature data 236c864c5abSJames Wright * @param[out] q_data CeedVector of the quadrature data 2374aea4664SJames Wright * @param[out] q_data_size Number of components of quadrature data 238c864c5abSJames Wright */ 239c864c5abSJames Wright PetscErrorCode QDataBoundaryGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedElemRestriction elem_restr_x, CeedBasis basis_x, 240c864c5abSJames Wright CeedVector x_coord, CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 24187d3884fSJeremy L Thompson CeedQFunction qf_setup_sur = NULL; 242c864c5abSJames Wright CeedOperator op_setup_sur; 243e816a7e4SJames Wright CeedVector q_data_created; 244e816a7e4SJames Wright CeedElemRestriction elem_restr_qd_created; 245c864c5abSJames Wright CeedInt num_comp_x; 246c864c5abSJames Wright PetscInt dim, height = 1; 247c864c5abSJames Wright 248c864c5abSJames Wright PetscFunctionBeginUser; 249c864c5abSJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, q_data_size)); 250c864c5abSJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x, &num_comp_x)); 251c864c5abSJames Wright PetscCall(DMGetDimension(dm, &dim)); 252c864c5abSJames Wright switch (dim) { 253c864c5abSJames Wright case 2: 254c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundary2d, SetupBoundary2d_loc, &qf_setup_sur)); 255c864c5abSJames Wright break; 256c864c5abSJames Wright case 3: 257c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundary, SetupBoundary_loc, &qf_setup_sur)); 258c864c5abSJames Wright break; 259c864c5abSJames Wright } 260c864c5abSJames Wright 261c864c5abSJames Wright // -- Create QFunction for quadrature data 262c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(qf_setup_sur, 0)); 263c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx", num_comp_x * (dim - height), CEED_EVAL_GRAD)); 264c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "weight", 1, CEED_EVAL_WEIGHT)); 265c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup_sur, "surface qdata", *q_data_size, CEED_EVAL_NONE)); 266c864c5abSJames Wright 267e816a7e4SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, *q_data_size, &elem_restr_qd_created)); 268e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 269c864c5abSJames Wright 270c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup_sur, NULL, NULL, &op_setup_sur)); 271c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE)); 272c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE)); 273e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "surface qdata", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 274c864c5abSJames Wright 275e816a7e4SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup_sur, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 276c864c5abSJames Wright 277e816a7e4SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 278e816a7e4SJames Wright 279e816a7e4SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 280e816a7e4SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 281c864c5abSJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup_sur)); 282c864c5abSJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup_sur)); 283c864c5abSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 284c864c5abSJames Wright } 2858c85b835SJames Wright 2868c85b835SJames Wright /** 2878c85b835SJames Wright * @brief Get number of components of quadrature data for boundary of domain 2888c85b835SJames Wright * 2898c85b835SJames Wright * @param[in] dm DM where quadrature data would be used 2908c85b835SJames Wright * @param[out] q_data_size Number of components of quadrature data 2918c85b835SJames Wright */ 2928c85b835SJames Wright PetscErrorCode QDataBoundaryGradientGetNumComponents(DM dm, CeedInt *q_data_size) { 2938c85b835SJames Wright PetscInt dim; 2948c85b835SJames Wright 2958c85b835SJames Wright PetscFunctionBeginUser; 2968c85b835SJames Wright PetscCall(DMGetDimension(dm, &dim)); 2978c85b835SJames Wright switch (dim) { 2988c85b835SJames Wright case 3: 2998c85b835SJames Wright *q_data_size = 13; 3008c85b835SJames Wright break; 3018c85b835SJames Wright default: 3028c85b835SJames Wright SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "QDataBoundary not valid for DM of dimension %" PetscInt_FMT, dim); 3038c85b835SJames Wright break; 3048c85b835SJames Wright } 3058c85b835SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 3068c85b835SJames Wright } 3078c85b835SJames Wright 3088c85b835SJames Wright /** 3098c85b835SJames Wright @brief Compute `CeedOperator` surface gradient QData 3108c85b835SJames Wright 3118c85b835SJames Wright Collective across MPI processes. 3128c85b835SJames Wright 3138c85b835SJames Wright @param[in] ceed `Ceed` object 3148c85b835SJames Wright @param[in] dm `DMPlex` grid 3158c85b835SJames Wright @param[in] domain_label `DMLabel` for surface 3168c85b835SJames Wright @param[in] label_value `DMPlex` label value for surface 3178c85b835SJames Wright @param[in] x_coord `CeedVector` for coordinates 31800dbc7b1SJames Wright @param[out] elem_restr_qd `CeedElemRestriction` for QData 3198c85b835SJames Wright @param[out] q_data `CeedVector` holding QData 3208c85b835SJames Wright @param[out] q_data_size Number of QData components per quadrature point 3218c85b835SJames Wright **/ 3228c85b835SJames Wright PetscErrorCode QDataBoundaryGradientGet(Ceed ceed, DM dm, DMLabel domain_label, PetscInt label_value, CeedVector x_coord, 32300dbc7b1SJames Wright CeedElemRestriction *elem_restr_qd, CeedVector *q_data, CeedInt *q_data_size) { 3248c85b835SJames Wright PetscInt dim; 3258c85b835SJames Wright const PetscInt height_cell = 0, height_face = 1; 3268c85b835SJames Wright CeedInt num_comp_x; 327*f17df9b6SJames Wright CeedElemRestriction elem_restr_x_cell, elem_restr_x_face, elem_restr_qd_created; 328*f17df9b6SJames Wright CeedVector q_data_created; 3298c85b835SJames Wright CeedBasis basis_x_cell_to_face, basis_x_face; 3308c85b835SJames Wright CeedQFunction qf_setup_sur; 3318c85b835SJames Wright CeedOperator op_setup_sur; 3328c85b835SJames Wright 3338c85b835SJames Wright PetscFunctionBeginUser; 3348c85b835SJames Wright PetscCall(CreateCoordinateBasisFromPlex(ceed, dm, domain_label, label_value, height_face, &basis_x_face)); 3358c85b835SJames Wright PetscCall(DMPlexCeedBasisCellToFaceCoordinateCreate(ceed, dm, domain_label, label_value, label_value, &basis_x_cell_to_face)); 33600dbc7b1SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height_cell, &elem_restr_x_cell)); 3378c85b835SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height_face, &elem_restr_x_face)); 3388c85b835SJames Wright 3398c85b835SJames Wright PetscCall(QDataBoundaryGradientGetNumComponents(dm, q_data_size)); 340*f17df9b6SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height_face, *q_data_size, &elem_restr_qd_created)); 341*f17df9b6SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_qd_created, &q_data_created, NULL)); 3428c85b835SJames Wright 3438c85b835SJames Wright PetscCall(DMGetDimension(dm, &dim)); 3448c85b835SJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(elem_restr_x_face, &num_comp_x)); 3458c85b835SJames Wright 3468c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, SetupBoundaryGradient, SetupBoundaryGradient_loc, &qf_setup_sur)); 3478c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx/dX cell", num_comp_x * (dim - height_cell), CEED_EVAL_GRAD)); 3488c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "dx/dX face", num_comp_x * (dim - height_face), CEED_EVAL_GRAD)); 3498c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_setup_sur, "weight", 1, CEED_EVAL_WEIGHT)); 3508c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_setup_sur, "q data", *q_data_size, CEED_EVAL_NONE)); 3518c85b835SJames Wright 3528c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_setup_sur, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup_sur)); 35300dbc7b1SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx/dX cell", elem_restr_x_cell, basis_x_cell_to_face, CEED_VECTOR_ACTIVE)); 3548c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "dx/dX face", elem_restr_x_face, basis_x_face, CEED_VECTOR_ACTIVE)); 3558c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "weight", CEED_ELEMRESTRICTION_NONE, basis_x_face, CEED_VECTOR_NONE)); 356*f17df9b6SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_setup_sur, "q data", elem_restr_qd_created, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 3578c85b835SJames Wright 358*f17df9b6SJames Wright PetscCallCeed(ceed, CeedOperatorApply(op_setup_sur, x_coord, q_data_created, CEED_REQUEST_IMMEDIATE)); 359*f17df9b6SJames Wright 360*f17df9b6SJames Wright PetscCall(QDataGetStored(q_data_created, elem_restr_qd_created, q_data, elem_restr_qd)); 3618c85b835SJames Wright 3628c85b835SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_setup_sur)); 3638c85b835SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_setup_sur)); 364*f17df9b6SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data_created)); 365*f17df9b6SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd_created)); 3668c85b835SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x_face)); 36700dbc7b1SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x_cell)); 3688c85b835SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x_face)); 3698c85b835SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x_cell_to_face)); 3708c85b835SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 3718c85b835SJames Wright } 372