xref: /honee/src/misc.c (revision 727da7e70824329c32c70307643ee0d0901369c8)
1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED:  http://github.com/ceed
7 
8 /// @file
9 /// Miscellaneous utility functions
10 
11 #include "../navierstokes.h"
12 
13 PetscErrorCode ICs_FixMultiplicity(DM dm, CeedData ceed_data, Vec Q_loc, Vec Q,
14                                    CeedScalar time) {
15   PetscErrorCode ierr;
16   PetscFunctionBeginUser;
17 
18   // ---------------------------------------------------------------------------
19   // Update SetupContext
20   // ---------------------------------------------------------------------------
21   SetupContext setup_ctx;
22   CeedQFunctionContextGetData(ceed_data->setup_context, CEED_MEM_HOST,
23                               (void **)&setup_ctx);
24   setup_ctx->time = time;
25   CeedQFunctionContextRestoreData(ceed_data->setup_context, (void **)&setup_ctx);
26 
27   // ---------------------------------------------------------------------------
28   // ICs
29   // ---------------------------------------------------------------------------
30   // -- CEED Restriction
31   CeedVector q0_ceed;
32   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &q0_ceed, NULL);
33 
34   // -- Place PETSc vector in CEED vector
35   CeedScalar *q0;
36   PetscMemType q0_mem_type;
37   ierr = VecGetArrayAndMemType(Q_loc, (PetscScalar **)&q0, &q0_mem_type);
38   CHKERRQ(ierr);
39   CeedVectorSetArray(q0_ceed, MemTypeP2C(q0_mem_type), CEED_USE_POINTER, q0);
40 
41   // -- Apply CEED Operator
42   CeedOperatorApply(ceed_data->op_ics, ceed_data->x_coord, q0_ceed,
43                     CEED_REQUEST_IMMEDIATE);
44 
45   // -- Restore vectors
46   CeedVectorTakeArray(q0_ceed, MemTypeP2C(q0_mem_type), NULL);
47   ierr = VecRestoreArrayReadAndMemType(Q_loc, (const PetscScalar **)&q0);
48   CHKERRQ(ierr);
49 
50   // -- Local-to-Global
51   ierr = VecZeroEntries(Q); CHKERRQ(ierr);
52   ierr = DMLocalToGlobal(dm, Q_loc, ADD_VALUES, Q); CHKERRQ(ierr);
53 
54   // ---------------------------------------------------------------------------
55   // Fix multiplicity for output of ICs
56   // ---------------------------------------------------------------------------
57   // -- CEED Restriction
58   CeedVector mult_vec;
59   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &mult_vec, NULL);
60 
61   // -- Place PETSc vector in CEED vector
62   CeedScalar *mult;
63   PetscMemType m_mem_type;
64   Vec multiplicity_loc;
65   ierr = DMGetLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr);
66   ierr = VecGetArrayAndMemType(multiplicity_loc, (PetscScalar **)&mult,
67                                &m_mem_type);
68   CHKERRQ(ierr);
69   CeedVectorSetArray(mult_vec, MemTypeP2C(m_mem_type), CEED_USE_POINTER, mult);
70   CHKERRQ(ierr);
71 
72   // -- Get multiplicity
73   CeedElemRestrictionGetMultiplicity(ceed_data->elem_restr_q, mult_vec);
74 
75   // -- Restore vectors
76   CeedVectorTakeArray(mult_vec, MemTypeP2C(m_mem_type), NULL);
77   ierr = VecRestoreArrayReadAndMemType(multiplicity_loc,
78                                        (const PetscScalar **)&mult); CHKERRQ(ierr);
79 
80   // -- Local-to-Global
81   Vec multiplicity;
82   ierr = DMGetGlobalVector(dm, &multiplicity); CHKERRQ(ierr);
83   ierr = VecZeroEntries(multiplicity); CHKERRQ(ierr);
84   ierr = DMLocalToGlobal(dm, multiplicity_loc, ADD_VALUES, multiplicity);
85   CHKERRQ(ierr);
86 
87   // -- Fix multiplicity
88   ierr = VecPointwiseDivide(Q, Q, multiplicity); CHKERRQ(ierr);
89   ierr = VecPointwiseDivide(Q_loc, Q_loc, multiplicity_loc); CHKERRQ(ierr);
90 
91   // -- Restore vectors
92   ierr = DMRestoreLocalVector(dm, &multiplicity_loc); CHKERRQ(ierr);
93   ierr = DMRestoreGlobalVector(dm, &multiplicity); CHKERRQ(ierr);
94 
95   // Cleanup
96   CeedVectorDestroy(&mult_vec);
97   CeedVectorDestroy(&q0_ceed);
98 
99   PetscFunctionReturn(0);
100 }
101 
102 PetscErrorCode DMPlexInsertBoundaryValues_NS(DM dm,
103     PetscBool insert_essential, Vec Q_loc, PetscReal time, Vec face_geom_FVM,
104     Vec cell_geom_FVM, Vec grad_FVM) {
105 
106   Vec            Qbc;
107   PetscErrorCode ierr;
108   PetscFunctionBegin;
109 
110   ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
111   ierr = VecAXPY(Q_loc, 1., Qbc); CHKERRQ(ierr);
112   ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
113 
114   PetscFunctionReturn(0);
115 }
116 
117 // Compare reference solution values with current test run for CI
118 PetscErrorCode RegressionTests_NS(AppCtx app_ctx, Vec Q) {
119 
120   Vec            Qref;
121   PetscViewer    viewer;
122   PetscReal      error, Qrefnorm;
123   PetscErrorCode ierr;
124   PetscFunctionBegin;
125 
126   // Read reference file
127   ierr = VecDuplicate(Q, &Qref); CHKERRQ(ierr);
128   ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)Q),
129                                app_ctx->file_path, FILE_MODE_READ,
130                                &viewer); CHKERRQ(ierr);
131   ierr = VecLoad(Qref, viewer); CHKERRQ(ierr);
132 
133   // Compute error with respect to reference solution
134   ierr = VecAXPY(Q, -1.0, Qref); CHKERRQ(ierr);
135   ierr = VecNorm(Qref, NORM_MAX, &Qrefnorm); CHKERRQ(ierr);
136   ierr = VecScale(Q, 1./Qrefnorm); CHKERRQ(ierr);
137   ierr = VecNorm(Q, NORM_MAX, &error); CHKERRQ(ierr);
138 
139   // Check error
140   if (error > app_ctx->test_tol) {
141     ierr = PetscPrintf(PETSC_COMM_WORLD,
142                        "Test failed with error norm %g\n",
143                        (double)error); CHKERRQ(ierr);
144   }
145 
146   // Cleanup
147   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
148   ierr = VecDestroy(&Qref); CHKERRQ(ierr);
149 
150   PetscFunctionReturn(0);
151 }
152 
153 // Get error for problems with exact solutions
154 PetscErrorCode GetError_NS(CeedData ceed_data, DM dm, AppCtx app_ctx, Vec Q,
155                            PetscScalar final_time) {
156   PetscInt       loc_nodes;
157   Vec            Q_exact, Q_exact_loc;
158   PetscReal      rel_error, norm_error, norm_exact;
159   PetscErrorCode ierr;
160   PetscFunctionBegin;
161 
162   // Get exact solution at final time
163   ierr = DMCreateGlobalVector(dm, &Q_exact); CHKERRQ(ierr);
164   ierr = DMGetLocalVector(dm, &Q_exact_loc); CHKERRQ(ierr);
165   ierr = VecGetSize(Q_exact_loc, &loc_nodes); CHKERRQ(ierr);
166   ierr = ICs_FixMultiplicity(dm, ceed_data, Q_exact_loc, Q_exact, final_time);
167   CHKERRQ(ierr);
168 
169   // Get |exact solution - obtained solution|
170   ierr = VecNorm(Q_exact, NORM_1, &norm_exact); CHKERRQ(ierr);
171   ierr = VecAXPY(Q, -1.0, Q_exact);  CHKERRQ(ierr);
172   ierr = VecNorm(Q, NORM_1, &norm_error); CHKERRQ(ierr);
173 
174   // Compute relative error
175   rel_error = norm_error / norm_exact;
176 
177   // Output relative error
178   ierr = PetscPrintf(PETSC_COMM_WORLD,
179                      "Relative Error: %g\n",
180                      (double)rel_error); CHKERRQ(ierr);
181   // Cleanup
182   ierr = DMRestoreLocalVector(dm, &Q_exact_loc); CHKERRQ(ierr);
183   ierr = VecDestroy(&Q_exact); CHKERRQ(ierr);
184 
185   PetscFunctionReturn(0);
186 }
187 
188 // Post-processing
189 PetscErrorCode PostProcess_NS(TS ts, CeedData ceed_data, DM dm,
190                               ProblemData *problem, AppCtx app_ctx,
191                               Vec Q, PetscScalar final_time) {
192   PetscInt       steps;
193   PetscErrorCode ierr;
194   PetscFunctionBegin;
195 
196   // Print relative error
197   if (problem->non_zero_time && !app_ctx->test_mode) {
198     ierr = GetError_NS(ceed_data, dm, app_ctx, Q, final_time); CHKERRQ(ierr);
199   }
200 
201   // Print final time and number of steps
202   ierr = TSGetStepNumber(ts, &steps); CHKERRQ(ierr);
203   if (!app_ctx->test_mode) {
204     ierr = PetscPrintf(PETSC_COMM_WORLD,
205                        "Time integrator took %D time steps to reach final time %g\n",
206                        steps, (double)final_time); CHKERRQ(ierr);
207   }
208 
209   // Output numerical values from command line
210   ierr = VecViewFromOptions(Q, NULL, "-vec_view"); CHKERRQ(ierr);
211 
212   // Compare reference solution values with current test run for CI
213   if (app_ctx->test_mode) {
214     ierr = RegressionTests_NS(app_ctx, Q); CHKERRQ(ierr);
215   }
216 
217   PetscFunctionReturn(0);
218 }
219 
220 // Gather initial Q values in case of continuation of simulation
221 PetscErrorCode SetupICsFromBinary(MPI_Comm comm, AppCtx app_ctx, Vec Q) {
222 
223   PetscViewer    viewer;
224   char           file_path[PETSC_MAX_PATH_LEN];
225   PetscErrorCode ierr;
226   PetscFunctionBegin;
227 
228   // Read input
229   ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-solution.bin",
230                        app_ctx->output_dir); CHKERRQ(ierr);
231   ierr = PetscViewerBinaryOpen(comm, file_path, FILE_MODE_READ, &viewer);
232   CHKERRQ(ierr);
233 
234   // Load Q from existent solution
235   ierr = VecLoad(Q, viewer); CHKERRQ(ierr);
236 
237   // Cleanup
238   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
239 
240   PetscFunctionReturn(0);
241 }
242 
243 // Record boundary values from initial condition
244 PetscErrorCode SetBCsFromICs_NS(DM dm, Vec Q, Vec Q_loc) {
245 
246   Vec            Qbc;
247   PetscErrorCode ierr;
248   PetscFunctionBegin;
249 
250   ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
251   ierr = VecCopy(Q_loc, Qbc); CHKERRQ(ierr);
252   ierr = VecZeroEntries(Q_loc); CHKERRQ(ierr);
253   ierr = DMGlobalToLocal(dm, Q, INSERT_VALUES, Q_loc); CHKERRQ(ierr);
254   ierr = VecAXPY(Qbc, -1., Q_loc); CHKERRQ(ierr);
255   ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
256   ierr = PetscObjectComposeFunction((PetscObject)dm,
257                                     "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_NS);
258   CHKERRQ(ierr);
259 
260   PetscFunctionReturn(0);
261 }
262