1*c38c977aSJames Wright // Copyright (c) 2017-2023, Lawrence Livermore National Security, LLC and other CEED contributors. 2*c38c977aSJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3*c38c977aSJames Wright // 4*c38c977aSJames Wright // SPDX-License-Identifier: BSD-2-Clause 5*c38c977aSJames Wright // 6*c38c977aSJames Wright // This file is part of CEED: http://github.com/ceed 7*c38c977aSJames Wright 8*c38c977aSJames Wright #include "../qfunctions/grid_anisotropy_tensor.h" 9*c38c977aSJames Wright 10*c38c977aSJames Wright #include <petscdmplex.h> 11*c38c977aSJames Wright 12*c38c977aSJames Wright #include "../navierstokes.h" 13*c38c977aSJames Wright 14*c38c977aSJames Wright PetscErrorCode GridAnisotropyTensorProjectionSetupApply(Ceed ceed, User user, CeedData ceed_data, CeedElemRestriction *elem_restr_grid_aniso, 15*c38c977aSJames Wright CeedVector *grid_aniso_vector) { 16*c38c977aSJames Wright NodalProjectionData grid_aniso_proj; 17*c38c977aSJames Wright OperatorApplyContext mass_matop_ctx, l2_rhs_ctx; 18*c38c977aSJames Wright CeedOperator op_rhs_assemble, op_mass; 19*c38c977aSJames Wright CeedQFunction qf_rhs_assemble, qf_mass; 20*c38c977aSJames Wright CeedBasis basis_grid_aniso; 21*c38c977aSJames Wright CeedVector rhs_ceed; 22*c38c977aSJames Wright PetscInt dim, q_data_size, num_qpts_1d, num_nodes_1d; 23*c38c977aSJames Wright MPI_Comm comm = PetscObjectComm((PetscObject)user->dm); 24*c38c977aSJames Wright KSP ksp; 25*c38c977aSJames Wright 26*c38c977aSJames Wright PetscFunctionBeginUser; 27*c38c977aSJames Wright PetscCall(PetscNew(&grid_aniso_proj)); 28*c38c977aSJames Wright 29*c38c977aSJames Wright // -- Create DM for Anisotropic tensor L^2 projection 30*c38c977aSJames Wright grid_aniso_proj->num_comp = 7; 31*c38c977aSJames Wright PetscCall(DMClone(user->dm, &grid_aniso_proj->dm)); 32*c38c977aSJames Wright PetscCall(DMGetDimension(grid_aniso_proj->dm, &dim)); 33*c38c977aSJames Wright PetscCall(PetscObjectSetName((PetscObject)grid_aniso_proj->dm, "Grid Anisotropy Tensor Projection")); 34*c38c977aSJames Wright 35*c38c977aSJames Wright { // -- Setup DM 36*c38c977aSJames Wright PetscFE fe; 37*c38c977aSJames Wright PetscSection section; 38*c38c977aSJames Wright PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, grid_aniso_proj->num_comp, PETSC_FALSE, user->app_ctx->degree, PETSC_DECIDE, &fe)); 39*c38c977aSJames Wright PetscCall(PetscObjectSetName((PetscObject)fe, "Grid Anisotropy Tensor Projection")); 40*c38c977aSJames Wright PetscCall(DMAddField(grid_aniso_proj->dm, NULL, (PetscObject)fe)); 41*c38c977aSJames Wright PetscCall(DMCreateDS(grid_aniso_proj->dm)); 42*c38c977aSJames Wright PetscCall(DMPlexSetClosurePermutationTensor(grid_aniso_proj->dm, PETSC_DETERMINE, NULL)); 43*c38c977aSJames Wright 44*c38c977aSJames Wright PetscCall(DMGetLocalSection(grid_aniso_proj->dm, §ion)); 45*c38c977aSJames Wright PetscCall(PetscSectionSetFieldName(section, 0, "")); 46*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 0, "KMGridAnisotropyTensorXX")); 47*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 1, "KMGridAnisotropyTensorYY")); 48*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 2, "KMGridAnisotropyTensorZZ")); 49*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 3, "KMGridAnisotropyTensorYZ")); 50*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 4, "KMGridAnisotropyTensorXZ")); 51*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 5, "KMGridAnisotropyTensorXY")); 52*c38c977aSJames Wright PetscCall(PetscSectionSetComponentName(section, 0, 6, "GridAnisotropyTensorFrobNorm")); 53*c38c977aSJames Wright 54*c38c977aSJames Wright PetscCall(PetscFEDestroy(&fe)); 55*c38c977aSJames Wright } 56*c38c977aSJames Wright 57*c38c977aSJames Wright // -- Get Pre-requisite things 58*c38c977aSJames Wright CeedBasisGetNumQuadraturePoints1D(ceed_data->basis_q, &num_qpts_1d); 59*c38c977aSJames Wright CeedBasisGetNumNodes1D(ceed_data->basis_q, &num_nodes_1d); 60*c38c977aSJames Wright CeedElemRestrictionGetNumComponents(ceed_data->elem_restr_qd_i, &q_data_size); 61*c38c977aSJames Wright 62*c38c977aSJames Wright PetscCall(GetRestrictionForDomain(ceed, grid_aniso_proj->dm, 0, 0, 0, num_qpts_1d, grid_aniso_proj->num_comp, elem_restr_grid_aniso, NULL, NULL)); 63*c38c977aSJames Wright CeedBasisCreateTensorH1Lagrange(ceed, dim, grid_aniso_proj->num_comp, num_nodes_1d, num_qpts_1d, CEED_GAUSS, &basis_grid_aniso); 64*c38c977aSJames Wright 65*c38c977aSJames Wright // -- Build RHS operator 66*c38c977aSJames Wright CeedQFunctionCreateInterior(ceed, 1, AnisotropyTensorProjection, AnisotropyTensorProjection_loc, &qf_rhs_assemble); 67*c38c977aSJames Wright CeedQFunctionAddInput(qf_rhs_assemble, "qdata", q_data_size, CEED_EVAL_NONE); 68*c38c977aSJames Wright CeedQFunctionAddOutput(qf_rhs_assemble, "v", grid_aniso_proj->num_comp, CEED_EVAL_INTERP); 69*c38c977aSJames Wright 70*c38c977aSJames Wright CeedOperatorCreate(ceed, qf_rhs_assemble, NULL, NULL, &op_rhs_assemble); 71*c38c977aSJames Wright CeedOperatorSetField(op_rhs_assemble, "qdata", ceed_data->elem_restr_qd_i, CEED_BASIS_COLLOCATED, ceed_data->q_data); 72*c38c977aSJames Wright CeedOperatorSetField(op_rhs_assemble, "v", *elem_restr_grid_aniso, basis_grid_aniso, CEED_VECTOR_ACTIVE); 73*c38c977aSJames Wright 74*c38c977aSJames Wright CeedElemRestrictionCreateVector(*elem_restr_grid_aniso, &rhs_ceed, NULL); 75*c38c977aSJames Wright 76*c38c977aSJames Wright PetscCall(OperatorApplyContextCreate(user->dm, grid_aniso_proj->dm, ceed, op_rhs_assemble, ceed_data->q_data, rhs_ceed, NULL, NULL, &l2_rhs_ctx)); 77*c38c977aSJames Wright 78*c38c977aSJames Wright // -- Build Mass Operator 79*c38c977aSJames Wright PetscCall(CreateMassQFunction(ceed, grid_aniso_proj->num_comp, q_data_size, &qf_mass)); 80*c38c977aSJames Wright CeedOperatorCreate(ceed, qf_mass, NULL, NULL, &op_mass); 81*c38c977aSJames Wright CeedOperatorSetField(op_mass, "u", *elem_restr_grid_aniso, basis_grid_aniso, CEED_VECTOR_ACTIVE); 82*c38c977aSJames Wright CeedOperatorSetField(op_mass, "qdata", ceed_data->elem_restr_qd_i, CEED_BASIS_COLLOCATED, ceed_data->q_data); 83*c38c977aSJames Wright CeedOperatorSetField(op_mass, "v", *elem_restr_grid_aniso, basis_grid_aniso, CEED_VECTOR_ACTIVE); 84*c38c977aSJames Wright 85*c38c977aSJames Wright { // -- Setup KSP for L^2 projection 86*c38c977aSJames Wright PetscInt l_size, g_size; 87*c38c977aSJames Wright Mat mat_mass; 88*c38c977aSJames Wright VecType vec_type; 89*c38c977aSJames Wright Vec M_inv; 90*c38c977aSJames Wright CeedVector mass_output; 91*c38c977aSJames Wright 92*c38c977aSJames Wright PetscCall(DMGetGlobalVector(grid_aniso_proj->dm, &M_inv)); 93*c38c977aSJames Wright PetscCall(VecGetLocalSize(M_inv, &l_size)); 94*c38c977aSJames Wright PetscCall(VecGetSize(M_inv, &g_size)); 95*c38c977aSJames Wright PetscCall(VecGetType(M_inv, &vec_type)); 96*c38c977aSJames Wright PetscCall(DMRestoreGlobalVector(grid_aniso_proj->dm, &M_inv)); 97*c38c977aSJames Wright 98*c38c977aSJames Wright CeedElemRestrictionCreateVector(*elem_restr_grid_aniso, &mass_output, NULL); 99*c38c977aSJames Wright PetscCall( 100*c38c977aSJames Wright OperatorApplyContextCreate(grid_aniso_proj->dm, grid_aniso_proj->dm, ceed, op_mass, rhs_ceed, mass_output, NULL, NULL, &mass_matop_ctx)); 101*c38c977aSJames Wright CeedVectorDestroy(&mass_output); 102*c38c977aSJames Wright 103*c38c977aSJames Wright PetscCall(MatCreateShell(comm, l_size, l_size, g_size, g_size, mass_matop_ctx, &mat_mass)); 104*c38c977aSJames Wright PetscCall(MatShellSetContextDestroy(mat_mass, (PetscErrorCode(*)(void *))OperatorApplyContextDestroy)); 105*c38c977aSJames Wright PetscCall(MatShellSetOperation(mat_mass, MATOP_MULT, (void (*)(void))MatMult_Ceed)); 106*c38c977aSJames Wright PetscCall(MatShellSetOperation(mat_mass, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiag_Ceed)); 107*c38c977aSJames Wright PetscCall(MatShellSetVecType(mat_mass, vec_type)); 108*c38c977aSJames Wright 109*c38c977aSJames Wright PetscCall(KSPCreate(comm, &ksp)); 110*c38c977aSJames Wright PetscCall(KSPSetOptionsPrefix(ksp, "grid_anisotropy_tensor_projection_")); 111*c38c977aSJames Wright { 112*c38c977aSJames Wright PC pc; 113*c38c977aSJames Wright PetscCall(KSPGetPC(ksp, &pc)); 114*c38c977aSJames Wright PetscCall(PCSetType(pc, PCJACOBI)); 115*c38c977aSJames Wright PetscCall(PCJacobiSetType(pc, PC_JACOBI_DIAGONAL)); 116*c38c977aSJames Wright PetscCall(KSPSetType(ksp, KSPCG)); 117*c38c977aSJames Wright PetscCall(KSPSetNormType(ksp, KSP_NORM_NATURAL)); 118*c38c977aSJames Wright PetscCall(KSPSetTolerances(ksp, 1e-10, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 119*c38c977aSJames Wright } 120*c38c977aSJames Wright PetscCall(KSPSetOperators(ksp, mat_mass, mat_mass)); 121*c38c977aSJames Wright PetscCall(KSPSetFromOptions(ksp)); 122*c38c977aSJames Wright } 123*c38c977aSJames Wright 124*c38c977aSJames Wright { // -- Project anisotropy data and store in CeedVector 125*c38c977aSJames Wright Vec Grid_Anisotropy, grid_anisotropy_loc; 126*c38c977aSJames Wright PetscMemType mem_type; 127*c38c977aSJames Wright 128*c38c977aSJames Wright // Get L^2 Projection RHS 129*c38c977aSJames Wright PetscCall(DMGetGlobalVector(grid_aniso_proj->dm, &Grid_Anisotropy)); 130*c38c977aSJames Wright PetscCall(DMGetLocalVector(grid_aniso_proj->dm, &grid_anisotropy_loc)); 131*c38c977aSJames Wright 132*c38c977aSJames Wright PetscCall(VecP2C(grid_anisotropy_loc, &mem_type, l2_rhs_ctx->y_ceed)); 133*c38c977aSJames Wright CeedOperatorApply(l2_rhs_ctx->op, CEED_VECTOR_NONE, l2_rhs_ctx->y_ceed, CEED_REQUEST_IMMEDIATE); 134*c38c977aSJames Wright PetscCall(VecC2P(l2_rhs_ctx->y_ceed, mem_type, grid_anisotropy_loc)); 135*c38c977aSJames Wright PetscCall(DMLocalToGlobal(l2_rhs_ctx->dm_y, grid_anisotropy_loc, ADD_VALUES, Grid_Anisotropy)); 136*c38c977aSJames Wright 137*c38c977aSJames Wright // Solve projection problem 138*c38c977aSJames Wright PetscCall(KSPSolve(ksp, Grid_Anisotropy, Grid_Anisotropy)); 139*c38c977aSJames Wright 140*c38c977aSJames Wright // Copy anisotropy tensor data to CeedVector 141*c38c977aSJames Wright CeedElemRestrictionCreateVector(*elem_restr_grid_aniso, grid_aniso_vector, NULL); 142*c38c977aSJames Wright PetscCall(DMGlobalToLocal(grid_aniso_proj->dm, Grid_Anisotropy, INSERT_VALUES, grid_anisotropy_loc)); 143*c38c977aSJames Wright PetscCall(VecCopyP2C(grid_anisotropy_loc, *grid_aniso_vector)); 144*c38c977aSJames Wright PetscCall(DMRestoreLocalVector(grid_aniso_proj->dm, &grid_anisotropy_loc)); 145*c38c977aSJames Wright PetscCall(DMRestoreGlobalVector(grid_aniso_proj->dm, &Grid_Anisotropy)); 146*c38c977aSJames Wright } 147*c38c977aSJames Wright 148*c38c977aSJames Wright // -- Cleanup 149*c38c977aSJames Wright PetscCall(NodalProjectionDataDestroy(grid_aniso_proj)); 150*c38c977aSJames Wright PetscCall(OperatorApplyContextDestroy(l2_rhs_ctx)); 151*c38c977aSJames Wright CeedVectorDestroy(&rhs_ceed); 152*c38c977aSJames Wright CeedQFunctionDestroy(&qf_rhs_assemble); 153*c38c977aSJames Wright CeedQFunctionDestroy(&qf_mass); 154*c38c977aSJames Wright CeedBasisDestroy(&basis_grid_aniso); 155*c38c977aSJames Wright CeedOperatorDestroy(&op_rhs_assemble); 156*c38c977aSJames Wright CeedOperatorDestroy(&op_mass); 157*c38c977aSJames Wright PetscCall(KSPDestroy(&ksp)); 158*c38c977aSJames Wright PetscFunctionReturn(0); 159*c38c977aSJames Wright } 160