187fd7f33SJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 287fd7f33SJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 387fd7f33SJames Wright 487fd7f33SJames Wright #include "../qfunctions/monitor_cfl.h" 587fd7f33SJames Wright #include <navierstokes.h> 687fd7f33SJames Wright 787fd7f33SJames Wright typedef struct { 887fd7f33SJames Wright OperatorApplyContext op_monitor_ctx; 987fd7f33SJames Wright Vec values; 1087fd7f33SJames Wright PetscInt num_comps; 1187fd7f33SJames Wright PetscInt tab_level; 1287fd7f33SJames Wright PetscBool is_header_written; 1387fd7f33SJames Wright } *MonitorCflCtx; 1487fd7f33SJames Wright 155206a5a0SJames Wright static PetscErrorCode MonitorCflCtxDestroy(MonitorCflCtx *monitor_ctx) { 165206a5a0SJames Wright MonitorCflCtx monitor_ctx_ = *monitor_ctx; 1787fd7f33SJames Wright 1887fd7f33SJames Wright PetscFunctionBeginUser; 195206a5a0SJames Wright PetscCall(OperatorApplyContextDestroy(monitor_ctx_->op_monitor_ctx)); 205206a5a0SJames Wright PetscCall(VecDestroy(&monitor_ctx_->values)); 215206a5a0SJames Wright PetscCall(PetscFree(monitor_ctx_)); 225206a5a0SJames Wright *monitor_ctx = NULL; 2387fd7f33SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2487fd7f33SJames Wright } 2587fd7f33SJames Wright 2687fd7f33SJames Wright PetscErrorCode SetupMontiorCfl(TS ts, PetscViewerAndFormat *ctx) { 2787fd7f33SJames Wright Honee honee; 2887fd7f33SJames Wright Ceed ceed; 2987fd7f33SJames Wright CeedQFunction qf_monitor = NULL; 3087fd7f33SJames Wright CeedOperator op_monitor; 3187fd7f33SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_cfl, elem_restr_q; 3287fd7f33SJames Wright CeedBasis basis_q; 3387fd7f33SJames Wright CeedVector q_data; 3487fd7f33SJames Wright CeedInt num_comp_q, q_data_size; 3587fd7f33SJames Wright DMLabel domain_label = NULL; 3687fd7f33SJames Wright PetscInt label_value = 0, num_comp_cfl = 1, dim, tab_level; 3787fd7f33SJames Wright MonitorCflCtx monitor_ctx; 3887fd7f33SJames Wright CeedQFunctionContext newt_qfctx; 3987fd7f33SJames Wright PetscBool is_ascii; 4087fd7f33SJames Wright 4187fd7f33SJames Wright PetscFunctionBeginUser; 4287fd7f33SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)ctx->viewer, PETSCVIEWERASCII, &is_ascii)); 4387fd7f33SJames Wright PetscCheck(is_ascii, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only supports ASCII viewers"); 4487fd7f33SJames Wright PetscCall(TSGetApplicationContext(ts, &honee)); 4587fd7f33SJames Wright PetscCall(DMGetDimension(honee->dm, &dim)); 4687fd7f33SJames Wright ceed = honee->ceed; 4787fd7f33SJames Wright 4887fd7f33SJames Wright PetscCall(PetscNew(&monitor_ctx)); 4987fd7f33SJames Wright 5087fd7f33SJames Wright PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(honee->elem_restr_q, &num_comp_q)); 5187fd7f33SJames 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, 5287fd7f33SJames Wright &q_data_size)); 5387fd7f33SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, honee->dm, domain_label, label_value, 0, num_comp_cfl, &elem_restr_cfl)); 5487fd7f33SJames Wright 5587fd7f33SJames Wright { // Get restriction and basis from the RHS function 5687fd7f33SJames Wright CeedOperator *sub_ops, main_op = honee->op_ifunction ? honee->op_ifunction : honee->op_rhs_ctx->op; 5787fd7f33SJames Wright CeedOperatorField op_field; 5887fd7f33SJames Wright PetscInt sub_op_index = 0; // will be 0 for the volume op 5987fd7f33SJames Wright 60*da7f3a07SJames Wright PetscCallCeed(ceed, CeedOperatorCompositeGetSubList(main_op, &sub_ops)); 6187fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_ops[sub_op_index], "q", &op_field)); 6287fd7f33SJames Wright 6387fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_q, &basis_q, NULL)); 6487fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorGetContext(sub_ops[sub_op_index], &newt_qfctx)); 6587fd7f33SJames Wright } 6687fd7f33SJames Wright 6787fd7f33SJames Wright switch (dim) { 6887fd7f33SJames Wright case 2: 6987fd7f33SJames Wright switch (honee->phys->state_var) { 7087fd7f33SJames Wright case STATEVAR_PRIMITIVE: 7187fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_2D_Prim, MonitorCFL_2D_Prim_loc, &qf_monitor)); 7287fd7f33SJames Wright break; 7387fd7f33SJames Wright case STATEVAR_CONSERVATIVE: 7487fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_2D_Conserv, MonitorCFL_2D_Conserv_loc, &qf_monitor)); 7587fd7f33SJames Wright break; 7687fd7f33SJames Wright case STATEVAR_ENTROPY: 7787fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_2D_Entropy, MonitorCFL_2D_Entropy_loc, &qf_monitor)); 7887fd7f33SJames Wright break; 7987fd7f33SJames Wright } 8087fd7f33SJames Wright break; 8187fd7f33SJames Wright case 3: 8287fd7f33SJames Wright switch (honee->phys->state_var) { 8387fd7f33SJames Wright case STATEVAR_PRIMITIVE: 8487fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_3D_Prim, MonitorCFL_3D_Prim_loc, &qf_monitor)); 8587fd7f33SJames Wright break; 8687fd7f33SJames Wright case STATEVAR_CONSERVATIVE: 8787fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_3D_Conserv, MonitorCFL_3D_Conserv_loc, &qf_monitor)); 8887fd7f33SJames Wright break; 8987fd7f33SJames Wright case STATEVAR_ENTROPY: 9087fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorCFL_3D_Entropy, MonitorCFL_3D_Entropy_loc, &qf_monitor)); 9187fd7f33SJames Wright break; 9287fd7f33SJames Wright } 9387fd7f33SJames Wright break; 9487fd7f33SJames Wright } 9587fd7f33SJames Wright PetscCheck(qf_monitor, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, 9687fd7f33SJames Wright "Could not create CFL monitor QFunction for dim %" PetscInt_FMT " and state variable %s", dim, StateVariables[honee->phys->state_var]); 9787fd7f33SJames Wright 98713571d7SJames Wright PetscBool is_advection; 99713571d7SJames Wright PetscCall(PetscStrcmp("advection", honee->app_ctx->problem_name, &is_advection)); 100713571d7SJames Wright if (is_advection) { 101713571d7SJames Wright NewtonianIdealGasContext newt_ctx; 102713571d7SJames Wright 103713571d7SJames Wright PetscCall(PetscNew(&newt_ctx)); 104713571d7SJames Wright PetscCallCeed(ceed, CeedQFunctionContextDestroy(&newt_qfctx)); 105713571d7SJames Wright PetscCallCeed(ceed, CeedQFunctionContextCreate(ceed, &newt_qfctx)); 106713571d7SJames Wright PetscCallCeed(ceed, CeedQFunctionContextSetData(newt_qfctx, CEED_MEM_HOST, CEED_USE_POINTER, sizeof(*newt_ctx), newt_ctx)); 107713571d7SJames Wright PetscCallCeed(ceed, CeedQFunctionContextSetDataDestroy(newt_qfctx, CEED_MEM_HOST, FreeContextPetsc)); 108713571d7SJames Wright } 109713571d7SJames Wright 11087fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(qf_monitor, newt_qfctx)); 11187fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q", num_comp_q, CEED_EVAL_INTERP)); 11287fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q_data", q_data_size, CEED_EVAL_NONE)); 11387fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_monitor, "v", num_comp_cfl, CEED_EVAL_NONE)); 11487fd7f33SJames Wright 11587fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_monitor, NULL, NULL, &op_monitor)); 11687fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 11787fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q_data", elem_restr_qd, CEED_BASIS_NONE, q_data)); 11887fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "v", elem_restr_cfl, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE)); 11987fd7f33SJames Wright 12087fd7f33SJames Wright PetscCall(OperatorApplyContextCreate(honee->dm, NULL, ceed, op_monitor, NULL, NULL, NULL, NULL, &monitor_ctx->op_monitor_ctx)); 12187fd7f33SJames Wright 12287fd7f33SJames Wright PetscCall(CeedOperatorCreateLocalVecs(op_monitor, DMReturnVecType(honee->dm), PETSC_COMM_SELF, NULL, &monitor_ctx->values)); 12387fd7f33SJames Wright PetscCall(VecSetBlockSize(monitor_ctx->values, num_comp_cfl)); 12487fd7f33SJames Wright monitor_ctx->num_comps = num_comp_cfl; 12587fd7f33SJames Wright PetscCall(PetscObjectGetTabLevel((PetscObject)ts, &tab_level)); 12687fd7f33SJames Wright monitor_ctx->tab_level = tab_level + 1; 12787fd7f33SJames Wright 12887fd7f33SJames Wright ctx->data = monitor_ctx; 1295206a5a0SJames Wright ctx->data_destroy = (PetscCtxDestroyFn *)MonitorCflCtxDestroy; 13087fd7f33SJames Wright 13187fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionContextDestroy(&newt_qfctx)); 13287fd7f33SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 13387fd7f33SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 13487fd7f33SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_cfl)); 13587fd7f33SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 13687fd7f33SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 13787fd7f33SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_monitor)); 13887fd7f33SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&op_monitor)); 13987fd7f33SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 14087fd7f33SJames Wright } 14187fd7f33SJames Wright 14287fd7f33SJames Wright PetscErrorCode TSMonitor_Cfl(TS ts, PetscInt step, PetscReal solution_time, Vec Q, PetscViewerAndFormat *ctx) { 14387fd7f33SJames Wright MonitorCflCtx monitor_ctx = (MonitorCflCtx)ctx->data; 14487fd7f33SJames Wright Honee honee; 14587fd7f33SJames Wright MPI_Comm comm; 14687fd7f33SJames Wright TSConvergedReason reason; 14787fd7f33SJames Wright PetscReal part_minmax[2], global_minmax[2], dt; 14887fd7f33SJames Wright 14987fd7f33SJames Wright PetscFunctionBeginUser; 15087fd7f33SJames Wright PetscCall(TSGetConvergedReason(ts, &reason)); 15187fd7f33SJames Wright if (!(step % ctx->view_interval == 0 || reason != TS_CONVERGED_ITERATING)) PetscFunctionReturn(PETSC_SUCCESS); 15287fd7f33SJames Wright PetscCall(TSGetApplicationContext(ts, &honee)); 15387fd7f33SJames Wright PetscCall(PetscObjectGetComm((PetscObject)ts, &comm)); 15487fd7f33SJames Wright 15587fd7f33SJames Wright PetscCall(UpdateBoundaryValues(honee, honee->Q_loc, solution_time)); 15687fd7f33SJames Wright PetscCall(DMGlobalToLocal(honee->dm, Q, INSERT_VALUES, honee->Q_loc)); 15787fd7f33SJames Wright 15887fd7f33SJames Wright PetscCall(ApplyCeedOperatorLocalToLocal(honee->Q_loc, monitor_ctx->values, monitor_ctx->op_monitor_ctx)); 15987fd7f33SJames Wright 16087fd7f33SJames Wright PetscCall(VecMin(monitor_ctx->values, NULL, &part_minmax[0])); 16187fd7f33SJames Wright PetscCall(VecMax(monitor_ctx->values, NULL, &part_minmax[1])); 16287fd7f33SJames Wright // Need to get global min/max since `values` is only the local partition 16387fd7f33SJames Wright PetscCall(PetscGlobalMinMaxReal(comm, part_minmax, global_minmax)); 16487fd7f33SJames Wright PetscCall(TSGetTimeStep(ts, &dt)); 16587fd7f33SJames Wright global_minmax[0] *= dt; 16687fd7f33SJames Wright global_minmax[1] *= dt; 16787fd7f33SJames Wright 16887fd7f33SJames Wright if (ctx->format == PETSC_VIEWER_ASCII_CSV) { 16987fd7f33SJames Wright if (!monitor_ctx->is_header_written) { 17087fd7f33SJames Wright char buf[PETSC_MAX_PATH_LEN]; 17187fd7f33SJames Wright const char *buf_const; 17287fd7f33SJames Wright time_t t = time(NULL); 17387fd7f33SJames Wright 17487fd7f33SJames Wright PetscCall(PetscGetVersion(buf, sizeof(buf))); 17587fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_version: %s\n", buf)); 17687fd7f33SJames Wright PetscCall(PetscGetPetscDir(&buf_const)); 17787fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_directory: %s\n", buf_const)); 17887fd7f33SJames Wright PetscCall(PetscGetArchType(buf, sizeof(buf))); 17987fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_arch: %s\n", buf)); 18014bd2a07SJames Wright PetscCheck(strftime(buf, sizeof(buf), "%FT%T%z", localtime(&t)), comm, PETSC_ERR_SYS, "strftime() call failed"); 18187fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date: %s\n", buf)); 18214bd2a07SJames Wright PetscCheck(strftime(buf, sizeof(buf), "%Z", localtime(&t)), comm, PETSC_ERR_SYS, "strftime() call failed"); 18387fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date_timezone: %s\n", buf)); 18487fd7f33SJames Wright PetscCall(PetscGetUserName(buf, sizeof(buf))); 18587fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# username: %s\n", buf)); 18687fd7f33SJames Wright PetscCall(PetscGetHostName(buf, sizeof(buf))); 18787fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# hostname: %s\n", buf)); 18887fd7f33SJames Wright PetscCall(PetscGetWorkingDirectory(buf, sizeof(buf))); 18987fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# working_directory: %s\n", buf)); 19087fd7f33SJames Wright 19187fd7f33SJames Wright PetscCall(PetscViewerFileGetName(ctx->viewer, &buf_const)); 19287fd7f33SJames Wright PetscCall(PetscGetFullPath(buf_const, buf, sizeof(buf))); 19387fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# original_file_path: %s\n", buf)); 19487fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "#\n")); 19587fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "step,time,mincfl,maxcfl\n")); 19687fd7f33SJames Wright monitor_ctx->is_header_written = PETSC_TRUE; 19787fd7f33SJames Wright } 19887fd7f33SJames Wright 19987fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%" PetscInt_FMT ",%0.17e,", step, solution_time)); 20087fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%0.17e,%0.17e", global_minmax[0], global_minmax[1])); 20187fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n")); 20287fd7f33SJames Wright } else { 20387fd7f33SJames Wright PetscCall(PetscViewerASCIIAddTab(ctx->viewer, monitor_ctx->tab_level)); 20487fd7f33SJames Wright PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "Min, Max CFL: %0.5g, %0.5g\n", global_minmax[0], global_minmax[1])); 20587fd7f33SJames Wright PetscCall(PetscViewerASCIISubtractTab(ctx->viewer, monitor_ctx->tab_level)); 20687fd7f33SJames Wright } 20787fd7f33SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 20887fd7f33SJames Wright } 209