1*25125139SJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2*25125139SJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3*25125139SJames Wright 4*25125139SJames Wright #include "../qfunctions/monitor_totalkineticenergy.h" 5*25125139SJames Wright #include <navierstokes.h> 6*25125139SJames Wright #include <time.h> 7*25125139SJames Wright 8*25125139SJames Wright typedef struct { 9*25125139SJames Wright OperatorApplyContext op_monitor_ctx; 10*25125139SJames Wright Vec values; 11*25125139SJames Wright PetscScalar *sum_values; 12*25125139SJames Wright PetscScalar volume; 13*25125139SJames Wright PetscInt num_comps; 14*25125139SJames Wright PetscBool is_header_written; 15*25125139SJames Wright } *MonitorDissipation; 16*25125139SJames Wright 17*25125139SJames Wright PetscErrorCode MonitorDissipationDestroy(void **ctx) { 18*25125139SJames Wright MonitorDissipation monitor_ctx = *(MonitorDissipation *)ctx; 19*25125139SJames Wright 20*25125139SJames Wright PetscFunctionBeginUser; 21*25125139SJames Wright PetscCall(OperatorApplyContextDestroy(monitor_ctx->op_monitor_ctx)); 22*25125139SJames Wright PetscCall(VecDestroy(&monitor_ctx->values)); 23*25125139SJames Wright PetscCall(PetscFree(monitor_ctx->sum_values)); 24*25125139SJames Wright PetscCall(PetscFree(monitor_ctx)); 25*25125139SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 26*25125139SJames Wright } 27*25125139SJames Wright 28*25125139SJames Wright /** @brief Create CeedElemRestriction for collocated data in component-major order. 29*25125139SJames Wright a. Sets the strides of the restriction to component-major order 30*25125139SJames Wright Number of quadrature points is used from the CeedBasis, and number of elements is used from the CeedElemRestriction. 31*25125139SJames Wright */ 32*25125139SJames Wright static PetscErrorCode CreateElemRestrColloc_CompMajor(Ceed ceed, CeedInt num_comp, CeedBasis basis, CeedElemRestriction elem_restr_base, 33*25125139SJames Wright CeedElemRestriction *elem_restr_collocated) { 34*25125139SJames Wright CeedInt num_elem_qpts, loc_num_elem; 35*25125139SJames Wright 36*25125139SJames Wright PetscFunctionBeginUser; 37*25125139SJames Wright PetscCallCeed(ceed, CeedBasisGetNumQuadraturePoints(basis, &num_elem_qpts)); 38*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumElements(elem_restr_base, &loc_num_elem)); 39*25125139SJames Wright 40*25125139SJames Wright const CeedInt strides[] = {num_comp, 1, num_elem_qpts * num_comp}; 41*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateStrided(ceed, loc_num_elem, num_elem_qpts, num_comp, num_comp * loc_num_elem * num_elem_qpts, strides, 42*25125139SJames Wright elem_restr_collocated)); 43*25125139SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 44*25125139SJames Wright } 45*25125139SJames Wright 46*25125139SJames Wright PetscErrorCode SetupMontiorTotalKineticEnergy(TS ts, PetscViewerAndFormat *ctx) { 47*25125139SJames Wright Honee honee; 48*25125139SJames Wright Ceed ceed; 49*25125139SJames Wright CeedQFunction qf_monitor; 50*25125139SJames Wright CeedOperator op_monitor; 51*25125139SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_totalke, elem_restr_q; 52*25125139SJames Wright CeedBasis basis_q; 53*25125139SJames Wright CeedVector q_data; 54*25125139SJames Wright CeedInt num_comp_q, q_data_size; 55*25125139SJames Wright DMLabel domain_label = NULL; 56*25125139SJames Wright PetscInt label_value = 0, num_comp_totalke = 5, dim; 57*25125139SJames Wright MonitorDissipation monitor_ctx; 58*25125139SJames Wright CeedQFunctionContext newt_qfctx; 59*25125139SJames Wright PetscBool is_ascii; 60*25125139SJames Wright 61*25125139SJames Wright PetscFunctionBeginUser; 62*25125139SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)ctx->viewer, PETSCVIEWERASCII, &is_ascii)); 63*25125139SJames Wright PetscCheck(is_ascii, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only supports ASCII viewers"); 64*25125139SJames Wright PetscCall(TSGetApplicationContext(ts, &honee)); 65*25125139SJames Wright PetscCall(DMGetDimension(honee->dm, &dim)); 66*25125139SJames Wright ceed = honee->ceed; 67*25125139SJames Wright 68*25125139SJames Wright PetscCall(PetscNew(&monitor_ctx)); 69*25125139SJames Wright PetscCall(HoneeCalculateDomainSize(honee, &monitor_ctx->volume)); 70*25125139SJames Wright 71*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(honee->elem_restr_q, &num_comp_q)); 72*25125139SJames Wright PetscCall(QDataGet(ceed, honee->dm, domain_label, label_value, honee->elem_restr_x, honee->basis_x, honee->x_coord, &elem_restr_qd, &q_data, 73*25125139SJames Wright &q_data_size)); 74*25125139SJames Wright 75*25125139SJames Wright { // Get restriction and basis from the RHS function 76*25125139SJames Wright CeedOperator *sub_ops; 77*25125139SJames Wright CeedOperatorField op_field; 78*25125139SJames Wright PetscInt sub_op_index = 0; // will be 0 for the volume op 79*25125139SJames Wright 80*25125139SJames Wright PetscCallCeed(ceed, CeedCompositeOperatorGetSubList(honee->op_rhs_ctx->op, &sub_ops)); 81*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_ops[sub_op_index], "q", &op_field)); 82*25125139SJames Wright 83*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_q, &basis_q, NULL)); 84*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorGetContext(sub_ops[sub_op_index], &newt_qfctx)); 85*25125139SJames Wright } 86*25125139SJames Wright PetscCall(CreateElemRestrColloc_CompMajor(ceed, num_comp_totalke, basis_q, elem_restr_q, &elem_restr_totalke)); 87*25125139SJames Wright 88*25125139SJames Wright switch (honee->phys->state_var) { 89*25125139SJames Wright case STATEVAR_PRIMITIVE: 90*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Prim, MonitorTotalKineticEnergy_Prim_loc, &qf_monitor)); 91*25125139SJames Wright break; 92*25125139SJames Wright case STATEVAR_CONSERVATIVE: 93*25125139SJames Wright PetscCallCeed(ceed, 94*25125139SJames Wright CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Conserv, MonitorTotalKineticEnergy_Conserv_loc, &qf_monitor)); 95*25125139SJames Wright break; 96*25125139SJames Wright case STATEVAR_ENTROPY: 97*25125139SJames Wright PetscCallCeed(ceed, 98*25125139SJames Wright CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Entropy, MonitorTotalKineticEnergy_Entropy_loc, &qf_monitor)); 99*25125139SJames Wright break; 100*25125139SJames Wright } 101*25125139SJames Wright 102*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(qf_monitor, newt_qfctx)); 103*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q", num_comp_q, CEED_EVAL_INTERP)); 104*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "Grad_q", num_comp_q * dim, CEED_EVAL_GRAD)); 105*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q_data", q_data_size, CEED_EVAL_NONE)); 106*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_monitor, "v", num_comp_totalke, CEED_EVAL_NONE)); 107*25125139SJames Wright 108*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_monitor, NULL, NULL, &op_monitor)); 109*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 110*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 111*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q_data", elem_restr_qd, CEED_BASIS_NONE, q_data)); 112*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "v", elem_restr_totalke, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 113*25125139SJames Wright 114*25125139SJames Wright PetscCall(OperatorApplyContextCreate(honee->dm, NULL, ceed, op_monitor, NULL, NULL, NULL, NULL, &monitor_ctx->op_monitor_ctx)); 115*25125139SJames Wright 116*25125139SJames Wright PetscCall(CeedOperatorCreateLocalVecs(op_monitor, DMReturnVecType(honee->dm), PETSC_COMM_SELF, NULL, &monitor_ctx->values)); 117*25125139SJames Wright PetscCall(VecSetBlockSize(monitor_ctx->values, num_comp_totalke)); 118*25125139SJames Wright monitor_ctx->num_comps = num_comp_totalke; 119*25125139SJames Wright PetscCall(PetscMalloc1(num_comp_totalke, &monitor_ctx->sum_values)); 120*25125139SJames Wright 121*25125139SJames Wright ctx->data = monitor_ctx; 122*25125139SJames Wright ctx->data_destroy = MonitorDissipationDestroy; 123*25125139SJames Wright 124*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionContextDestroy(&newt_qfctx)); 125*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 126*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 127*25125139SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_totalke)); 128*25125139SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 129*25125139SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 130*25125139SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_monitor)); 131*25125139SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_monitor)); 132*25125139SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 133*25125139SJames Wright } 134*25125139SJames Wright 135*25125139SJames Wright PetscErrorCode TSMonitor_TotalKineticEnergy(TS ts, PetscInt step, PetscReal solution_time, Vec Q, PetscViewerAndFormat *ctx) { 136*25125139SJames Wright MonitorDissipation monitor_ctx = (MonitorDissipation)ctx->data; 137*25125139SJames Wright Honee honee; 138*25125139SJames Wright MPI_Comm comm; 139*25125139SJames Wright PetscMPIInt rank; 140*25125139SJames Wright TSConvergedReason reason; 141*25125139SJames Wright static const char *field_names[] = {"TotalKineticEnergy", "StrainDissipation", "DivergenceDissipation", "VolumeExpansion", "MuVorticity2"}; 142*25125139SJames Wright 143*25125139SJames Wright PetscFunctionBeginUser; 144*25125139SJames Wright PetscCall(TSGetConvergedReason(ts, &reason)); 145*25125139SJames Wright if (!(step % ctx->view_interval == 0 || reason != TS_CONVERGED_ITERATING)) PetscFunctionReturn(PETSC_SUCCESS); 146*25125139SJames Wright PetscCall(TSGetApplicationContext(ts, &honee)); 147*25125139SJames Wright PetscCall(PetscObjectGetComm((PetscObject)ts, &comm)); 148*25125139SJames Wright PetscCallMPI(MPI_Comm_rank(comm, &rank)); 149*25125139SJames Wright 150*25125139SJames Wright PetscCall(UpdateBoundaryValues(honee, honee->Q_loc, solution_time)); 151*25125139SJames Wright PetscCall(DMGlobalToLocal(honee->dm, Q, INSERT_VALUES, honee->Q_loc)); 152*25125139SJames Wright 153*25125139SJames Wright PetscCall(ApplyCeedOperatorLocalToLocal(honee->Q_loc, monitor_ctx->values, monitor_ctx->op_monitor_ctx)); 154*25125139SJames Wright 155*25125139SJames Wright for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) { 156*25125139SJames Wright PetscCall(VecStrideSum(monitor_ctx->values, i, &monitor_ctx->sum_values[i])); 157*25125139SJames Wright } 158*25125139SJames Wright 159*25125139SJames Wright if (rank == 0) PetscCallMPI(MPI_Reduce(MPI_IN_PLACE, monitor_ctx->sum_values, monitor_ctx->num_comps, MPIU_SCALAR, MPI_SUM, 0, comm)); 160*25125139SJames Wright else PetscCallMPI(MPI_Reduce(monitor_ctx->sum_values, monitor_ctx->sum_values, monitor_ctx->num_comps, MPIU_SCALAR, MPI_SUM, 0, comm)); 161*25125139SJames Wright 162*25125139SJames Wright if (rank == 0) 163*25125139SJames Wright for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) monitor_ctx->sum_values[i] /= monitor_ctx->volume; 164*25125139SJames Wright 165*25125139SJames Wright if (ctx->format == PETSC_VIEWER_ASCII_CSV) { 166*25125139SJames Wright if (!monitor_ctx->is_header_written) { 167*25125139SJames Wright char buf[PETSC_MAX_PATH_LEN]; 168*25125139SJames Wright const char *buf_const; 169*25125139SJames Wright time_t t = time(NULL); 170*25125139SJames Wright 171*25125139SJames Wright PetscCall(PetscGetVersion(buf, sizeof(buf))); 172*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_version: %s\n", buf)); 173*25125139SJames Wright PetscCall(PetscGetPetscDir(&buf_const)); 174*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_directory: %s\n", buf_const)); 175*25125139SJames Wright PetscCall(PetscGetArchType(buf, sizeof(buf))); 176*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_arch: %s\n", buf)); 177*25125139SJames Wright if (strftime(buf, sizeof(buf), "%FT%T%z", localtime(&t)) == 0) SETERRQ(comm, PETSC_ERR_SYS, "strftime() call failed"); 178*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date: %s\n", buf)); 179*25125139SJames Wright if (strftime(buf, sizeof(buf), "%Z", localtime(&t)) == 0) SETERRQ(comm, PETSC_ERR_SYS, "strftime() call failed"); 180*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date_timezone: %s\n", buf)); 181*25125139SJames Wright PetscCall(PetscGetUserName(buf, sizeof(buf))); 182*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# username: %s\n", buf)); 183*25125139SJames Wright PetscCall(PetscGetHostName(buf, sizeof(buf))); 184*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# hostname: %s\n", buf)); 185*25125139SJames Wright PetscCall(PetscGetWorkingDirectory(buf, sizeof(buf))); 186*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# working_directory: %s\n", buf)); 187*25125139SJames Wright 188*25125139SJames Wright PetscCall(PetscViewerFileGetName(ctx->viewer, &buf_const)); 189*25125139SJames Wright PetscCall(PetscGetFullPath(buf_const, buf, sizeof(buf))); 190*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# original_file_path: %s\n", buf)); 191*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "#\n")); 192*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "step,time,")); 193*25125139SJames Wright for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) { 194*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%s", field_names[i])); 195*25125139SJames Wright if (i < monitor_ctx->num_comps - 1) PetscCall(PetscViewerASCIIPrintf(ctx->viewer, ",")); 196*25125139SJames Wright } 197*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n")); 198*25125139SJames Wright monitor_ctx->is_header_written = PETSC_TRUE; 199*25125139SJames Wright } 200*25125139SJames Wright 201*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%" PetscInt_FMT ",%0.17e,", step, solution_time)); 202*25125139SJames Wright for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) { 203*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%0.17e", monitor_ctx->sum_values[i])); 204*25125139SJames Wright if (i < monitor_ctx->num_comps - 1) PetscCall(PetscViewerASCIIPrintf(ctx->viewer, ",")); 205*25125139SJames Wright } 206*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n")); 207*25125139SJames Wright } else { 208*25125139SJames Wright for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) { 209*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%s: %0.12e ", field_names[i], monitor_ctx->sum_values[i])); 210*25125139SJames Wright } 211*25125139SJames Wright PetscScalar sum_rates = 0; 212*25125139SJames Wright for (PetscInt i = 1; i < monitor_ctx->num_comps - 1; i++) sum_rates += monitor_ctx->sum_values[i]; 213*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "SumOfRates: %0.12e ", sum_rates)); 214*25125139SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n")); 215*25125139SJames Wright } 216*25125139SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 217*25125139SJames Wright } 218