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)