CAMP 1.0.0
Chemistry Across Multiple Phases
camp_debug.h
Go to the documentation of this file.
1/* Copyright (C) 2021 Barcelona Supercomputing Center and University of
2 * Illinois at Urbana-Champaign
3 * SPDX-License-Identifier: MIT
4 *
5 * Header file with some debugging functions for use with camp_solver.c
6 *
7 */
8#ifndef CAMP_DEBUG_H
9#define CAMP_DEBUG_H
10
11// file name prefix
13
14// Maximum size of output file names
15#define MAX_FILE_NAME 256
16
17// Number of points to advance state for output
18#define N_OUTPUT_STATES 100
19
20#ifdef CAMP_DEBUG
21#define CAMP_DEBUG_SPEC_ 0
22#define CAMP_DEBUG_PRINT(x) \
23 camp_debug_print(sd->cvode_mem, x, false, 0, __LINE__, __func__)
24#define CAMP_DEBUG_PRINT_INT(x, y) \
25 camp_debug_print(sd->cvode_mem, x, false, y, __LINE__, __func__)
26#define CAMP_DEBUG_PRINT_FULL(x) \
27 camp_debug_print(sd->cvode_mem, x, true, 0, __LINE__, __func__)
28#define CAMP_DEBUG_JAC_STRUCT(J, x) \
29 camp_debug_print_jac_struct((void *)sd, J, x)
30#define CAMP_DEBUG_JAC(J, x) camp_debug_print_jac((void *)sd, J, x)
31void camp_debug_print(void *cvode_mem, const char *message, bool do_full,
32 const int int_val, const int line, const char *func) {
33#ifdef CAMP_USE_SUNDIALS
34 CVodeMem cv_mem = (CVodeMem)cvode_mem;
35 if (!(cv_mem->cv_debug_out)) return;
36 printf(
37 "\n[DEBUG] line %4d in %-20s(): %-25s %-4.0d t_n = %le h = %le q = %d "
38 "hin = %le species %d(zn[0] = %le zn[1] = %le tempv = %le tempv1 = %le "
39 "tempv2 = %le acor_init = %le last_yn = %le",
40 line, func, message, int_val, cv_mem->cv_tn, cv_mem->cv_h, cv_mem->cv_q,
41 cv_mem->cv_hin, CAMP_DEBUG_SPEC_,
42 NV_DATA_S(cv_mem->cv_zn[0])[CAMP_DEBUG_SPEC_],
43 NV_DATA_S(cv_mem->cv_zn[1])[CAMP_DEBUG_SPEC_],
44 NV_DATA_S(cv_mem->cv_tempv)[CAMP_DEBUG_SPEC_],
45 NV_DATA_S(cv_mem->cv_tempv1)[CAMP_DEBUG_SPEC_],
46 NV_DATA_S(cv_mem->cv_tempv2)[CAMP_DEBUG_SPEC_],
47 NV_DATA_S(cv_mem->cv_acor_init)[CAMP_DEBUG_SPEC_],
48 NV_DATA_S(cv_mem->cv_last_yn)[CAMP_DEBUG_SPEC_]);
49 if (do_full) {
50 for (int i = 0; i < NV_LENGTH_S(cv_mem->cv_y); i++) {
51 printf(
52 "\n zn[0][%3d] = % -le zn[1][%3d] = % -le tempv[%3d] = % -le "
53 "tempv1[%3d] = % -le tempv2[%3d] = % -le acor_init[%3d] = % -le "
54 "last_yn[%3d] = % -le",
55 i, NV_DATA_S(cv_mem->cv_zn[0])[i], i, NV_DATA_S(cv_mem->cv_zn[1])[i],
56 i, NV_DATA_S(cv_mem->cv_tempv)[i], i, NV_DATA_S(cv_mem->cv_tempv1)[i],
57 i, NV_DATA_S(cv_mem->cv_tempv2)[i], i,
58 NV_DATA_S(cv_mem->cv_acor_init)[i], i,
59 NV_DATA_S(cv_mem->cv_last_yn)[i]);
60 }
61 }
62#endif
63}
64void camp_debug_print_jac_struct(void *solver_data, SUNMatrix J,
65 const char *message) {
66#ifdef CAMP_USE_SUNDIALS
67 SolverData *sd = (SolverData *)solver_data;
68
69 if (!(sd->debug_out)) return;
70 int n_state_var = SM_COLUMNS_S(J);
71 int i_elem = 0;
72 int next_col = 0;
73 printf("\n\n Jacobian structure (↓ind →dep) - %s\n ", message);
74 for (int i_dep = 0; i_dep < n_state_var; i_dep++) printf("[%3d]", i_dep);
75 for (int i_ind = 0; i_ind < n_state_var; i_ind++) {
76 printf("\n[%3d]", i_ind);
77 next_col = SM_INDEXPTRS_S(J)[i_ind + 1];
78 for (int i_dep = 0; i_dep < n_state_var; i_dep++) {
79 if (i_dep == SM_INDEXVALS_S(J)[i_elem] && i_elem < next_col) {
80 printf(" %3d ", i_elem++);
81 } else {
82 printf(" - ");
83 }
84 }
85 }
86#endif
87}
88void camp_debug_print_jac(void *solver_data, SUNMatrix J, const char *message) {
89#ifdef CAMP_USE_SUNDIALS
90 SolverData *sd = (SolverData *)solver_data;
91
92 if (!(sd->debug_out)) return;
93 int n_state_var = SM_COLUMNS_S(J);
94 int i_elem = 0;
95 int next_col = 0;
96 printf("\n\n Jacobian (↓ind →dep) - %s\n ", message);
97 for (int i_dep = 0; i_dep < n_state_var; i_dep++)
98 printf(" [%3d]", i_dep);
99 for (int i_ind = 0; i_ind < n_state_var; i_ind++) {
100 printf("\n[%3d] ", i_ind);
101 next_col = SM_INDEXPTRS_S(J)[i_ind + 1];
102 for (int i_dep = 0; i_dep < n_state_var; i_dep++) {
103 if (i_dep == SM_INDEXVALS_S(J)[i_elem] && i_elem < next_col) {
104 printf(" % -1.2le ", SM_DATA_S(J)[i_elem++]);
105 } else {
106 printf(" - ");
107 }
108 }
109 }
110#endif
111}
112
113realtype camp_jac_elem(SUNMatrix J, unsigned int j, unsigned int i) {
114 for (int i_elem = SM_INDEXPTRS_S(J)[j]; i_elem < SM_INDEXPTRS_S(J)[j + 1];
115 ++i_elem) {
116 if (i == SM_INDEXVALS_S(J)[i_elem]) return SM_DATA_S(J)[i_elem];
117 }
118 return 0.0;
119}
120#else
121#define CAMP_DEBUG_PRINT(x)
122#define CAMP_DEBUG_PRINT_INT(x, y)
123#define CAMP_DEBUG_PRINT_FULL(x)
124#define CAMP_DEBUG_JAC_STRUCT(J, x)
125#define CAMP_DEBUG_JAC(J, x)
126#endif
127
128/** \brief Print some camp-chem data sizes
129 *
130 * \param md Pointer to the model data
131 */
132static void print_data_sizes(ModelData *md) {
133 int *ptr = md->rxn_int_data;
134 int n_rxn = ptr[0];
135
136 printf("n_rxn: %d ", n_rxn);
137 printf("n_state_var: %d", md->n_per_cell_state_var * md->n_cells);
138 printf("n_dep_var: %d", md->n_per_cell_dep_var * md->n_cells);
139}
140
141/** \brief Print Jacobian matrix in format KLU SPARSE
142 *
143 * \param M Jacobian matrix
144 */
145static void print_jacobian(SUNMatrix M) {
146 printf("\n NNZ JAC: %lld \n", (long long)SM_NNZ_S(M));
147 printf("DATA | INDEXVALS:\n");
148 for (int i = 0; i < SM_NNZ_S(M); i++) {
149 printf("% -le \n", (SM_DATA_S(M))[i]);
150 printf("%lld \n", (long long)((SM_INDEXVALS_S(M))[i]));
151 }
152 printf("PTRS:\n");
153 for (int i = 0; i <= SM_NP_S(M); i++) {
154 printf("%lld \n", (long long)((SM_INDEXPTRS_S(M))[i]));
155 }
156}
157
158/** \brief Print derivative array
159 *
160 * \param deriv Derivative array
161 */
162static void print_derivative(N_Vector deriv) {
163 // printf(" deriv length: %d\n", NV_LENGTH_S(deriv));
164 for (int i = 0; i < NV_LENGTH_S(deriv); i++) { // NV_LENGTH_S(deriv)
165 printf(" deriv: % -le", NV_DATA_S(deriv)[i]);
166 printf(" index: %d \n", i);
167 }
168}
169
170/** \brief Evaluate the derivative and Jacobian near a given state
171 * for a specified species
172 *
173 * \param curr_time Current time
174 * \param state State array
175 * \param deriv Derivative array
176 * \param solver_data Void pointer to solver data
177 * \param f Pointer to derivative function
178 * \param i_dep Dependent species index
179 * \param i_ind Independent species index
180 * \param d_rate_d_ind Change in rate for dependent species with change in
181 * independent species
182 * \param d_ind Increment to use in plot of rate_dep vs conc_ind
183 */
184void output_deriv_local_state(realtype curr_time, N_Vector state,
185 N_Vector deriv, void *solver_data,
186 int (*f)(realtype, N_Vector, N_Vector, void *),
187 int i_dep, int i_ind, double d_rate_d_ind,
188 double d_ind) {
189 realtype *deriv_data = NV_DATA_S(deriv);
190 realtype *state_data = NV_DATA_S(state);
191 realtype rate_orig = deriv_data[i_dep];
192 realtype ind_orig = state_data[i_ind];
193
194 SolverData *sd = (SolverData *)solver_data;
195 ModelData *md = &(sd->model_data);
196
197 FILE *f_output;
198 char file_name[MAX_FILE_NAME];
199 sprintf(file_name, "local_%d_i%d_d%d", file_name_prefix++, i_ind, i_dep);
200 f_output = fopen(file_name, "w");
201 printf("\nOutputting deriv local state file: %s", file_name);
202
203 // Output the loss of precision for all species
204 ((SolverData *)solver_data)->output_precision = 1;
205 if (f(curr_time, state, deriv, solver_data) != 0) {
206 printf("\nERROR: Derivative failure\n\n");
207 }
208 ((SolverData *)solver_data)->output_precision = 0;
209
210 // Output the current state
211 fprintf(f_output, "#time %1.30le", curr_time);
212 for (int i = 0; i < NV_LENGTH_S(state); ++i)
213 fprintf(f_output, " [%3d] %1.30le", i, state_data[i]);
214 fprintf(f_output, "\n");
215
216 // Vary the model state and recalculate the derivative directly and using
217 // the partial derivative provided
218 for (int i = 0; i < N_OUTPUT_STATES; ++i) {
219 state_data[i_ind] -= d_ind;
220 if (state_data[i_ind] < 0.0) break;
221
222 if (f(curr_time, state, deriv, solver_data) != 0) {
223 printf("\nERROR: Derivative failure\n\n");
224 break;
225 }
226 fprintf(f_output, "%d %1.30le %1.30le %1.30le\n", -i, state_data[i_ind],
227 deriv_data[i_dep],
228 (state_data[i_ind] - ind_orig) * d_rate_d_ind + rate_orig);
229 }
230 state_data[i_ind] = ind_orig;
231 for (int i = 0; i < N_OUTPUT_STATES; ++i) {
232 state_data[i_ind] += d_ind;
233 if (f(curr_time, state, deriv, solver_data) != 0) {
234 printf("\nERROR: Derivative failure\n\n");
235 break;
236 }
237 fprintf(f_output, "%d %1.30le %1.30le %1.30le\n", i, state_data[i_ind],
238 deriv_data[i_dep],
239 (state_data[i_ind] - ind_orig) * d_rate_d_ind + rate_orig);
240 }
241 state_data[i_ind] = ind_orig;
242 if (f(curr_time, state, deriv, solver_data) != 0) {
243 printf("\nERROR: Derivative failure\n\n");
244 EXIT_FAILURE;
245 }
246
247 printf("\nEnd output deriv local state file: %s", file_name);
248 fclose(f_output);
249}
250
251#endif
void output_deriv_local_state(realtype curr_time, N_Vector state, N_Vector deriv, void *solver_data, int(*f)(realtype, N_Vector, N_Vector, void *), int i_dep, int i_ind, double d_rate_d_ind, double d_ind)
Evaluate the derivative and Jacobian near a given state for a specified species.
Definition camp_debug.h:184
#define N_OUTPUT_STATES
Definition camp_debug.h:18
static void print_jacobian(SUNMatrix M)
Print Jacobian matrix in format KLU SPARSE.
Definition camp_debug.h:145
static void print_derivative(N_Vector deriv)
Print derivative array.
Definition camp_debug.h:162
int file_name_prefix
Definition camp_debug.h:12
static void print_data_sizes(ModelData *md)
Print some camp-chem data sizes.
Definition camp_debug.h:132
#define MAX_FILE_NAME
Definition camp_debug.h:15
int f(realtype t, N_Vector y, N_Vector deriv, void *solver_data)
Compute the time derivative f(t,y)
#define CAMP_DEBUG_SPEC_
Definition rxn_solver.c:11
int n_per_cell_state_var
Definition camp_common.h:63
int * rxn_int_data
int n_per_cell_dep_var
Definition camp_common.h:64
ModelData model_data