xref: /libCEED/examples/fluids/src/misc.c (revision 841e4c7362a2acf3a6f116f4961b1eb52fa410fc)
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