24#include "cuda/camp_gpu_solver.h"
29#define DEFAULT_TIME_STEP 1.0
31#define JAC_CHECK_ADV_MAX 1.0E-00
32#define JAC_CHECK_ADV_MIN 1.0E-12
34#define MAX_TIMESTEP_WARNINGS -1
36#define GUESS_MAX_ITER 5
39#define CAMP_SOLVER_SUCCESS 0
40#define CAMP_SOLVER_FAIL 1
73void *
solver_new(
int n_state_var,
int n_cells,
int *var_type,
int n_rxn,
74 int n_rxn_int_param,
int n_rxn_float_param,
75 int n_rxn_env_param,
int n_aero_phase,
76 int n_aero_phase_int_param,
int n_aero_phase_float_param,
77 int n_aero_rep,
int n_aero_rep_int_param,
78 int n_aero_rep_float_param,
int n_aero_rep_env_param,
79 int n_sub_model,
int n_sub_model_int_param,
80 int n_sub_model_float_param,
int n_sub_model_env_param) {
84 printf(
"\n\nERROR allocating space for SolverData\n\n");
88#ifdef CAMP_USE_SUNDIALS
91 sd->debug_out = SUNFALSE;
94 sd->eval_Jac = SUNFALSE;
113 printf(
"\n\nERROR allocating space for variable types\n\n");
116 for (
int i = 0; i < n_state_var; i++)
121 for (
int i = 0; i < n_state_var; i++)
127#ifdef CAMP_USE_SUNDIALS
130 printf(
"\n\nERROR initializing the TimeDerivative\n\n");
135 sd->
y = N_VNew_Serial(n_dep_var * n_cells);
136 sd->
deriv = N_VNew_Serial(n_dep_var * n_cells);
143 (
int *)malloc((n_rxn_int_param + n_rxn) *
sizeof(int));
145 printf(
"\n\nERROR allocating space for reaction integer data\n\n");
149 (
double *)malloc(n_rxn_float_param *
sizeof(
double));
151 printf(
"\n\nERROR allocating space for reaction float data\n\n");
155 (
double *)calloc(n_cells * n_rxn_env_param,
sizeof(
double));
158 "\n\nERROR allocating space for environment-dependent "
166 printf(
"\n\nERROR allocating space for reaction integer indices\n\n");
171 printf(
"\n\nERROR allocating space for reaction float indices\n\n");
177 "\n\nERROR allocating space for reaction environment-dependent "
178 "data pointers\n\n");
196 (
int *)malloc(n_aero_phase_int_param *
sizeof(
int));
198 printf(
"\n\nERROR allocating space for aerosol phase integer data\n\n");
202 (
double *)malloc(n_aero_phase_float_param *
sizeof(
double));
205 "\n\nERROR allocating space for aerosol phase floating-point "
212 (
int *)malloc((n_aero_phase + 1) *
sizeof(
int *));
214 printf(
"\n\nERROR allocating space for reaction integer indices\n\n");
218 (
int *)malloc((n_aero_phase + 1) *
sizeof(
int *));
220 printf(
"\n\nERROR allocating space for reaction float indices\n\n");
235 (
int *)malloc((n_aero_rep_int_param + n_aero_rep) *
sizeof(int));
238 "\n\nERROR allocating space for aerosol representation integer "
243 (
double *)malloc(n_aero_rep_float_param *
sizeof(
double));
246 "\n\nERROR allocating space for aerosol representation "
247 "floating-point data\n\n");
251 (
double *)calloc(n_cells * n_aero_rep_env_param,
sizeof(
double));
254 "\n\nERROR allocating space for aerosol representation "
255 "environmental parameters\n\n");
261 (
int *)malloc((n_aero_rep + 1) *
sizeof(
int *));
263 printf(
"\n\nERROR allocating space for reaction integer indices\n\n");
267 (
int *)malloc((n_aero_rep + 1) *
sizeof(
int *));
269 printf(
"\n\nERROR allocating space for reaction float indices\n\n");
273 (
int *)malloc((n_aero_rep + 1) *
sizeof(int));
276 "\n\nERROR allocating space for aerosol representation "
277 "environment-dependent data pointers\n\n");
292 (
int *)malloc((n_sub_model_int_param + n_sub_model) *
sizeof(int));
294 printf(
"\n\nERROR allocating space for sub model integer data\n\n");
298 (
double *)malloc(n_sub_model_float_param *
sizeof(
double));
300 printf(
"\n\nERROR allocating space for sub model floating-point data\n\n");
304 (
double *)calloc(n_cells * n_sub_model_env_param,
sizeof(
double));
307 "\n\nERROR allocating space for sub model environment-dependent "
314 (
int *)malloc((n_sub_model + 1) *
sizeof(
int *));
316 printf(
"\n\nERROR allocating space for reaction integer indices\n\n");
320 (
int *)malloc((n_sub_model + 1) *
sizeof(
int *));
322 printf(
"\n\nERROR allocating space for reaction float indices\n\n");
326 (
int *)malloc((n_sub_model + 1) *
sizeof(int));
329 "\n\nERROR allocating space for sub model environment-dependent "
330 "data pointers\n\n");
342 solver_new_gpu_cu(n_dep_var, n_state_var, n_rxn, n_rxn_int_param,
343 n_rxn_float_param, n_rxn_env_param, n_cells);
365 int max_steps,
int max_conv_fails) {
366#ifdef CAMP_USE_SUNDIALS
377 srand((
unsigned int)100);
384#ifndef SUNDIALS_VERSION_MAJOR
385# error SUNDIALS_VERSION_MAJOR not defined
386#elif SUNDIALS_VERSION_MAJOR < 4
400 flag = CVodeSetUserData(sd->
cvode_mem, sd);
406 flag = CVodeInit(sd->
cvode_mem,
f, (realtype)0.0, sd->
y);
410 sd->
abs_tol_nv = N_VNew_Serial(n_dep_var * n_cells);
412 for (
int i_cell = 0; i_cell < n_cells; ++i_cell)
413 for (
int i_spec = 0; i_spec < n_state_var; ++i_spec)
415 NV_Ith_S(sd->
abs_tol_nv, i_dep_var++) = (realtype)abs_tol[i_spec];
424 flag = CVodeSetMaxNumSteps(sd->
cvode_mem, max_steps);
428 flag = CVodeSetMaxConvFails(sd->
cvode_mem, max_conv_fails);
432 flag = CVodeSetMaxErrTestFails(sd->
cvode_mem, max_conv_fails);
450 sd->
ls = SUNKLU(sd->
y, sd->
J);
454 flag = CVDlsSetLinearSolver(sd->
cvode_mem, sd->
ls, sd->
J);
461#ifdef CAMP_CUSTOM_CVODE
477#ifndef FAILURE_DETAIL
492int solver_set_debug_out(
void *solver_data,
bool do_output) {
493#ifdef CAMP_USE_SUNDIALS
496 sd->debug_out = do_output ==
true ? SUNTRUE : SUNFALSE;
512int solver_set_eval_jac(
void *solver_data,
bool eval_Jac) {
513#ifdef CAMP_USE_SUNDIALS
516 sd->eval_Jac = eval_Jac ==
true ? SUNTRUE : SUNFALSE;
534int solver_run(
void *solver_data,
double *state,
double *env,
double t_initial,
536#ifdef CAMP_USE_SUNDIALS
545 for (
int i_cell = 0; i_cell < n_cells; i_cell++)
546 for (
int i_spec = 0; i_spec < n_state_var; i_spec++)
548 NV_Ith_S(sd->
y, i_dep_var++) =
549 state[i_spec + i_cell * n_state_var] >
TINY
550 ? (realtype)state[i_spec + i_cell * n_state_var]
553 state[i_spec + i_cell * n_state_var] =
554 state[i_spec + i_cell * n_state_var] >
TINY
555 ? state[i_spec + i_cell * n_state_var]
565 flag = CVodeSetDebugOut(sd->
cvode_mem, sd->debug_out);
567 flag = SUNKLUSetDebugOut(sd->
ls, sd->debug_out);
577 for (
int i_cell = 0; i_cell < md->
n_cells; ++i_cell) {
609 flag = CVodeReInit(sd->
cvode_mem, t_initial, sd->
y);
613 flag = SUNKLUReInit(sd->
ls, sd->
J, SM_NNZ_S(sd->
J), SUNKLU_REINIT_PARTIAL);
621 realtype t_rt = (realtype)t_initial;
623 flag = CVode(sd->
cvode_mem, (realtype)t_final, sd->
y, &t_rt, CV_NORMAL);
625#ifndef FAILURE_DETAIL
631 int lastflag = CVDlsGetLastFlag(sd->
cvode_mem, &lsflag);
632 printf(
"\nLinear Solver Setup Fail: %d %ld", lastflag, lsflag);
634 N_Vector deriv = N_VClone(sd->
y);
635 flag =
f(t_initial, sd->
y, deriv, sd);
637 printf(
"\nCall to f() at failed state failed with flag %d\n", flag);
638 for (
int i_cell = 0; i_cell < md->
n_cells; ++i_cell) {
639 printf(
"\n Cell: %d ", i_cell);
646 "spec %d = %le deriv = %le\n", i_spec,
651 printf(
"spec %d = %le\n", i_spec,
663 for (
int i_cell = 0; i_cell < n_cells; i_cell++) {
664 for (
int i_spec = 0; i_spec < n_state_var; i_spec++) {
666 state[i_spec + i_cell * n_state_var] =
667 (double)(NV_Ith_S(sd->
y, i_dep_var) > 0.0
668 ? NV_Ith_S(sd->
y, i_dep_var)
716 int *RHS_evals,
int *LS_setups,
717 int *error_test_fails,
int *NLS_iters,
718 int *NLS_convergence_fails,
int *DLS_Jac_evals,
719 int *DLS_RHS_evals,
double *last_time_step__s,
720 double *next_time_step__s,
int *Jac_eval_fails,
721 int *RHS_evals_total,
int *Jac_evals_total,
722 double *RHS_time__s,
double *Jac_time__s,
723 double *max_loss_precision) {
724#ifdef CAMP_USE_SUNDIALS
726 long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
727 realtype last_h, curr_h;
731 flag = CVodeGetNumSteps(sd->
cvode_mem, &nst);
733 *num_steps = (int)nst;
734 flag = CVodeGetNumRhsEvals(sd->
cvode_mem, &nfe);
736 *RHS_evals = (int)nfe;
737 flag = CVodeGetNumLinSolvSetups(sd->
cvode_mem, &nsetups);
740 *LS_setups = (int)nsetups;
741 flag = CVodeGetNumErrTestFails(sd->
cvode_mem, &netf);
744 *error_test_fails = (int)netf;
745 flag = CVodeGetNumNonlinSolvIters(sd->
cvode_mem, &nni);
748 *NLS_iters = (int)nni;
749 flag = CVodeGetNumNonlinSolvConvFails(sd->
cvode_mem, &ncfn);
750 if (
check_flag(&flag,
"CVodeGetNumNonlinSolvConvFails", 1) ==
753 *NLS_convergence_fails = ncfn;
754 flag = CVDlsGetNumJacEvals(sd->
cvode_mem, &nje);
756 *DLS_Jac_evals = (int)nje;
757 flag = CVDlsGetNumRhsEvals(sd->
cvode_mem, &nfeLS);
759 *DLS_RHS_evals = (int)nfeLS;
760 flag = CVodeGetLastStep(sd->
cvode_mem, &last_h);
762 *last_time_step__s = (double)last_h;
763 flag = CVodeGetCurrentStep(sd->
cvode_mem, &curr_h);
765 *next_time_step__s = (double)curr_h;
768 *RHS_evals_total = sd->counterDeriv;
769 *Jac_evals_total = sd->counterJac;
770 *RHS_time__s = ((double)sd->timeDeriv) / CLOCKS_PER_SEC;
771 *Jac_time__s = ((double)sd->timeJac) / CLOCKS_PER_SEC;
772 *max_loss_precision = sd->max_loss_precision;
774 *RHS_evals_total = -1;
775 *Jac_evals_total = -1;
778 *max_loss_precision = 0.0;
783#ifdef CAMP_USE_SUNDIALS
797 realtype replacement_value) {
800 int n_cells = model_data->
n_cells;
803 for (
int i_cell = 0; i_cell < n_cells; i_cell++) {
804 for (
int i_spec = 0; i_spec < n_state_var; ++i_spec) {
806 if (NV_DATA_S(solver_state)[i_dep_var] < -
SMALL) {
808 printf(
"\nFailed model state update: [spec %d] = %le", i_spec,
809 NV_DATA_S(solver_state)[i_dep_var]);
814 model_data->
total_state[i_spec + i_cell * n_state_var] =
815 NV_DATA_S(solver_state)[i_dep_var] > threshhold
816 ? NV_DATA_S(solver_state)[i_dep_var]
833int f(realtype t, N_Vector y, N_Vector deriv,
void *solver_data) {
843 double *deriv_data = N_VGetArrayPointer(deriv);
846 double *jac_deriv_data = N_VGetArrayPointer(md->
J_tmp);
854 CVodeGetCurrentStep(sd->
cvode_mem, &time_step);
873 clock_t start = clock();
878 N_VConst(
ZERO, deriv);
882 rxn_calc_deriv_gpu(md, deriv, (
double)time_step);
886 clock_t end = clock();
887 sd->timeDeriv += (end - start);
891 for (
int i_cell = 0; i_cell < n_cells; ++i_cell) {
911 clock_t start2 = clock();
936 clock_t end2 = clock();
937 sd->timeDeriv += (end2 - start2);
938 sd->max_loss_precision = time_derivative_max_loss_precision(sd->
time_deriv);
942 deriv_data += n_dep_var;
943 jac_deriv_data += n_dep_var;
962int Jac(realtype t, N_Vector y, N_Vector deriv, SUNMatrix J,
void *solver_data,
963 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
978 double *J_param_data = SM_DATA_S(md->
J_params);
979 double *J_rxn_data = SM_DATA_S(md->
J_rxn);
997 if (
f(t, y, deriv, solver_data) != 0) {
998 printf(
"\n Derivative calculation failed.\n");
1011 CVodeGetCurrentStep(sd->
cvode_mem, &time_step);
1016 SM_NNZ_S(J) = SM_NNZ_S(md->
J_init);
1017 for (
int i = 0; i <= SM_NP_S(J); i++) {
1018 (SM_INDEXPTRS_S(J))[i] = (SM_INDEXPTRS_S(md->
J_init))[i];
1020 for (
int i = 0; i < SM_NNZ_S(J); i++) {
1021 (SM_INDEXVALS_S(J))[i] = (SM_INDEXVALS_S(md->
J_init))[i];
1022 (SM_DATA_S(J))[i] = (realtype)0.0;
1026 clock_t start2 = clock();
1031 rxn_calc_jac_gpu(md, J, time_step);
1035 clock_t end2 = clock();
1036 sd->timeJac += (end2 - start2);
1042 for (
int i_cell = 0; i_cell < n_cells; ++i_cell) {
1055 for (
int i = 0; i < SM_NNZ_S(md->
J_params); ++i)
1068 clock_t start = clock();
1081 clock_t end = clock();
1082 sd->timeJac += (end - start);
1101 for (
int i_elem = 0; i_elem < SM_NNZ_S(J); ++i_elem)
1102 SM_DATA_S(md->
J_solver)[i_elem] = SM_DATA_S(J)[i_elem];
1103 N_VScale(1.0, y, md->
J_state);
1104 N_VScale(1.0, deriv, md->
J_deriv);
1108 if (sd->eval_Jac == SUNTRUE) {
1109 if (!
check_Jac(t, y, J, deriv, tmp1, tmp3, solver_data)) {
1136bool check_Jac(realtype t, N_Vector y, SUNMatrix J, N_Vector deriv,
1137 N_Vector tmp, N_Vector tmp1,
void *solver_data) {
1138 realtype *d_state = NV_DATA_S(y);
1139 realtype *d_deriv = NV_DATA_S(deriv);
1143 if (
f(t, y, deriv, solver_data) != 0) {
1144 printf(
"\n Derivative calculation failed.\n");
1181#ifdef CAMP_CUSTOM_CVODE
1182int guess_helper(
const realtype t_n,
const realtype h_n, N_Vector y_n,
1183 N_Vector y_n1, N_Vector hf,
void *solver_data, N_Vector tmp1,
1186 realtype *ay_n = NV_DATA_S(y_n);
1187 realtype *ay_n1 = NV_DATA_S(y_n1);
1188 realtype *atmp1 = NV_DATA_S(tmp1);
1189 realtype *acorr = NV_DATA_S(corr);
1190 realtype *ahf = NV_DATA_S(hf);
1191 int n_elem = NV_LENGTH_S(y_n);
1194 if (N_VMin(y_n) > -
SMALL)
return 0;
1199 N_VScale(
ONE, y_n1, tmp1);
1203 N_VScale(
ONE / h_n, hf, corr);
1205 N_VScale(
ONE, hf, corr);
1210 realtype t_0 = h_n >
ZERO ? t_n - h_n : t_n -
ONE;
1211 realtype t_j =
ZERO;
1215 realtype h_j = t_n - (t_0 + t_j);
1217 for (
int i = 0; i < n_elem; i++) {
1218 realtype t_star = -atmp1[i] / acorr[i];
1219 if ((t_star >
ZERO || (t_star ==
ZERO && acorr[i] <
ZERO)) &&
1227 if (i_fast >= 0 && h_n >
ZERO)
1229 h_j = t_n < t_0 + t_j + h_j ? t_n - (t_0 + t_j) : h_j;
1233 t_n - (h_j + t_j + t_0) > ((CVodeMem)sd->
cvode_mem)->cv_reltol)
1237 N_VLinearSum(
ONE, tmp1, h_j, corr, tmp1);
1244 if (
f(t_0 + t_j, tmp1, corr, solver_data) != 0) {
1246 N_VConst(
ZERO, corr);
1253 if (h_n ==
ZERO)
return -1;
1260 N_VLinearSum(
ONE, tmp1, -
ONE, y_n, corr);
1263 if (h_n >
ZERO) N_VScale(0.999, corr, corr);
1266 N_VLinearSum(
ONE, tmp1, -
ONE, y_n1, hf);
1281 sunindextype n_jac_elem_rxn;
1283 sunindextype n_jac_elem_param;
1285 sunindextype n_jac_elem_solver;
1295 int n_state_var_total = n_state_var * n_cells;
1302 int n_dep_var_total = n_dep_var * n_cells;
1306 (
unsigned int)n_state_var) != 1) {
1307 printf(
"\n\nERROR allocating Jacobian structure\n\n");
1312 for (
unsigned int i_spec = 0; i_spec < n_state_var; ++i_spec) {
1322 printf(
"\n\nERROR building sparse full-state Jacobian\n\n");
1334 SUNSparseMatrix(n_state_var, n_state_var, n_jac_elem_rxn, CSC_MAT);
1337 for (
unsigned int i_col = 0; i_col <= n_state_var; ++i_col) {
1341 for (
unsigned int i_elem = 0; i_elem < n_jac_elem_rxn; ++i_elem) {
1348 int *deriv_ids = (
int *)malloc(
sizeof(
int) * n_state_var);
1350 if (deriv_ids == NULL) {
1351 printf(
"\n\nERROR allocating space for derivative ids\n\n");
1355 for (
int i_spec = 0; i_spec < n_state_var; i_spec++) {
1357 deriv_ids[i_spec] = i_dep_var++;
1359 deriv_ids[i_spec] = -1;
1373 printf(
"\n\nERROR allocating sub-model Jacobian structure\n\n");
1386 printf(
"\n\nERROR building sparse Jacobian for sub-model parameters\n\n");
1399 SUNSparseMatrix(n_state_var, n_state_var, n_jac_elem_param, CSC_MAT);
1402 for (
unsigned int i_col = 0; i_col <= n_state_var; ++i_col) {
1406 for (
unsigned int i_elem = 0; i_elem < n_jac_elem_param; ++i_elem) {
1422 printf(
"\n\nERROR allocating solver Jacobian structure\n\n");
1427 int n_mapped_values = 0;
1428 for (
int i_ind = 0; i_ind < n_state_var; ++i_ind) {
1429 for (
int i_dep = 0; i_dep < n_state_var; ++i_dep) {
1445 for (
int j_ind = 0; j_ind < n_state_var; ++j_ind) {
1457 printf(
"\n\nERROR building sparse Jacobian for the solver\n\n");
1466 SUNMatrix M = SUNSparseMatrix(n_dep_var_total, n_dep_var_total,
1467 n_jac_elem_solver * n_cells, CSC_MAT);
1469 n_dep_var_total, n_dep_var_total, n_jac_elem_solver * n_cells, CSC_MAT);
1472 for (
unsigned int i_cell = 0; i_cell < n_cells; ++i_cell) {
1473 for (
unsigned int cell_col = 0; cell_col < n_state_var; ++cell_col) {
1474 if (deriv_ids[cell_col] == -1)
continue;
1475 unsigned int i_col = deriv_ids[cell_col] + i_cell * n_dep_var;
1476 (SM_INDEXPTRS_S(M))[i_col] =
1479 i_cell * n_jac_elem_solver;
1481 for (
unsigned int cell_elem = 0; cell_elem < n_jac_elem_solver;
1483 unsigned int i_elem = cell_elem + i_cell * n_jac_elem_solver;
1484 (SM_DATA_S(M))[i_elem] =
1486 (SM_INDEXVALS_S(M))[i_elem] =
1492 (SM_INDEXPTRS_S(M))[n_cells * n_dep_var] =
1494 n_cells * n_jac_elem_solver;
1501 printf(
"\n\nERROR allocating space for jacobian map\n\n");
1508 int i_mapped_value = 0;
1509 for (
unsigned int i_ind = 0; i_ind < n_state_var; ++i_ind) {
1510 for (
unsigned int i_elem =
1525 map[i_mapped_value].
rxn_id = i_elem;
1532 for (
int j_ind = 0; j_ind < n_state_var; ++j_ind) {
1537 map[i_mapped_value].
rxn_id = i_elem;
1551 if (i_mapped_value != n_mapped_values) {
1552 printf(
"[ERROR-340355266] Internal error");
1588 if (opt == 0 && flag_value == NULL) {
1589 fprintf(stderr,
"\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
1595 else if (opt == 1) {
1596 err_flag = (
int *)flag_value;
1597 if (*err_flag < 0) {
1598 fprintf(stderr,
"\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
1599 func_name, *err_flag);
1624#ifdef CAMP_USE_SUNDIALS
1629 sd->counterDeriv = 0;
1642 long int nst, nfe, nsetups, nje, nfeLS, nni, ncfn, netf, nge;
1643 realtype last_h, curr_h;
1646 flag = CVodeGetNumSteps(cvode_mem, &nst);
1648 flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
1650 flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
1653 flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
1656 flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
1659 flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
1660 if (
check_flag(&flag,
"CVodeGetNumNonlinSolvConvFails", 1) ==
1663 flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
1665 flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
1667 flag = CVodeGetNumGEvals(cvode_mem, &nge);
1669 flag = CVodeGetLastStep(cvode_mem, &last_h);
1671 flag = CVodeGetCurrentStep(cvode_mem, &curr_h);
1674 printf(
"\nSUNDIALS Solver Statistics:\n");
1675 printf(
"number of steps = %-6ld RHS evals = %-6ld LS setups = %-6ld\n", nst,
1677 printf(
"error test fails = %-6ld LS iters = %-6ld NLS iters = %-6ld\n", netf,
1680 "NL conv fails = %-6ld Dls Jac evals = %-6ld Dls RHS evals = %-6ld G "
1683 ncfn, nje, nfeLS, nge);
1684 printf(
"Last time step = %le Next time step = %le\n", last_h, curr_h);
1696#ifdef CAMP_USE_SUNDIALS
1711 N_VDestroy(sd->
deriv);
1714 SUNMatDestroy(sd->
J);
1720 SUNLinSolFree(sd->
ls);
1730#ifdef CAMP_USE_SUNDIALS
1740 if (
f(t_initial, sd->
y, sd->
deriv, sd)) {
1742 for (
int i_cell = 0; i_cell < md->
n_cells; ++i_cell) {
1745 if (NV_Ith_S(sd->
y, i_dep_var) >
1746 NV_Ith_S(sd->
abs_tol_nv, i_dep_var) * 1.0e-10)
1748 if (NV_Ith_S(sd->
deriv, i_dep_var) * (t_final - t_initial) >
1749 NV_Ith_S(sd->
abs_tol_nv, i_dep_var) * 1.0e-10)
1768 char *msg,
void *sd) {
1781#ifdef CAMP_USE_SUNDIALS
1783 SUNMatDestroy(model_data.
J_init);
1784 SUNMatDestroy(model_data.
J_rxn);
1785 SUNMatDestroy(model_data.
J_params);
1786 SUNMatDestroy(model_data.
J_solver);
1787 N_VDestroy(model_data.
J_state);
1788 N_VDestroy(model_data.
J_deriv);
1789 N_VDestroy(model_data.
J_tmp);
1790 N_VDestroy(model_data.
J_tmp2);
unsigned int jacobian_column_pointer_value(Jacobian jac, unsigned int col_id)
Returns the value of a column pointer.
void jacobian_free(Jacobian *jac)
Free memory associated with a Jacobian.
unsigned int jacobian_build_matrix(Jacobian *jac)
Builds the sparse matrix with the registered elements.
int jacobian_initialize_empty(Jacobian *jac, unsigned int num_spec)
Initialize the Jacobian.
unsigned int jacobian_number_of_elements(Jacobian jac)
Returns the number of elements in the Jacobian.
unsigned int jacobian_get_element_id(Jacobian jac, unsigned int dep_id, unsigned int ind_id)
Get an element id in the Jacobian data arrays.
void jacobian_reset(Jacobian jac)
Reset the Jacobian.
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
Adds an element to the sparse matrix.
void jacobian_output(Jacobian jac, double *dest_array)
Output the Jacobian.
unsigned int jacobian_row_index(Jacobian jac, unsigned int elem_id)
Returns the row for a given Jacobian element.
#define CHEM_SPEC_VARIABLE
#define CHEM_SPEC_CONSTANT
void aero_rep_update_env_state(ModelData *model_data)
Update the aerosol representations for new environmental conditions.
void aero_rep_update_state(ModelData *model_data)
Update the aerosol representations for a new state.
Header file for abstract aerosol representation functions.
#define CAMP_NUM_ENV_PARAM_
#define CAMP_DEBUG_PRINT(x)
#define CAMP_DEBUG_JAC(J, x)
#define CAMP_DEBUG_JAC_STRUCT(J, x)
static void print_data_sizes(ModelData *md)
Print some camp-chem data sizes.
#define CAMP_DEBUG_PRINT_INT(x, y)
#define CAMP_DEBUG_PRINT_FULL(x)
void model_free(ModelData model_data)
Free a ModelData object.
int check_flag(void *flag_value, char *func_name, int opt)
Check the return value of a SUNDIALS function.
void solver_get_statistics(void *solver_data, int *solver_flag, int *num_steps, int *RHS_evals, int *LS_setups, int *error_test_fails, int *NLS_iters, int *NLS_convergence_fails, int *DLS_Jac_evals, int *DLS_RHS_evals, double *last_time_step__s, double *next_time_step__s, int *Jac_eval_fails, int *RHS_evals_total, int *Jac_evals_total, double *RHS_time__s, double *Jac_time__s, double *max_loss_precision)
Get solver statistics after an integration attempt.
int Jac(realtype t, N_Vector y, N_Vector deriv, SUNMatrix J, void *solver_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
Compute the Jacobian.
int camp_solver_update_model_state(N_Vector solver_state, ModelData *model_data, realtype threshhold, realtype replacement_value)
Update the model state from the current solver state.
#define MAX_TIMESTEP_WARNINGS
bool is_anything_going_on_here(SolverData *sd, realtype t_initial, realtype t_final)
Determine if there is anything to solve.
void solver_initialize(void *solver_data, double *abs_tol, double rel_tol, int max_steps, int max_conv_fails)
Solver initialization.
SUNMatrix get_jac_init(SolverData *solver_data)
Try to improve guesses of y sent to the linear solver.
void * solver_new(int n_state_var, int n_cells, int *var_type, int n_rxn, int n_rxn_int_param, int n_rxn_float_param, int n_rxn_env_param, int n_aero_phase, int n_aero_phase_int_param, int n_aero_phase_float_param, int n_aero_rep, int n_aero_rep_int_param, int n_aero_rep_float_param, int n_aero_rep_env_param, int n_sub_model, int n_sub_model_int_param, int n_sub_model_float_param, int n_sub_model_env_param)
Get a new solver object.
void check_flag_fail(void *flag_value, char *func_name, int opt)
Check the return value of a SUNDIALS function and exit on failure.
#define DEFAULT_TIME_STEP
void solver_free(void *solver_data)
Free a SolverData object.
void solver_free_update_data(void *update_data)
Free update data.
static void solver_print_stats(void *cvode_mem)
Print solver statistics.
#define CAMP_SOLVER_SUCCESS
void error_handler(int error_code, const char *module, const char *function, char *msg, void *sd)
Custom error handling function.
int f(realtype t, N_Vector y, N_Vector deriv, void *solver_data)
Compute the time derivative f(t,y)
bool check_Jac(realtype t, N_Vector y, SUNMatrix J, N_Vector deriv, N_Vector tmp, N_Vector tmp1, void *solver_data)
Check a Jacobian for accuracy.
void solver_reset_timers(void *solver_data)
Reset the timers for solver functions.
int solver_run(void *solver_data, double *state, double *env, double t_initial, double t_final)
Solve for a given timestep.
Header file for solver functions.
int guess_helper(const realtype t_n, const realtype h_n, N_Vector y_n, N_Vector y_n1, N_Vector hf, void *solver_data, N_Vector tmp1, N_Vector corr)
void rxn_update_ids(ModelData *model_data, int *deriv_ids, Jacobian jac)
Update the time derivative and Jacobian array ids.
void rxn_calc_deriv_specific_types(ModelData *model_data, TimeDerivative time_deriv, realtype time_step)
Calculate the time derivative for only some specific types.
void rxn_calc_jac_specific_types(ModelData *model_data, Jacobian jac, realtype time_step)
Calculate the Jacobian for only some specific types.
void rxn_get_used_jac_elem(ModelData *model_data, Jacobian *jac)
Get the Jacobian elements used by a particular reaction.
void rxn_update_env_state(ModelData *model_data)
Update reaction data for new environmental state.
void rxn_calc_jac(ModelData *model_data, Jacobian jac, realtype time_step)
Calculate the Jacobian.
void rxn_calc_deriv(ModelData *model_data, TimeDerivative time_deriv, realtype time_step)
Calculate the time derivative .
Header file for abstract reaction functions.
int * aero_phase_float_indices
int * sub_model_int_indices
int * aero_rep_int_indices
double * aero_rep_env_data
int n_per_cell_rxn_jac_elem
int * aero_phase_int_indices
double * grid_cell_rxn_env_data
double * aero_rep_float_data
int n_per_cell_param_jac_elem
double * sub_model_float_data
int * aero_rep_float_indices
int n_per_cell_solver_jac_elem
double * aero_phase_float_data
double * grid_cell_aero_rep_env_data
double * grid_cell_sub_model_env_data
double * sub_model_env_data
int * aero_phase_int_data
int * sub_model_float_indices
TimeDerivative time_deriv
void sub_model_update_ids(ModelData *model_data, int *deriv_ids, Jacobian jac)
Update the time derivative and Jacobian array ids.
void sub_model_get_used_jac_elem(ModelData *model_data, Jacobian *jac)
Get the Jacobian elements used by a particular sub model.
void sub_model_update_env_state(ModelData *model_data)
Update sub model data for a new environmental state.
void sub_model_calculate(ModelData *model_data)
Perform the sub model calculations for the current model state.
void sub_model_get_jac_contrib(ModelData *model_data, double *J_data, realtype time_step)
Calculate the Jacobian constributions from sub model calculations.
Header file for abstract sub model functions.
void time_derivative_free(TimeDerivative time_deriv)
Free memory associated with a TimeDerivative.
int time_derivative_initialize(TimeDerivative *time_deriv, unsigned int num_spec)
Initialize the derivative.
void time_derivative_reset(TimeDerivative time_deriv)
Reset the derivative.
void time_derivative_output(TimeDerivative time_deriv, double *dest_array, double *deriv_est, unsigned int output_precision)
Output the current derivative array.