13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 377841947SLeila Ghaffari // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 577841947SLeila Ghaffari // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 777841947SLeila Ghaffari 877841947SLeila Ghaffari /// @file 977841947SLeila Ghaffari /// Miscellaneous utility functions 1077841947SLeila Ghaffari 1177841947SLeila Ghaffari #include "../navierstokes.h" 1277841947SLeila Ghaffari 13*2b730f8bSJeremy L Thompson PetscErrorCode ICs_FixMultiplicity(DM dm, CeedData ceed_data, User user, Vec Q_loc, Vec Q, CeedScalar time) { 1477841947SLeila Ghaffari PetscFunctionBeginUser; 1577841947SLeila Ghaffari 1677841947SLeila Ghaffari // --------------------------------------------------------------------------- 17a0add3c9SJed Brown // Update time for evaluation 1877841947SLeila Ghaffari // --------------------------------------------------------------------------- 19*2b730f8bSJeremy L Thompson if (user->phys->ics_time_label) CeedOperatorContextSetDouble(ceed_data->op_ics, user->phys->ics_time_label, &time); 2077841947SLeila Ghaffari 2177841947SLeila Ghaffari // --------------------------------------------------------------------------- 2277841947SLeila Ghaffari // ICs 2377841947SLeila Ghaffari // --------------------------------------------------------------------------- 2477841947SLeila Ghaffari // -- CEED Restriction 2577841947SLeila Ghaffari CeedVector q0_ceed; 2677841947SLeila Ghaffari CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &q0_ceed, NULL); 2777841947SLeila Ghaffari 2877841947SLeila Ghaffari // -- Place PETSc vector in CEED vector 2977841947SLeila Ghaffari CeedScalar *q0; 3077841947SLeila Ghaffari PetscMemType q0_mem_type; 31*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(Q_loc, (PetscScalar **)&q0, &q0_mem_type)); 3277841947SLeila Ghaffari CeedVectorSetArray(q0_ceed, MemTypeP2C(q0_mem_type), CEED_USE_POINTER, q0); 3377841947SLeila Ghaffari 3477841947SLeila Ghaffari // -- Apply CEED Operator 35*2b730f8bSJeremy L Thompson CeedOperatorApply(ceed_data->op_ics, ceed_data->x_coord, q0_ceed, CEED_REQUEST_IMMEDIATE); 3677841947SLeila Ghaffari 3777841947SLeila Ghaffari // -- Restore vectors 3877841947SLeila Ghaffari CeedVectorTakeArray(q0_ceed, MemTypeP2C(q0_mem_type), NULL); 39*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(Q_loc, (const PetscScalar **)&q0)); 4077841947SLeila Ghaffari 4177841947SLeila Ghaffari // -- Local-to-Global 42*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Q)); 43*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(dm, Q_loc, ADD_VALUES, Q)); 4477841947SLeila Ghaffari 4577841947SLeila Ghaffari // --------------------------------------------------------------------------- 4677841947SLeila Ghaffari // Fix multiplicity for output of ICs 4777841947SLeila Ghaffari // --------------------------------------------------------------------------- 4877841947SLeila Ghaffari // -- CEED Restriction 4977841947SLeila Ghaffari CeedVector mult_vec; 5077841947SLeila Ghaffari CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &mult_vec, NULL); 5177841947SLeila Ghaffari 5277841947SLeila Ghaffari // -- Place PETSc vector in CEED vector 5377841947SLeila Ghaffari CeedScalar *mult; 5477841947SLeila Ghaffari PetscMemType m_mem_type; 5577841947SLeila Ghaffari Vec multiplicity_loc; 56*2b730f8bSJeremy L Thompson PetscCall(DMGetLocalVector(dm, &multiplicity_loc)); 57*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(multiplicity_loc, (PetscScalar **)&mult, &m_mem_type)); 5877841947SLeila Ghaffari CeedVectorSetArray(mult_vec, MemTypeP2C(m_mem_type), CEED_USE_POINTER, mult); 5977841947SLeila Ghaffari 6077841947SLeila Ghaffari // -- Get multiplicity 6177841947SLeila Ghaffari CeedElemRestrictionGetMultiplicity(ceed_data->elem_restr_q, mult_vec); 6277841947SLeila Ghaffari 6377841947SLeila Ghaffari // -- Restore vectors 6477841947SLeila Ghaffari CeedVectorTakeArray(mult_vec, MemTypeP2C(m_mem_type), NULL); 65*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(multiplicity_loc, (const PetscScalar **)&mult)); 6677841947SLeila Ghaffari 6777841947SLeila Ghaffari // -- Local-to-Global 6877841947SLeila Ghaffari Vec multiplicity; 69*2b730f8bSJeremy L Thompson PetscCall(DMGetGlobalVector(dm, &multiplicity)); 70*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(multiplicity)); 71*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(dm, multiplicity_loc, ADD_VALUES, multiplicity)); 7277841947SLeila Ghaffari 7377841947SLeila Ghaffari // -- Fix multiplicity 74*2b730f8bSJeremy L Thompson PetscCall(VecPointwiseDivide(Q, Q, multiplicity)); 75*2b730f8bSJeremy L Thompson PetscCall(VecPointwiseDivide(Q_loc, Q_loc, multiplicity_loc)); 7677841947SLeila Ghaffari 7777841947SLeila Ghaffari // -- Restore vectors 78*2b730f8bSJeremy L Thompson PetscCall(DMRestoreLocalVector(dm, &multiplicity_loc)); 79*2b730f8bSJeremy L Thompson PetscCall(DMRestoreGlobalVector(dm, &multiplicity)); 8077841947SLeila Ghaffari 8177841947SLeila Ghaffari // Cleanup 8277841947SLeila Ghaffari CeedVectorDestroy(&mult_vec); 8377841947SLeila Ghaffari CeedVectorDestroy(&q0_ceed); 8477841947SLeila Ghaffari 8577841947SLeila Ghaffari PetscFunctionReturn(0); 8677841947SLeila Ghaffari } 8777841947SLeila Ghaffari 88*2b730f8bSJeremy L Thompson PetscErrorCode DMPlexInsertBoundaryValues_NS(DM dm, PetscBool insert_essential, Vec Q_loc, PetscReal time, Vec face_geom_FVM, Vec cell_geom_FVM, 89*2b730f8bSJeremy L Thompson Vec grad_FVM) { 905571c6fdSJames Wright Vec Qbc, boundary_mask; 9177841947SLeila Ghaffari PetscFunctionBegin; 9277841947SLeila Ghaffari 935571c6fdSJames Wright // Mask (zero) Dirichlet entries 945571c6fdSJames Wright PetscCall(DMGetNamedLocalVector(dm, "boundary mask", &boundary_mask)); 955571c6fdSJames Wright PetscCall(VecPointwiseMult(Q_loc, Q_loc, boundary_mask)); 965571c6fdSJames Wright PetscCall(DMRestoreNamedLocalVector(dm, "boundary mask", &boundary_mask)); 975571c6fdSJames Wright 98*2b730f8bSJeremy L Thompson PetscCall(DMGetNamedLocalVector(dm, "Qbc", &Qbc)); 99*2b730f8bSJeremy L Thompson PetscCall(VecAXPY(Q_loc, 1., Qbc)); 100*2b730f8bSJeremy L Thompson PetscCall(DMRestoreNamedLocalVector(dm, "Qbc", &Qbc)); 10177841947SLeila Ghaffari 10277841947SLeila Ghaffari PetscFunctionReturn(0); 10377841947SLeila Ghaffari } 10477841947SLeila Ghaffari 10577841947SLeila Ghaffari // Compare reference solution values with current test run for CI 10677841947SLeila Ghaffari PetscErrorCode RegressionTests_NS(AppCtx app_ctx, Vec Q) { 10777841947SLeila Ghaffari Vec Qref; 10877841947SLeila Ghaffari PetscViewer viewer; 10977841947SLeila Ghaffari PetscReal error, Qrefnorm; 11077841947SLeila Ghaffari PetscFunctionBegin; 11177841947SLeila Ghaffari 11277841947SLeila Ghaffari // Read reference file 113*2b730f8bSJeremy L Thompson PetscCall(VecDuplicate(Q, &Qref)); 114*2b730f8bSJeremy L Thompson PetscCall(PetscViewerBinaryOpen(PetscObjectComm((PetscObject)Q), app_ctx->file_path, FILE_MODE_READ, &viewer)); 115*2b730f8bSJeremy L Thompson PetscCall(VecLoad(Qref, viewer)); 11677841947SLeila Ghaffari 11777841947SLeila Ghaffari // Compute error with respect to reference solution 118*2b730f8bSJeremy L Thompson PetscCall(VecAXPY(Q, -1.0, Qref)); 119*2b730f8bSJeremy L Thompson PetscCall(VecNorm(Qref, NORM_MAX, &Qrefnorm)); 120*2b730f8bSJeremy L Thompson PetscCall(VecScale(Q, 1. / Qrefnorm)); 121*2b730f8bSJeremy L Thompson PetscCall(VecNorm(Q, NORM_MAX, &error)); 12277841947SLeila Ghaffari 12377841947SLeila Ghaffari // Check error 12477841947SLeila Ghaffari if (error > app_ctx->test_tol) { 125*2b730f8bSJeremy L Thompson PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test failed with error norm %g\n", (double)error)); 12677841947SLeila Ghaffari } 12777841947SLeila Ghaffari 12877841947SLeila Ghaffari // Cleanup 129*2b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 130*2b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Qref)); 13177841947SLeila Ghaffari 13277841947SLeila Ghaffari PetscFunctionReturn(0); 13377841947SLeila Ghaffari } 13477841947SLeila Ghaffari 13577841947SLeila Ghaffari // Get error for problems with exact solutions 136*2b730f8bSJeremy L Thompson PetscErrorCode GetError_NS(CeedData ceed_data, DM dm, User user, Vec Q, PetscScalar final_time) { 13777841947SLeila Ghaffari PetscInt loc_nodes; 13877841947SLeila Ghaffari Vec Q_exact, Q_exact_loc; 13977841947SLeila Ghaffari PetscReal rel_error, norm_error, norm_exact; 14077841947SLeila Ghaffari PetscFunctionBegin; 14177841947SLeila Ghaffari 14277841947SLeila Ghaffari // Get exact solution at final time 143*2b730f8bSJeremy L Thompson PetscCall(DMCreateGlobalVector(dm, &Q_exact)); 144*2b730f8bSJeremy L Thompson PetscCall(DMGetLocalVector(dm, &Q_exact_loc)); 145*2b730f8bSJeremy L Thompson PetscCall(VecGetSize(Q_exact_loc, &loc_nodes)); 146*2b730f8bSJeremy L Thompson PetscCall(ICs_FixMultiplicity(dm, ceed_data, user, Q_exact_loc, Q_exact, final_time)); 14777841947SLeila Ghaffari 14877841947SLeila Ghaffari // Get |exact solution - obtained solution| 149*2b730f8bSJeremy L Thompson PetscCall(VecNorm(Q_exact, NORM_1, &norm_exact)); 150*2b730f8bSJeremy L Thompson PetscCall(VecAXPY(Q, -1.0, Q_exact)); 151*2b730f8bSJeremy L Thompson PetscCall(VecNorm(Q, NORM_1, &norm_error)); 15277841947SLeila Ghaffari 15377841947SLeila Ghaffari // Compute relative error 15477841947SLeila Ghaffari rel_error = norm_error / norm_exact; 15577841947SLeila Ghaffari 15677841947SLeila Ghaffari // Output relative error 157*2b730f8bSJeremy L Thompson PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Relative Error: %g\n", (double)rel_error)); 15877841947SLeila Ghaffari // Cleanup 159*2b730f8bSJeremy L Thompson PetscCall(DMRestoreLocalVector(dm, &Q_exact_loc)); 160*2b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Q_exact)); 16177841947SLeila Ghaffari 16277841947SLeila Ghaffari PetscFunctionReturn(0); 16377841947SLeila Ghaffari } 16477841947SLeila Ghaffari 16577841947SLeila Ghaffari // Post-processing 166*2b730f8bSJeremy L Thompson PetscErrorCode PostProcess_NS(TS ts, CeedData ceed_data, DM dm, ProblemData *problem, User user, Vec Q, PetscScalar final_time) { 16777841947SLeila Ghaffari PetscInt steps; 16877841947SLeila Ghaffari PetscFunctionBegin; 16977841947SLeila Ghaffari 17077841947SLeila Ghaffari // Print relative error 171841e4c73SJed Brown if (problem->non_zero_time && !user->app_ctx->test_mode) { 172*2b730f8bSJeremy L Thompson PetscCall(GetError_NS(ceed_data, dm, user, Q, final_time)); 17377841947SLeila Ghaffari } 17477841947SLeila Ghaffari 17577841947SLeila Ghaffari // Print final time and number of steps 176*2b730f8bSJeremy L Thompson PetscCall(TSGetStepNumber(ts, &steps)); 177841e4c73SJed Brown if (!user->app_ctx->test_mode) { 178*2b730f8bSJeremy L Thompson PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Time integrator took %" PetscInt_FMT " time steps to reach final time %g\n", steps, (double)final_time)); 17977841947SLeila Ghaffari } 18077841947SLeila Ghaffari 18177841947SLeila Ghaffari // Output numerical values from command line 182*2b730f8bSJeremy L Thompson PetscCall(VecViewFromOptions(Q, NULL, "-vec_view")); 18377841947SLeila Ghaffari 18477841947SLeila Ghaffari // Compare reference solution values with current test run for CI 185841e4c73SJed Brown if (user->app_ctx->test_mode) { 186*2b730f8bSJeremy L Thompson PetscCall(RegressionTests_NS(user->app_ctx, Q)); 18777841947SLeila Ghaffari } 18877841947SLeila Ghaffari 18977841947SLeila Ghaffari PetscFunctionReturn(0); 19077841947SLeila Ghaffari } 19177841947SLeila Ghaffari 19277841947SLeila Ghaffari // Gather initial Q values in case of continuation of simulation 19377841947SLeila Ghaffari PetscErrorCode SetupICsFromBinary(MPI_Comm comm, AppCtx app_ctx, Vec Q) { 19477841947SLeila Ghaffari PetscViewer viewer; 195*2b730f8bSJeremy L Thompson 19677841947SLeila Ghaffari PetscFunctionBegin; 19777841947SLeila Ghaffari 19877841947SLeila Ghaffari // Read input 199*2b730f8bSJeremy L Thompson PetscCall(PetscViewerBinaryOpen(comm, app_ctx->cont_file, FILE_MODE_READ, &viewer)); 20077841947SLeila Ghaffari 20177841947SLeila Ghaffari // Load Q from existent solution 202*2b730f8bSJeremy L Thompson PetscCall(VecLoad(Q, viewer)); 20377841947SLeila Ghaffari 20477841947SLeila Ghaffari // Cleanup 205*2b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 20677841947SLeila Ghaffari 20777841947SLeila Ghaffari PetscFunctionReturn(0); 20877841947SLeila Ghaffari } 20977841947SLeila Ghaffari 21077841947SLeila Ghaffari // Record boundary values from initial condition 21177841947SLeila Ghaffari PetscErrorCode SetBCsFromICs_NS(DM dm, Vec Q, Vec Q_loc) { 2125571c6fdSJames Wright Vec Qbc, boundary_mask; 21377841947SLeila Ghaffari PetscFunctionBegin; 21477841947SLeila Ghaffari 215*2b730f8bSJeremy L Thompson PetscCall(DMGetNamedLocalVector(dm, "Qbc", &Qbc)); 216*2b730f8bSJeremy L Thompson PetscCall(VecCopy(Q_loc, Qbc)); 217*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Q_loc)); 218*2b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(dm, Q, INSERT_VALUES, Q_loc)); 219*2b730f8bSJeremy L Thompson PetscCall(VecAXPY(Qbc, -1., Q_loc)); 220*2b730f8bSJeremy L Thompson PetscCall(DMRestoreNamedLocalVector(dm, "Qbc", &Qbc)); 221*2b730f8bSJeremy L Thompson PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_NS)); 22277841947SLeila Ghaffari 2235571c6fdSJames Wright PetscCall(DMGetNamedLocalVector(dm, "boundary mask", &boundary_mask)); 2245571c6fdSJames Wright PetscCall(DMGetGlobalVector(dm, &Q)); 2255571c6fdSJames Wright PetscCall(VecZeroEntries(boundary_mask)); 2265571c6fdSJames Wright PetscCall(VecSet(Q, 1.0)); 2275571c6fdSJames Wright PetscCall(DMGlobalToLocal(dm, Q, INSERT_VALUES, boundary_mask)); 2285571c6fdSJames Wright PetscCall(DMRestoreNamedLocalVector(dm, "boundary mask", &boundary_mask)); 2295571c6fdSJames Wright 23077841947SLeila Ghaffari PetscFunctionReturn(0); 23177841947SLeila Ghaffari } 232841e4c73SJed Brown 233841e4c73SJed Brown // Free a plain data context that was allocated using PETSc; returning libCEED error codes 234841e4c73SJed Brown int FreeContextPetsc(void *data) { 235*2b730f8bSJeremy L Thompson if (PetscFree(data)) return CeedError(NULL, CEED_ERROR_ACCESS, "PetscFree failed"); 236841e4c73SJed Brown return CEED_ERROR_SUCCESS; 237841e4c73SJed Brown } 238