xref: /libCEED/examples/fluids/src/misc.c (revision 0814089585cdf806de225f3491b42521824423b0) !
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 
1377841947SLeila Ghaffari PetscErrorCode ICs_FixMultiplicity(DM dm, CeedData ceed_data, Vec Q_loc, Vec Q,
1477841947SLeila Ghaffari                                    CeedScalar time) {
1577841947SLeila Ghaffari   PetscErrorCode ierr;
1677841947SLeila Ghaffari   PetscFunctionBeginUser;
1777841947SLeila Ghaffari 
1877841947SLeila Ghaffari   // ---------------------------------------------------------------------------
1977841947SLeila Ghaffari   // Update SetupContext
2077841947SLeila Ghaffari   // ---------------------------------------------------------------------------
2177841947SLeila Ghaffari   SetupContext setup_ctx;
2277841947SLeila Ghaffari   CeedQFunctionContextGetData(ceed_data->setup_context, CEED_MEM_HOST,
2377841947SLeila Ghaffari                               (void **)&setup_ctx);
2477841947SLeila Ghaffari   setup_ctx->time = time;
2577841947SLeila Ghaffari   CeedQFunctionContextRestoreData(ceed_data->setup_context, (void **)&setup_ctx);
2677841947SLeila Ghaffari 
2777841947SLeila Ghaffari   // ---------------------------------------------------------------------------
2877841947SLeila Ghaffari   // ICs
2977841947SLeila Ghaffari   // ---------------------------------------------------------------------------
3077841947SLeila Ghaffari   // -- CEED Restriction
3177841947SLeila Ghaffari   CeedVector q0_ceed;
3277841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &q0_ceed, NULL);
3377841947SLeila Ghaffari 
3477841947SLeila Ghaffari   // -- Place PETSc vector in CEED vector
3577841947SLeila Ghaffari   CeedScalar *q0;
3677841947SLeila Ghaffari   PetscMemType q0_mem_type;
3777841947SLeila Ghaffari   ierr = VecGetArrayAndMemType(Q_loc, (PetscScalar **)&q0, &q0_mem_type);
3877841947SLeila Ghaffari   CHKERRQ(ierr);
3977841947SLeila Ghaffari   CeedVectorSetArray(q0_ceed, MemTypeP2C(q0_mem_type), CEED_USE_POINTER, q0);
4077841947SLeila Ghaffari 
4177841947SLeila Ghaffari   // -- Apply CEED Operator
4277841947SLeila Ghaffari   CeedOperatorApply(ceed_data->op_ics, ceed_data->x_coord, q0_ceed,
4377841947SLeila Ghaffari                     CEED_REQUEST_IMMEDIATE);
4477841947SLeila Ghaffari 
4577841947SLeila Ghaffari   // -- Restore vectors
4677841947SLeila Ghaffari   CeedVectorTakeArray(q0_ceed, MemTypeP2C(q0_mem_type), NULL);
4777841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(Q_loc, (const PetscScalar **)&q0);
4877841947SLeila Ghaffari   CHKERRQ(ierr);
4977841947SLeila Ghaffari 
5077841947SLeila Ghaffari   // -- Local-to-Global
5177841947SLeila Ghaffari   ierr = VecZeroEntries(Q); CHKERRQ(ierr);
5277841947SLeila Ghaffari   ierr = DMLocalToGlobal(dm, Q_loc, ADD_VALUES, Q); CHKERRQ(ierr);
5377841947SLeila Ghaffari 
5477841947SLeila Ghaffari   // ---------------------------------------------------------------------------
5577841947SLeila Ghaffari   // Fix multiplicity for output of ICs
5677841947SLeila Ghaffari   // ---------------------------------------------------------------------------
5777841947SLeila Ghaffari   // -- CEED Restriction
5877841947SLeila Ghaffari   CeedVector mult_vec;
5977841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &mult_vec, NULL);
6077841947SLeila Ghaffari 
6177841947SLeila Ghaffari   // -- Place PETSc vector in CEED vector
6277841947SLeila Ghaffari   CeedScalar *mult;
6377841947SLeila Ghaffari   PetscMemType m_mem_type;
6477841947SLeila Ghaffari   Vec multiplicity_loc;
6577841947SLeila Ghaffari   ierr = DMGetLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr);
6677841947SLeila Ghaffari   ierr = VecGetArrayAndMemType(multiplicity_loc, (PetscScalar **)&mult,
6777841947SLeila Ghaffari                                &m_mem_type);
6877841947SLeila Ghaffari   CHKERRQ(ierr);
6977841947SLeila Ghaffari   CeedVectorSetArray(mult_vec, MemTypeP2C(m_mem_type), CEED_USE_POINTER, mult);
7077841947SLeila Ghaffari   CHKERRQ(ierr);
7177841947SLeila Ghaffari 
7277841947SLeila Ghaffari   // -- Get multiplicity
7377841947SLeila Ghaffari   CeedElemRestrictionGetMultiplicity(ceed_data->elem_restr_q, mult_vec);
7477841947SLeila Ghaffari 
7577841947SLeila Ghaffari   // -- Restore vectors
7677841947SLeila Ghaffari   CeedVectorTakeArray(mult_vec, MemTypeP2C(m_mem_type), NULL);
7777841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(multiplicity_loc,
7877841947SLeila Ghaffari                                        (const PetscScalar **)&mult); CHKERRQ(ierr);
7977841947SLeila Ghaffari 
8077841947SLeila Ghaffari   // -- Local-to-Global
8177841947SLeila Ghaffari   Vec multiplicity;
8277841947SLeila Ghaffari   ierr = DMGetGlobalVector(dm, &multiplicity); CHKERRQ(ierr);
8377841947SLeila Ghaffari   ierr = VecZeroEntries(multiplicity); CHKERRQ(ierr);
8477841947SLeila Ghaffari   ierr = DMLocalToGlobal(dm, multiplicity_loc, ADD_VALUES, multiplicity);
8577841947SLeila Ghaffari   CHKERRQ(ierr);
8677841947SLeila Ghaffari 
8777841947SLeila Ghaffari   // -- Fix multiplicity
8877841947SLeila Ghaffari   ierr = VecPointwiseDivide(Q, Q, multiplicity); CHKERRQ(ierr);
8977841947SLeila Ghaffari   ierr = VecPointwiseDivide(Q_loc, Q_loc, multiplicity_loc); CHKERRQ(ierr);
9077841947SLeila Ghaffari 
9177841947SLeila Ghaffari   // -- Restore vectors
9277841947SLeila Ghaffari   ierr = DMRestoreLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr);
9377841947SLeila Ghaffari   ierr = DMRestoreGlobalVector(dm, &multiplicity); CHKERRQ(ierr);
9477841947SLeila Ghaffari 
9577841947SLeila Ghaffari   // Cleanup
9677841947SLeila Ghaffari   CeedVectorDestroy(&mult_vec);
9777841947SLeila Ghaffari   CeedVectorDestroy(&q0_ceed);
9877841947SLeila Ghaffari 
9977841947SLeila Ghaffari   PetscFunctionReturn(0);
10077841947SLeila Ghaffari }
10177841947SLeila Ghaffari 
10277841947SLeila Ghaffari PetscErrorCode DMPlexInsertBoundaryValues_NS(DM dm,
10377841947SLeila Ghaffari     PetscBool insert_essential, Vec Q_loc, PetscReal time, Vec face_geom_FVM,
10477841947SLeila Ghaffari     Vec cell_geom_FVM, Vec grad_FVM) {
10577841947SLeila Ghaffari 
10677841947SLeila Ghaffari   Vec            Qbc;
10777841947SLeila Ghaffari   PetscErrorCode ierr;
10877841947SLeila Ghaffari   PetscFunctionBegin;
10977841947SLeila Ghaffari 
11077841947SLeila Ghaffari   ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
11177841947SLeila Ghaffari   ierr = VecAXPY(Q_loc, 1., Qbc); CHKERRQ(ierr);
11277841947SLeila Ghaffari   ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
11377841947SLeila Ghaffari 
11477841947SLeila Ghaffari   PetscFunctionReturn(0);
11577841947SLeila Ghaffari }
11677841947SLeila Ghaffari 
11777841947SLeila Ghaffari // Compare reference solution values with current test run for CI
11877841947SLeila Ghaffari PetscErrorCode RegressionTests_NS(AppCtx app_ctx, Vec Q) {
11977841947SLeila Ghaffari 
12077841947SLeila Ghaffari   Vec            Qref;
12177841947SLeila Ghaffari   PetscViewer    viewer;
12277841947SLeila Ghaffari   PetscReal      error, Qrefnorm;
12377841947SLeila Ghaffari   PetscErrorCode ierr;
12477841947SLeila Ghaffari   PetscFunctionBegin;
12577841947SLeila Ghaffari 
12677841947SLeila Ghaffari   // Read reference file
12777841947SLeila Ghaffari   ierr = VecDuplicate(Q, &Qref); CHKERRQ(ierr);
12877841947SLeila Ghaffari   ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)Q),
12977841947SLeila Ghaffari                                app_ctx->file_path, FILE_MODE_READ,
13077841947SLeila Ghaffari                                &viewer); CHKERRQ(ierr);
13177841947SLeila Ghaffari   ierr = VecLoad(Qref, viewer); CHKERRQ(ierr);
13277841947SLeila Ghaffari 
13377841947SLeila Ghaffari   // Compute error with respect to reference solution
13477841947SLeila Ghaffari   ierr = VecAXPY(Q, -1.0, Qref); CHKERRQ(ierr);
13577841947SLeila Ghaffari   ierr = VecNorm(Qref, NORM_MAX, &Qrefnorm); CHKERRQ(ierr);
13677841947SLeila Ghaffari   ierr = VecScale(Q, 1./Qrefnorm); CHKERRQ(ierr);
13777841947SLeila Ghaffari   ierr = VecNorm(Q, NORM_MAX, &error); CHKERRQ(ierr);
13877841947SLeila Ghaffari 
13977841947SLeila Ghaffari   // Check error
14077841947SLeila Ghaffari   if (error > app_ctx->test_tol) {
14177841947SLeila Ghaffari     ierr = PetscPrintf(PETSC_COMM_WORLD,
14277841947SLeila Ghaffari                        "Test failed with error norm %g\n",
14377841947SLeila Ghaffari                        (double)error); CHKERRQ(ierr);
14477841947SLeila Ghaffari   }
14577841947SLeila Ghaffari 
14677841947SLeila Ghaffari   // Cleanup
14777841947SLeila Ghaffari   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
14877841947SLeila Ghaffari   ierr = VecDestroy(&Qref); CHKERRQ(ierr);
14977841947SLeila Ghaffari 
15077841947SLeila Ghaffari   PetscFunctionReturn(0);
15177841947SLeila Ghaffari }
15277841947SLeila Ghaffari 
15377841947SLeila Ghaffari // Get error for problems with exact solutions
15477841947SLeila Ghaffari PetscErrorCode GetError_NS(CeedData ceed_data, DM dm, AppCtx app_ctx, Vec Q,
15577841947SLeila Ghaffari                            PetscScalar final_time) {
15677841947SLeila Ghaffari   PetscInt       loc_nodes;
15777841947SLeila Ghaffari   Vec            Q_exact, Q_exact_loc;
15877841947SLeila Ghaffari   PetscReal      rel_error, norm_error, norm_exact;
15977841947SLeila Ghaffari   PetscErrorCode ierr;
16077841947SLeila Ghaffari   PetscFunctionBegin;
16177841947SLeila Ghaffari 
16277841947SLeila Ghaffari   // Get exact solution at final time
16377841947SLeila Ghaffari   ierr = DMCreateGlobalVector(dm, &Q_exact); CHKERRQ(ierr);
16477841947SLeila Ghaffari   ierr = DMGetLocalVector(dm, &Q_exact_loc); CHKERRQ(ierr);
16577841947SLeila Ghaffari   ierr = VecGetSize(Q_exact_loc, &loc_nodes); CHKERRQ(ierr);
16677841947SLeila Ghaffari   ierr = ICs_FixMultiplicity(dm, ceed_data, Q_exact_loc, Q_exact, 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,
19077841947SLeila Ghaffari                               ProblemData *problem, AppCtx app_ctx,
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
19777841947SLeila Ghaffari   if (problem->non_zero_time && !app_ctx->test_mode) {
19877841947SLeila Ghaffari     ierr = GetError_NS(ceed_data, dm, app_ctx, 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);
20377841947SLeila Ghaffari   if (!app_ctx->test_mode) {
20477841947SLeila Ghaffari     ierr = PetscPrintf(PETSC_COMM_WORLD,
205*08140895SJed 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
21377841947SLeila Ghaffari   if (app_ctx->test_mode) {
21477841947SLeila Ghaffari     ierr = RegressionTests_NS(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