xref: /honee/src/monitor_totalkineticenergy.c (revision 25125139fdc4964835f5c559770e5027599868dc)
1*25125139SJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2*25125139SJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
3*25125139SJames Wright 
4*25125139SJames Wright #include "../qfunctions/monitor_totalkineticenergy.h"
5*25125139SJames Wright #include <navierstokes.h>
6*25125139SJames Wright #include <time.h>
7*25125139SJames Wright 
8*25125139SJames Wright typedef struct {
9*25125139SJames Wright   OperatorApplyContext op_monitor_ctx;
10*25125139SJames Wright   Vec                  values;
11*25125139SJames Wright   PetscScalar         *sum_values;
12*25125139SJames Wright   PetscScalar          volume;
13*25125139SJames Wright   PetscInt             num_comps;
14*25125139SJames Wright   PetscBool            is_header_written;
15*25125139SJames Wright } *MonitorDissipation;
16*25125139SJames Wright 
17*25125139SJames Wright PetscErrorCode MonitorDissipationDestroy(void **ctx) {
18*25125139SJames Wright   MonitorDissipation monitor_ctx = *(MonitorDissipation *)ctx;
19*25125139SJames Wright 
20*25125139SJames Wright   PetscFunctionBeginUser;
21*25125139SJames Wright   PetscCall(OperatorApplyContextDestroy(monitor_ctx->op_monitor_ctx));
22*25125139SJames Wright   PetscCall(VecDestroy(&monitor_ctx->values));
23*25125139SJames Wright   PetscCall(PetscFree(monitor_ctx->sum_values));
24*25125139SJames Wright   PetscCall(PetscFree(monitor_ctx));
25*25125139SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
26*25125139SJames Wright }
27*25125139SJames Wright 
28*25125139SJames Wright /** @brief Create CeedElemRestriction for collocated data in component-major order.
29*25125139SJames Wright a. Sets the strides of the restriction to component-major order
30*25125139SJames Wright  Number of quadrature points is used from the CeedBasis, and number of elements is used from the CeedElemRestriction.
31*25125139SJames Wright */
32*25125139SJames Wright static PetscErrorCode CreateElemRestrColloc_CompMajor(Ceed ceed, CeedInt num_comp, CeedBasis basis, CeedElemRestriction elem_restr_base,
33*25125139SJames Wright                                                       CeedElemRestriction *elem_restr_collocated) {
34*25125139SJames Wright   CeedInt num_elem_qpts, loc_num_elem;
35*25125139SJames Wright 
36*25125139SJames Wright   PetscFunctionBeginUser;
37*25125139SJames Wright   PetscCallCeed(ceed, CeedBasisGetNumQuadraturePoints(basis, &num_elem_qpts));
38*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionGetNumElements(elem_restr_base, &loc_num_elem));
39*25125139SJames Wright 
40*25125139SJames Wright   const CeedInt strides[] = {num_comp, 1, num_elem_qpts * num_comp};
41*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionCreateStrided(ceed, loc_num_elem, num_elem_qpts, num_comp, num_comp * loc_num_elem * num_elem_qpts, strides,
42*25125139SJames Wright                                                        elem_restr_collocated));
43*25125139SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
44*25125139SJames Wright }
45*25125139SJames Wright 
46*25125139SJames Wright PetscErrorCode SetupMontiorTotalKineticEnergy(TS ts, PetscViewerAndFormat *ctx) {
47*25125139SJames Wright   Honee                honee;
48*25125139SJames Wright   Ceed                 ceed;
49*25125139SJames Wright   CeedQFunction        qf_monitor;
50*25125139SJames Wright   CeedOperator         op_monitor;
51*25125139SJames Wright   CeedElemRestriction  elem_restr_qd, elem_restr_totalke, elem_restr_q;
52*25125139SJames Wright   CeedBasis            basis_q;
53*25125139SJames Wright   CeedVector           q_data;
54*25125139SJames Wright   CeedInt              num_comp_q, q_data_size;
55*25125139SJames Wright   DMLabel              domain_label = NULL;
56*25125139SJames Wright   PetscInt             label_value = 0, num_comp_totalke = 5, dim;
57*25125139SJames Wright   MonitorDissipation   monitor_ctx;
58*25125139SJames Wright   CeedQFunctionContext newt_qfctx;
59*25125139SJames Wright   PetscBool            is_ascii;
60*25125139SJames Wright 
61*25125139SJames Wright   PetscFunctionBeginUser;
62*25125139SJames Wright   PetscCall(PetscObjectTypeCompare((PetscObject)ctx->viewer, PETSCVIEWERASCII, &is_ascii));
63*25125139SJames Wright   PetscCheck(is_ascii, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only supports ASCII viewers");
64*25125139SJames Wright   PetscCall(TSGetApplicationContext(ts, &honee));
65*25125139SJames Wright   PetscCall(DMGetDimension(honee->dm, &dim));
66*25125139SJames Wright   ceed = honee->ceed;
67*25125139SJames Wright 
68*25125139SJames Wright   PetscCall(PetscNew(&monitor_ctx));
69*25125139SJames Wright   PetscCall(HoneeCalculateDomainSize(honee, &monitor_ctx->volume));
70*25125139SJames Wright 
71*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionGetNumComponents(honee->elem_restr_q, &num_comp_q));
72*25125139SJames Wright   PetscCall(QDataGet(ceed, honee->dm, domain_label, label_value, honee->elem_restr_x, honee->basis_x, honee->x_coord, &elem_restr_qd, &q_data,
73*25125139SJames Wright                      &q_data_size));
74*25125139SJames Wright 
75*25125139SJames Wright   {  // Get restriction and basis from the RHS function
76*25125139SJames Wright     CeedOperator     *sub_ops;
77*25125139SJames Wright     CeedOperatorField op_field;
78*25125139SJames Wright     PetscInt          sub_op_index = 0;  // will be 0 for the volume op
79*25125139SJames Wright 
80*25125139SJames Wright     PetscCallCeed(ceed, CeedCompositeOperatorGetSubList(honee->op_rhs_ctx->op, &sub_ops));
81*25125139SJames Wright     PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_ops[sub_op_index], "q", &op_field));
82*25125139SJames Wright 
83*25125139SJames Wright     PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_q, &basis_q, NULL));
84*25125139SJames Wright     PetscCallCeed(ceed, CeedOperatorGetContext(sub_ops[sub_op_index], &newt_qfctx));
85*25125139SJames Wright   }
86*25125139SJames Wright   PetscCall(CreateElemRestrColloc_CompMajor(ceed, num_comp_totalke, basis_q, elem_restr_q, &elem_restr_totalke));
87*25125139SJames Wright 
88*25125139SJames Wright   switch (honee->phys->state_var) {
89*25125139SJames Wright     case STATEVAR_PRIMITIVE:
90*25125139SJames Wright       PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Prim, MonitorTotalKineticEnergy_Prim_loc, &qf_monitor));
91*25125139SJames Wright       break;
92*25125139SJames Wright     case STATEVAR_CONSERVATIVE:
93*25125139SJames Wright       PetscCallCeed(ceed,
94*25125139SJames Wright                     CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Conserv, MonitorTotalKineticEnergy_Conserv_loc, &qf_monitor));
95*25125139SJames Wright       break;
96*25125139SJames Wright     case STATEVAR_ENTROPY:
97*25125139SJames Wright       PetscCallCeed(ceed,
98*25125139SJames Wright                     CeedQFunctionCreateInterior(ceed, 1, MonitorTotalKineticEnergy_Entropy, MonitorTotalKineticEnergy_Entropy_loc, &qf_monitor));
99*25125139SJames Wright       break;
100*25125139SJames Wright   }
101*25125139SJames Wright 
102*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionSetContext(qf_monitor, newt_qfctx));
103*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q", num_comp_q, CEED_EVAL_INTERP));
104*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "Grad_q", num_comp_q * dim, CEED_EVAL_GRAD));
105*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionAddInput(qf_monitor, "q_data", q_data_size, CEED_EVAL_NONE));
106*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionAddOutput(qf_monitor, "v", num_comp_totalke, CEED_EVAL_NONE));
107*25125139SJames Wright 
108*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_monitor, NULL, NULL, &op_monitor));
109*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
110*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
111*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "q_data", elem_restr_qd, CEED_BASIS_NONE, q_data));
112*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorSetField(op_monitor, "v", elem_restr_totalke, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE));
113*25125139SJames Wright 
114*25125139SJames Wright   PetscCall(OperatorApplyContextCreate(honee->dm, NULL, ceed, op_monitor, NULL, NULL, NULL, NULL, &monitor_ctx->op_monitor_ctx));
115*25125139SJames Wright 
116*25125139SJames Wright   PetscCall(CeedOperatorCreateLocalVecs(op_monitor, DMReturnVecType(honee->dm), PETSC_COMM_SELF, NULL, &monitor_ctx->values));
117*25125139SJames Wright   PetscCall(VecSetBlockSize(monitor_ctx->values, num_comp_totalke));
118*25125139SJames Wright   monitor_ctx->num_comps = num_comp_totalke;
119*25125139SJames Wright   PetscCall(PetscMalloc1(num_comp_totalke, &monitor_ctx->sum_values));
120*25125139SJames Wright 
121*25125139SJames Wright   ctx->data         = monitor_ctx;
122*25125139SJames Wright   ctx->data_destroy = MonitorDissipationDestroy;
123*25125139SJames Wright 
124*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionContextDestroy(&newt_qfctx));
125*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd));
126*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q));
127*25125139SJames Wright   PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_totalke));
128*25125139SJames Wright   PetscCallCeed(ceed, CeedBasisDestroy(&basis_q));
129*25125139SJames Wright   PetscCallCeed(ceed, CeedVectorDestroy(&q_data));
130*25125139SJames Wright   PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_monitor));
131*25125139SJames Wright   PetscCallCeed(ceed, CeedOperatorDestroy(&op_monitor));
132*25125139SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
133*25125139SJames Wright }
134*25125139SJames Wright 
135*25125139SJames Wright PetscErrorCode TSMonitor_TotalKineticEnergy(TS ts, PetscInt step, PetscReal solution_time, Vec Q, PetscViewerAndFormat *ctx) {
136*25125139SJames Wright   MonitorDissipation monitor_ctx = (MonitorDissipation)ctx->data;
137*25125139SJames Wright   Honee              honee;
138*25125139SJames Wright   MPI_Comm           comm;
139*25125139SJames Wright   PetscMPIInt        rank;
140*25125139SJames Wright   TSConvergedReason  reason;
141*25125139SJames Wright   static const char *field_names[] = {"TotalKineticEnergy", "StrainDissipation", "DivergenceDissipation", "VolumeExpansion", "MuVorticity2"};
142*25125139SJames Wright 
143*25125139SJames Wright   PetscFunctionBeginUser;
144*25125139SJames Wright   PetscCall(TSGetConvergedReason(ts, &reason));
145*25125139SJames Wright   if (!(step % ctx->view_interval == 0 || reason != TS_CONVERGED_ITERATING)) PetscFunctionReturn(PETSC_SUCCESS);
146*25125139SJames Wright   PetscCall(TSGetApplicationContext(ts, &honee));
147*25125139SJames Wright   PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
148*25125139SJames Wright   PetscCallMPI(MPI_Comm_rank(comm, &rank));
149*25125139SJames Wright 
150*25125139SJames Wright   PetscCall(UpdateBoundaryValues(honee, honee->Q_loc, solution_time));
151*25125139SJames Wright   PetscCall(DMGlobalToLocal(honee->dm, Q, INSERT_VALUES, honee->Q_loc));
152*25125139SJames Wright 
153*25125139SJames Wright   PetscCall(ApplyCeedOperatorLocalToLocal(honee->Q_loc, monitor_ctx->values, monitor_ctx->op_monitor_ctx));
154*25125139SJames Wright 
155*25125139SJames Wright   for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) {
156*25125139SJames Wright     PetscCall(VecStrideSum(monitor_ctx->values, i, &monitor_ctx->sum_values[i]));
157*25125139SJames Wright   }
158*25125139SJames Wright 
159*25125139SJames Wright   if (rank == 0) PetscCallMPI(MPI_Reduce(MPI_IN_PLACE, monitor_ctx->sum_values, monitor_ctx->num_comps, MPIU_SCALAR, MPI_SUM, 0, comm));
160*25125139SJames Wright   else PetscCallMPI(MPI_Reduce(monitor_ctx->sum_values, monitor_ctx->sum_values, monitor_ctx->num_comps, MPIU_SCALAR, MPI_SUM, 0, comm));
161*25125139SJames Wright 
162*25125139SJames Wright   if (rank == 0)
163*25125139SJames Wright     for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) monitor_ctx->sum_values[i] /= monitor_ctx->volume;
164*25125139SJames Wright 
165*25125139SJames Wright   if (ctx->format == PETSC_VIEWER_ASCII_CSV) {
166*25125139SJames Wright     if (!monitor_ctx->is_header_written) {
167*25125139SJames Wright       char        buf[PETSC_MAX_PATH_LEN];
168*25125139SJames Wright       const char *buf_const;
169*25125139SJames Wright       time_t      t = time(NULL);
170*25125139SJames Wright 
171*25125139SJames Wright       PetscCall(PetscGetVersion(buf, sizeof(buf)));
172*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_version: %s\n", buf));
173*25125139SJames Wright       PetscCall(PetscGetPetscDir(&buf_const));
174*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_directory: %s\n", buf_const));
175*25125139SJames Wright       PetscCall(PetscGetArchType(buf, sizeof(buf)));
176*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# petsc_arch: %s\n", buf));
177*25125139SJames Wright       if (strftime(buf, sizeof(buf), "%FT%T%z", localtime(&t)) == 0) SETERRQ(comm, PETSC_ERR_SYS, "strftime() call failed");
178*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date: %s\n", buf));
179*25125139SJames Wright       if (strftime(buf, sizeof(buf), "%Z", localtime(&t)) == 0) SETERRQ(comm, PETSC_ERR_SYS, "strftime() call failed");
180*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# date_timezone: %s\n", buf));
181*25125139SJames Wright       PetscCall(PetscGetUserName(buf, sizeof(buf)));
182*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# username: %s\n", buf));
183*25125139SJames Wright       PetscCall(PetscGetHostName(buf, sizeof(buf)));
184*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# hostname: %s\n", buf));
185*25125139SJames Wright       PetscCall(PetscGetWorkingDirectory(buf, sizeof(buf)));
186*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# working_directory: %s\n", buf));
187*25125139SJames Wright 
188*25125139SJames Wright       PetscCall(PetscViewerFileGetName(ctx->viewer, &buf_const));
189*25125139SJames Wright       PetscCall(PetscGetFullPath(buf_const, buf, sizeof(buf)));
190*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "# original_file_path: %s\n", buf));
191*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "#\n"));
192*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "step,time,"));
193*25125139SJames Wright       for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) {
194*25125139SJames Wright         PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%s", field_names[i]));
195*25125139SJames Wright         if (i < monitor_ctx->num_comps - 1) PetscCall(PetscViewerASCIIPrintf(ctx->viewer, ","));
196*25125139SJames Wright       }
197*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n"));
198*25125139SJames Wright       monitor_ctx->is_header_written = PETSC_TRUE;
199*25125139SJames Wright     }
200*25125139SJames Wright 
201*25125139SJames Wright     PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%" PetscInt_FMT ",%0.17e,", step, solution_time));
202*25125139SJames Wright     for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) {
203*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%0.17e", monitor_ctx->sum_values[i]));
204*25125139SJames Wright       if (i < monitor_ctx->num_comps - 1) PetscCall(PetscViewerASCIIPrintf(ctx->viewer, ","));
205*25125139SJames Wright     }
206*25125139SJames Wright     PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n"));
207*25125139SJames Wright   } else {
208*25125139SJames Wright     for (PetscInt i = 0; i < monitor_ctx->num_comps; i++) {
209*25125139SJames Wright       PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "%s: %0.12e ", field_names[i], monitor_ctx->sum_values[i]));
210*25125139SJames Wright     }
211*25125139SJames Wright     PetscScalar sum_rates = 0;
212*25125139SJames Wright     for (PetscInt i = 1; i < monitor_ctx->num_comps - 1; i++) sum_rates += monitor_ctx->sum_values[i];
213*25125139SJames Wright     PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "SumOfRates: %0.12e ", sum_rates));
214*25125139SJames Wright     PetscCall(PetscViewerASCIIPrintf(ctx->viewer, "\n"));
215*25125139SJames Wright   }
216*25125139SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
217*25125139SJames Wright }
218