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*841e4c73SJed Brown PetscErrorCode ICs_FixMultiplicity(DM dm, CeedData ceed_data, User user, 14*841e4c73SJed Brown Vec Q_loc, Vec Q, 1577841947SLeila Ghaffari CeedScalar time) { 1677841947SLeila Ghaffari PetscErrorCode ierr; 1777841947SLeila Ghaffari PetscFunctionBeginUser; 1877841947SLeila Ghaffari 1977841947SLeila Ghaffari // --------------------------------------------------------------------------- 2077841947SLeila Ghaffari // Update SetupContext 2177841947SLeila Ghaffari // --------------------------------------------------------------------------- 22*841e4c73SJed Brown if (user->phys->ics_time_label) 23*841e4c73SJed Brown CeedOperatorContextSetDouble(ceed_data->op_ics, user->phys->ics_time_label, 24*841e4c73SJed Brown &time); 2577841947SLeila Ghaffari 2677841947SLeila Ghaffari // --------------------------------------------------------------------------- 2777841947SLeila Ghaffari // ICs 2877841947SLeila Ghaffari // --------------------------------------------------------------------------- 2977841947SLeila Ghaffari // -- CEED Restriction 3077841947SLeila Ghaffari CeedVector q0_ceed; 3177841947SLeila Ghaffari CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &q0_ceed, NULL); 3277841947SLeila Ghaffari 3377841947SLeila Ghaffari // -- Place PETSc vector in CEED vector 3477841947SLeila Ghaffari CeedScalar *q0; 3577841947SLeila Ghaffari PetscMemType q0_mem_type; 3677841947SLeila Ghaffari ierr = VecGetArrayAndMemType(Q_loc, (PetscScalar **)&q0, &q0_mem_type); 3777841947SLeila Ghaffari CHKERRQ(ierr); 3877841947SLeila Ghaffari CeedVectorSetArray(q0_ceed, MemTypeP2C(q0_mem_type), CEED_USE_POINTER, q0); 3977841947SLeila Ghaffari 4077841947SLeila Ghaffari // -- Apply CEED Operator 4177841947SLeila Ghaffari CeedOperatorApply(ceed_data->op_ics, ceed_data->x_coord, q0_ceed, 4277841947SLeila Ghaffari CEED_REQUEST_IMMEDIATE); 4377841947SLeila Ghaffari 4477841947SLeila Ghaffari // -- Restore vectors 4577841947SLeila Ghaffari CeedVectorTakeArray(q0_ceed, MemTypeP2C(q0_mem_type), NULL); 4677841947SLeila Ghaffari ierr = VecRestoreArrayReadAndMemType(Q_loc, (const PetscScalar **)&q0); 4777841947SLeila Ghaffari CHKERRQ(ierr); 4877841947SLeila Ghaffari 4977841947SLeila Ghaffari // -- Local-to-Global 5077841947SLeila Ghaffari ierr = VecZeroEntries(Q); CHKERRQ(ierr); 5177841947SLeila Ghaffari ierr = DMLocalToGlobal(dm, Q_loc, ADD_VALUES, Q); CHKERRQ(ierr); 5277841947SLeila Ghaffari 5377841947SLeila Ghaffari // --------------------------------------------------------------------------- 5477841947SLeila Ghaffari // Fix multiplicity for output of ICs 5577841947SLeila Ghaffari // --------------------------------------------------------------------------- 5677841947SLeila Ghaffari // -- CEED Restriction 5777841947SLeila Ghaffari CeedVector mult_vec; 5877841947SLeila Ghaffari CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &mult_vec, NULL); 5977841947SLeila Ghaffari 6077841947SLeila Ghaffari // -- Place PETSc vector in CEED vector 6177841947SLeila Ghaffari CeedScalar *mult; 6277841947SLeila Ghaffari PetscMemType m_mem_type; 6377841947SLeila Ghaffari Vec multiplicity_loc; 6477841947SLeila Ghaffari ierr = DMGetLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr); 6577841947SLeila Ghaffari ierr = VecGetArrayAndMemType(multiplicity_loc, (PetscScalar **)&mult, 6677841947SLeila Ghaffari &m_mem_type); 6777841947SLeila Ghaffari CHKERRQ(ierr); 6877841947SLeila Ghaffari CeedVectorSetArray(mult_vec, MemTypeP2C(m_mem_type), CEED_USE_POINTER, mult); 6977841947SLeila Ghaffari CHKERRQ(ierr); 7077841947SLeila Ghaffari 7177841947SLeila Ghaffari // -- Get multiplicity 7277841947SLeila Ghaffari CeedElemRestrictionGetMultiplicity(ceed_data->elem_restr_q, mult_vec); 7377841947SLeila Ghaffari 7477841947SLeila Ghaffari // -- Restore vectors 7577841947SLeila Ghaffari CeedVectorTakeArray(mult_vec, MemTypeP2C(m_mem_type), NULL); 7677841947SLeila Ghaffari ierr = VecRestoreArrayReadAndMemType(multiplicity_loc, 7777841947SLeila Ghaffari (const PetscScalar **)&mult); CHKERRQ(ierr); 7877841947SLeila Ghaffari 7977841947SLeila Ghaffari // -- Local-to-Global 8077841947SLeila Ghaffari Vec multiplicity; 8177841947SLeila Ghaffari ierr = DMGetGlobalVector(dm, &multiplicity); CHKERRQ(ierr); 8277841947SLeila Ghaffari ierr = VecZeroEntries(multiplicity); CHKERRQ(ierr); 8377841947SLeila Ghaffari ierr = DMLocalToGlobal(dm, multiplicity_loc, ADD_VALUES, multiplicity); 8477841947SLeila Ghaffari CHKERRQ(ierr); 8577841947SLeila Ghaffari 8677841947SLeila Ghaffari // -- Fix multiplicity 8777841947SLeila Ghaffari ierr = VecPointwiseDivide(Q, Q, multiplicity); CHKERRQ(ierr); 8877841947SLeila Ghaffari ierr = VecPointwiseDivide(Q_loc, Q_loc, multiplicity_loc); CHKERRQ(ierr); 8977841947SLeila Ghaffari 9077841947SLeila Ghaffari // -- Restore vectors 9177841947SLeila Ghaffari ierr = DMRestoreLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr); 9277841947SLeila Ghaffari ierr = DMRestoreGlobalVector(dm, &multiplicity); CHKERRQ(ierr); 9377841947SLeila Ghaffari 9477841947SLeila Ghaffari // Cleanup 9577841947SLeila Ghaffari CeedVectorDestroy(&mult_vec); 9677841947SLeila Ghaffari CeedVectorDestroy(&q0_ceed); 9777841947SLeila Ghaffari 9877841947SLeila Ghaffari PetscFunctionReturn(0); 9977841947SLeila Ghaffari } 10077841947SLeila Ghaffari 10177841947SLeila Ghaffari PetscErrorCode DMPlexInsertBoundaryValues_NS(DM dm, 10277841947SLeila Ghaffari PetscBool insert_essential, Vec Q_loc, PetscReal time, Vec face_geom_FVM, 10377841947SLeila Ghaffari Vec cell_geom_FVM, Vec grad_FVM) { 10477841947SLeila Ghaffari 10577841947SLeila Ghaffari Vec Qbc; 10677841947SLeila Ghaffari PetscErrorCode ierr; 10777841947SLeila Ghaffari PetscFunctionBegin; 10877841947SLeila Ghaffari 10977841947SLeila Ghaffari ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr); 11077841947SLeila Ghaffari ierr = VecAXPY(Q_loc, 1., Qbc); CHKERRQ(ierr); 11177841947SLeila Ghaffari ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr); 11277841947SLeila Ghaffari 11377841947SLeila Ghaffari PetscFunctionReturn(0); 11477841947SLeila Ghaffari } 11577841947SLeila Ghaffari 11677841947SLeila Ghaffari // Compare reference solution values with current test run for CI 11777841947SLeila Ghaffari PetscErrorCode RegressionTests_NS(AppCtx app_ctx, Vec Q) { 11877841947SLeila Ghaffari 11977841947SLeila Ghaffari Vec Qref; 12077841947SLeila Ghaffari PetscViewer viewer; 12177841947SLeila Ghaffari PetscReal error, Qrefnorm; 12277841947SLeila Ghaffari PetscErrorCode ierr; 12377841947SLeila Ghaffari PetscFunctionBegin; 12477841947SLeila Ghaffari 12577841947SLeila Ghaffari // Read reference file 12677841947SLeila Ghaffari ierr = VecDuplicate(Q, &Qref); CHKERRQ(ierr); 12777841947SLeila Ghaffari ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)Q), 12877841947SLeila Ghaffari app_ctx->file_path, FILE_MODE_READ, 12977841947SLeila Ghaffari &viewer); CHKERRQ(ierr); 13077841947SLeila Ghaffari ierr = VecLoad(Qref, viewer); CHKERRQ(ierr); 13177841947SLeila Ghaffari 13277841947SLeila Ghaffari // Compute error with respect to reference solution 13377841947SLeila Ghaffari ierr = VecAXPY(Q, -1.0, Qref); CHKERRQ(ierr); 13477841947SLeila Ghaffari ierr = VecNorm(Qref, NORM_MAX, &Qrefnorm); CHKERRQ(ierr); 13577841947SLeila Ghaffari ierr = VecScale(Q, 1./Qrefnorm); CHKERRQ(ierr); 13677841947SLeila Ghaffari ierr = VecNorm(Q, NORM_MAX, &error); CHKERRQ(ierr); 13777841947SLeila Ghaffari 13877841947SLeila Ghaffari // Check error 13977841947SLeila Ghaffari if (error > app_ctx->test_tol) { 14077841947SLeila Ghaffari ierr = PetscPrintf(PETSC_COMM_WORLD, 14177841947SLeila Ghaffari "Test failed with error norm %g\n", 14277841947SLeila Ghaffari (double)error); CHKERRQ(ierr); 14377841947SLeila Ghaffari } 14477841947SLeila Ghaffari 14577841947SLeila Ghaffari // Cleanup 14677841947SLeila Ghaffari ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr); 14777841947SLeila Ghaffari ierr = VecDestroy(&Qref); CHKERRQ(ierr); 14877841947SLeila Ghaffari 14977841947SLeila Ghaffari PetscFunctionReturn(0); 15077841947SLeila Ghaffari } 15177841947SLeila Ghaffari 15277841947SLeila Ghaffari // Get error for problems with exact solutions 153*841e4c73SJed Brown PetscErrorCode GetError_NS(CeedData ceed_data, DM dm, User user, Vec Q, 15477841947SLeila Ghaffari PetscScalar final_time) { 15577841947SLeila Ghaffari PetscInt loc_nodes; 15677841947SLeila Ghaffari Vec Q_exact, Q_exact_loc; 15777841947SLeila Ghaffari PetscReal rel_error, norm_error, norm_exact; 15877841947SLeila Ghaffari PetscErrorCode ierr; 15977841947SLeila Ghaffari PetscFunctionBegin; 16077841947SLeila Ghaffari 16177841947SLeila Ghaffari // Get exact solution at final time 16277841947SLeila Ghaffari ierr = DMCreateGlobalVector(dm, &Q_exact); CHKERRQ(ierr); 16377841947SLeila Ghaffari ierr = DMGetLocalVector(dm, &Q_exact_loc); CHKERRQ(ierr); 16477841947SLeila Ghaffari ierr = VecGetSize(Q_exact_loc, &loc_nodes); CHKERRQ(ierr); 165*841e4c73SJed Brown ierr = ICs_FixMultiplicity(dm, ceed_data, user, Q_exact_loc, Q_exact, 166*841e4c73SJed Brown final_time); 16777841947SLeila Ghaffari CHKERRQ(ierr); 16877841947SLeila Ghaffari 16977841947SLeila Ghaffari // Get |exact solution - obtained solution| 17077841947SLeila Ghaffari ierr = VecNorm(Q_exact, NORM_1, &norm_exact); CHKERRQ(ierr); 17177841947SLeila Ghaffari ierr = VecAXPY(Q, -1.0, Q_exact); CHKERRQ(ierr); 17277841947SLeila Ghaffari ierr = VecNorm(Q, NORM_1, &norm_error); CHKERRQ(ierr); 17377841947SLeila Ghaffari 17477841947SLeila Ghaffari // Compute relative error 17577841947SLeila Ghaffari rel_error = norm_error / norm_exact; 17677841947SLeila Ghaffari 17777841947SLeila Ghaffari // Output relative error 17877841947SLeila Ghaffari ierr = PetscPrintf(PETSC_COMM_WORLD, 17977841947SLeila Ghaffari "Relative Error: %g\n", 18077841947SLeila Ghaffari (double)rel_error); CHKERRQ(ierr); 18177841947SLeila Ghaffari // Cleanup 18277841947SLeila Ghaffari ierr = DMRestoreLocalVector(dm, &Q_exact_loc); CHKERRQ(ierr); 18377841947SLeila Ghaffari ierr = VecDestroy(&Q_exact); CHKERRQ(ierr); 18477841947SLeila Ghaffari 18577841947SLeila Ghaffari PetscFunctionReturn(0); 18677841947SLeila Ghaffari } 18777841947SLeila Ghaffari 18877841947SLeila Ghaffari // Post-processing 18977841947SLeila Ghaffari PetscErrorCode PostProcess_NS(TS ts, CeedData ceed_data, DM dm, 190*841e4c73SJed Brown ProblemData *problem, User user, 19177841947SLeila Ghaffari Vec Q, PetscScalar final_time) { 19277841947SLeila Ghaffari PetscInt steps; 19377841947SLeila Ghaffari PetscErrorCode ierr; 19477841947SLeila Ghaffari PetscFunctionBegin; 19577841947SLeila Ghaffari 19677841947SLeila Ghaffari // Print relative error 197*841e4c73SJed Brown if (problem->non_zero_time && !user->app_ctx->test_mode) { 198*841e4c73SJed Brown ierr = GetError_NS(ceed_data, dm, user, Q, final_time); CHKERRQ(ierr); 19977841947SLeila Ghaffari } 20077841947SLeila Ghaffari 20177841947SLeila Ghaffari // Print final time and number of steps 20277841947SLeila Ghaffari ierr = TSGetStepNumber(ts, &steps); CHKERRQ(ierr); 203*841e4c73SJed Brown if (!user->app_ctx->test_mode) { 20477841947SLeila Ghaffari ierr = PetscPrintf(PETSC_COMM_WORLD, 20508140895SJed Brown "Time integrator took %" PetscInt_FMT " time steps to reach final time %g\n", 20677841947SLeila Ghaffari steps, (double)final_time); CHKERRQ(ierr); 20777841947SLeila Ghaffari } 20877841947SLeila Ghaffari 20977841947SLeila Ghaffari // Output numerical values from command line 21077841947SLeila Ghaffari ierr = VecViewFromOptions(Q, NULL, "-vec_view"); CHKERRQ(ierr); 21177841947SLeila Ghaffari 21277841947SLeila Ghaffari // Compare reference solution values with current test run for CI 213*841e4c73SJed Brown if (user->app_ctx->test_mode) { 214*841e4c73SJed Brown ierr = RegressionTests_NS(user->app_ctx, Q); CHKERRQ(ierr); 21577841947SLeila Ghaffari } 21677841947SLeila Ghaffari 21777841947SLeila Ghaffari PetscFunctionReturn(0); 21877841947SLeila Ghaffari } 21977841947SLeila Ghaffari 22077841947SLeila Ghaffari // Gather initial Q values in case of continuation of simulation 22177841947SLeila Ghaffari PetscErrorCode SetupICsFromBinary(MPI_Comm comm, AppCtx app_ctx, Vec Q) { 22277841947SLeila Ghaffari 22377841947SLeila Ghaffari PetscViewer viewer; 22477841947SLeila Ghaffari char file_path[PETSC_MAX_PATH_LEN]; 22577841947SLeila Ghaffari PetscErrorCode ierr; 22677841947SLeila Ghaffari PetscFunctionBegin; 22777841947SLeila Ghaffari 22877841947SLeila Ghaffari // Read input 22977841947SLeila Ghaffari ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-solution.bin", 23077841947SLeila Ghaffari app_ctx->output_dir); CHKERRQ(ierr); 23177841947SLeila Ghaffari ierr = PetscViewerBinaryOpen(comm, file_path, FILE_MODE_READ, &viewer); 23277841947SLeila Ghaffari CHKERRQ(ierr); 23377841947SLeila Ghaffari 23477841947SLeila Ghaffari // Load Q from existent solution 23577841947SLeila Ghaffari ierr = VecLoad(Q, viewer); CHKERRQ(ierr); 23677841947SLeila Ghaffari 23777841947SLeila Ghaffari // Cleanup 23877841947SLeila Ghaffari ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr); 23977841947SLeila Ghaffari 24077841947SLeila Ghaffari PetscFunctionReturn(0); 24177841947SLeila Ghaffari } 24277841947SLeila Ghaffari 24377841947SLeila Ghaffari // Record boundary values from initial condition 24477841947SLeila Ghaffari PetscErrorCode SetBCsFromICs_NS(DM dm, Vec Q, Vec Q_loc) { 24577841947SLeila Ghaffari 24677841947SLeila Ghaffari Vec Qbc; 24777841947SLeila Ghaffari PetscErrorCode ierr; 24877841947SLeila Ghaffari PetscFunctionBegin; 24977841947SLeila Ghaffari 25077841947SLeila Ghaffari ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr); 25177841947SLeila Ghaffari ierr = VecCopy(Q_loc, Qbc); CHKERRQ(ierr); 25277841947SLeila Ghaffari ierr = VecZeroEntries(Q_loc); CHKERRQ(ierr); 25377841947SLeila Ghaffari ierr = DMGlobalToLocal(dm, Q, INSERT_VALUES, Q_loc); CHKERRQ(ierr); 25477841947SLeila Ghaffari ierr = VecAXPY(Qbc, -1., Q_loc); CHKERRQ(ierr); 25577841947SLeila Ghaffari ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr); 25677841947SLeila Ghaffari ierr = PetscObjectComposeFunction((PetscObject)dm, 25777841947SLeila Ghaffari "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_NS); 25877841947SLeila Ghaffari CHKERRQ(ierr); 25977841947SLeila Ghaffari 26077841947SLeila Ghaffari PetscFunctionReturn(0); 26177841947SLeila Ghaffari } 262*841e4c73SJed Brown 263*841e4c73SJed Brown // Free a plain data context that was allocated using PETSc; returning libCEED error codes 264*841e4c73SJed Brown int FreeContextPetsc(void *data) { 265*841e4c73SJed Brown if (PetscFree(data)) return CeedError(NULL, CEED_ERROR_ACCESS, 266*841e4c73SJed Brown "PetscFree failed"); 267*841e4c73SJed Brown return CEED_ERROR_SUCCESS; 268*841e4c73SJed Brown } 269