11#include <camp/Jacobian.h>
12#include <camp/time_derivative.h>
18#define SMALL_NUMBER 1e-90
21 jac->num_spec = num_spec;
23 jac->elements = (JacobianColumnElements *)malloc(
24 num_spec *
sizeof(JacobianColumnElements));
29 for (
unsigned int i_col = 0; i_col < num_spec; ++i_col) {
31 jac->elements[i_col].number_of_elements = 0;
32 jac->elements[i_col].row_ids =
33 (
unsigned int *)malloc(
BUFFER_SIZE *
sizeof(
unsigned int));
34 if (!jac->elements[i_col].row_ids) {
41 jac->production_partials = NULL;
42 jac->loss_partials = NULL;
47 unsigned int **jac_struct) {
48 unsigned int num_elem = 0;
49 for (
unsigned int i_col = 0; i_col < num_spec; ++i_col)
50 for (
unsigned int i_row = 0; i_row < num_spec; ++i_row)
51 if (jac_struct[i_col][i_row] == 1) ++num_elem;
53 jac->num_spec = num_spec;
54 jac->num_elem = num_elem;
55 jac->col_ptrs = (
unsigned int *)malloc((num_spec + 1) *
sizeof(
unsigned int));
56 if (!jac->col_ptrs)
return 0;
57 jac->row_ids = (
unsigned int *)malloc(num_elem *
sizeof(
unsigned int));
62 jac->production_partials =
63 (
long double *)malloc(num_elem *
sizeof(
long double));
64 if (!jac->production_partials) {
69 jac->loss_partials = (
long double *)malloc(num_elem *
sizeof(
long double));
70 if (!jac->loss_partials) {
73 free(jac->production_partials);
77 unsigned int i_elem = 0;
78 unsigned int i_col = 0;
79 for (; i_col < num_spec; ++i_col) {
80 jac->col_ptrs[i_col] = i_elem;
81 for (
unsigned int i_row = 0; i_row < num_spec; ++i_row) {
82 if (jac_struct[i_row][i_col] == 1) jac->row_ids[i_elem++] = i_row;
85 jac->col_ptrs[i_col] = i_elem;
93 unsigned int *temp_ids;
95 temp_ids = (
unsigned int *)malloc(column->array_size *
sizeof(
unsigned int));
96 if (!temp_ids)
return 0;
97 for (
unsigned int i_elem = 0; i_elem < column->number_of_elements; ++i_elem) {
98 temp_ids[i_elem] = column->row_ids[i_elem];
100 free(column->row_ids);
101 column->row_ids = temp_ids;
106 unsigned int ind_id) {
107 if (!jac->elements) {
109 "\n\nERROR - Trying to register elements in a Jacobian that has "
110 "already been built.\n\n");
113 JacobianColumnElements *column = &(jac->elements[ind_id]);
114 for (
unsigned int i_elem = 0; i_elem < column->number_of_elements; ++i_elem) {
115 if (column->row_ids[i_elem] == dep_id)
return;
117 if (column->array_size == column->number_of_elements) {
120 jac->elements[ind_id].row_ids[jac->elements[ind_id].number_of_elements] =
122 ++(jac->elements[ind_id].number_of_elements);
126 return (*(
unsigned int *)a - *(
unsigned int *)b);
130 if (!jac->elements) {
132 "\n\nERROR - Trying to build a Jacobian that has already been "
137 for (
unsigned int i_col = 0; i_col < jac->num_spec; ++i_col) {
138 JacobianColumnElements *column = &(jac->elements[i_col]);
139 qsort(column->row_ids, column->number_of_elements,
sizeof(
unsigned int),
141 jac->num_elem += column->number_of_elements;
144 (
unsigned int *)malloc((jac->num_spec + 1) *
sizeof(
unsigned int));
145 if (!jac->col_ptrs) {
149 jac->row_ids = (
unsigned int *)malloc(jac->num_elem *
sizeof(
unsigned int));
154 unsigned int i_elem = 0;
155 for (
unsigned int i_col = 0; i_col < jac->num_spec; ++i_col) {
156 jac->col_ptrs[i_col] = i_elem;
157 JacobianColumnElements *column = &(jac->elements[i_col]);
158 for (
unsigned int j_elem = 0; j_elem < column->number_of_elements;
160 jac->row_ids[i_elem++] = column->row_ids[j_elem];
163 jac->col_ptrs[jac->num_spec] = i_elem;
164 if (i_elem != jac->num_elem) {
165 printf(
"\n\n ERROR - Internal error building Jacobain matrix %d %d\n\n",
166 i_elem, jac->num_elem);
169 jac->production_partials =
170 (
long double *)malloc(jac->num_elem *
sizeof(
long double));
171 if (!jac->production_partials) {
176 (
long double *)malloc(jac->num_elem *
sizeof(
long double));
177 if (!jac->loss_partials) {
181 for (
unsigned int i_col = 0; i_col < jac->num_spec; ++i_col) {
185 jac->elements = NULL;
193 return jac.col_ptrs[col_id];
197 return jac.row_ids[elem_id];
201 unsigned int ind_id) {
202 if (ind_id >= jac.num_spec || ind_id < 0) {
204 "\nError: Bad Jacobian column id: %u. Expected value between 0 and "
206 ind_id, jac.num_spec);
209 for (
unsigned int i_elem = jac.col_ptrs[ind_id];
210 i_elem < jac.col_ptrs[ind_id + 1]; ++i_elem) {
211 if (jac.row_ids[i_elem] == dep_id)
return i_elem;
217 for (
unsigned int i_elem = 0; i_elem < jac.num_elem; ++i_elem) {
218 jac.production_partials[i_elem] = 0.0;
219 jac.loss_partials[i_elem] = 0.0;
224 for (
unsigned int i_col = 0; i_col < jac.num_spec; ++i_col) {
225 for (
unsigned int i_elem = jac.col_ptrs[i_col];
226 i_elem < jac.col_ptrs[i_col + 1]; ++i_elem) {
227 long double drf_dy = jac.production_partials[i_elem];
228 long double drr_dy = jac.loss_partials[i_elem];
229 dest_array[i_elem] = drf_dy - drr_dy;
235 unsigned int prod_or_loss,
236 long double jac_contribution) {
237 if (prod_or_loss == JACOBIAN_PRODUCTION)
238 jac.production_partials[elem_id] += jac_contribution;
239 if (prod_or_loss == JACOBIAN_LOSS)
240 jac.loss_partials[elem_id] += jac_contribution;
244 printf(
"\n *** Jacobian ***");
245 printf(
"\nnumber of variables: %d", jac.num_spec);
246 printf(
"\nnumber of non-zero Jacobian elements: %d", jac.num_elem);
247 if (!jac.col_ptrs && !jac.row_ids && !jac.production_partials &&
248 !jac.loss_partials && jac.elements) {
249 printf(
"\nstatus: building Jacobian");
250 for (
unsigned int i_col = 0; i_col < jac.num_spec; ++i_col) {
251 for (
unsigned int i_elem = 0;
252 i_elem < jac.elements[i_col].number_of_elements; ++i_elem) {
253 printf(
"\n col = %6d row = %6d", i_col,
254 jac.elements[i_col].row_ids[i_elem]);
257 }
else if (jac.col_ptrs && jac.row_ids && jac.production_partials &&
259 printf(
"\nstatus: Jacobian built");
260 for (
unsigned int i_col = 0; i_col < jac.num_spec; ++i_col) {
261 for (
unsigned int i_elem = jac.col_ptrs[i_col];
262 i_elem < jac.col_ptrs[i_col + 1]; ++i_elem) {
263 printf(
"\n col = %6d row = %6d production = %Le loss = %Le", i_col,
264 jac.row_ids[i_elem], jac.production_partials[i_elem],
265 jac.loss_partials[i_elem]);
269 printf(
"\nstatus: invalid state");
271 printf(
"\n *** end Jacobian ***");
275 if (column->row_ids) {
276 free(column->row_ids);
277 column->row_ids = NULL;
284 jac->col_ptrs = NULL;
290 if (jac->production_partials) {
291 free(jac->production_partials);
292 jac->production_partials = NULL;
294 if (jac->loss_partials) {
295 free(jac->loss_partials);
296 jac->loss_partials = NULL;
299 for (
unsigned int i_col = 0; i_col < jac->num_spec; ++i_col) {
303 jac->elements = NULL;
unsigned int jacobian_column_pointer_value(Jacobian jac, unsigned int col_id)
void jacobian_free(Jacobian *jac)
unsigned int jacobian_build_matrix(Jacobian *jac)
int jacobian_initialize_empty(Jacobian *jac, unsigned int num_spec)
int jacobian_initialize(Jacobian *jac, unsigned int num_spec, unsigned int **jac_struct)
unsigned int jacobian_number_of_elements(Jacobian jac)
unsigned int jacobian_get_element_id(Jacobian jac, unsigned int dep_id, unsigned int ind_id)
void jacobian_column_elements_free(JacobianColumnElements *column)
void jacobian_add_value(Jacobian jac, unsigned int elem_id, unsigned int prod_or_loss, long double jac_contribution)
int compare_ids(const void *a, const void *b)
void jacobian_reset(Jacobian jac)
void jacobian_register_element(Jacobian *jac, unsigned int dep_id, unsigned int ind_id)
int jacobian_column_elements_add_space(JacobianColumnElements *column)
void jacobian_print(Jacobian jac)
void jacobian_output(Jacobian jac, double *dest_array)
unsigned int jacobian_row_index(Jacobian jac, unsigned int elem_id)