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