CAMP 1.0.0
Chemistry Across Multiple Phases
time_derivative.c
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 * Functions of the time derivative structure
6 *
7 */
8/** \file
9 * \brief Functions of the time derivative structure
10 */
11#include "time_derivative.h"
12#include <math.h>
13#include <stdio.h>
14
16 unsigned int num_spec) {
17 if (num_spec <= 0) return 0;
18
19 time_deriv->production_rates =
20 (long double *)malloc(num_spec * sizeof(long double));
21 if (time_deriv->production_rates == NULL) return 0;
22
23 time_deriv->loss_rates =
24 (long double *)malloc(num_spec * sizeof(long double));
25 if (time_deriv->loss_rates == NULL) {
26 free(time_deriv->production_rates);
27 return 0;
28 }
29
30 time_deriv->num_spec = num_spec;
31
32#ifdef CAMP_DEBUG
33 time_deriv->last_max_loss_precision = 0.0;
34#endif
35
36 return 1;
37}
38
40 for (unsigned int i_spec = 0; i_spec < time_deriv.num_spec; ++i_spec) {
41 time_deriv.production_rates[i_spec] = 0.0;
42 time_deriv.loss_rates[i_spec] = 0.0;
43 }
44}
45
46void time_derivative_output(TimeDerivative time_deriv, double *dest_array,
47 double *deriv_est, unsigned int output_precision) {
48 long double *r_p = time_deriv.production_rates;
49 long double *r_l = time_deriv.loss_rates;
50
51#ifdef CAMP_DEBUG
52 time_deriv.last_max_loss_precision = 1.0;
53#endif
54
55 for (unsigned int i_spec = 0; i_spec < time_deriv.num_spec; ++i_spec) {
56 double prec_loss = 1.0;
57 if (*r_p + *r_l != 0.0) {
58 if (deriv_est) {
59 long double scale_fact;
60 scale_fact =
61 1.0 / (*r_p + *r_l) /
62 (1.0 / (*r_p + *r_l) + MAX_PRECISION_LOSS / fabsl(*r_p - *r_l));
63 *dest_array =
64 scale_fact * (*r_p - *r_l) + (1.0 - scale_fact) * (*deriv_est);
65 } else {
66 *dest_array = *r_p - *r_l;
67 }
68#ifdef CAMP_DEBUG
69 if (*r_p != 0.0 && *r_l != 0.0) {
70 prec_loss = *r_p > *r_l ? 1.0 - *r_l / *r_p : 1.0 - *r_p / *r_l;
71 if (prec_loss < time_deriv.last_max_loss_precision)
72 time_deriv.last_max_loss_precision = prec_loss;
73 }
74#endif
75 } else {
76 *dest_array = 0.0;
77 }
78 ++r_p;
79 ++r_l;
80 ++dest_array;
81 if (deriv_est) ++deriv_est;
82#ifdef CAMP_DEBUG
83 if (output_precision == 1) {
84 printf("\nspec %d prec_loss %le", i_spec, -log(prec_loss) / log(2.0));
85 }
86#endif
87 }
88}
89
90void time_derivative_add_value(TimeDerivative time_deriv, unsigned int spec_id,
91 long double rate_contribution) {
92 if (rate_contribution > 0.0) {
93 time_deriv.production_rates[spec_id] += rate_contribution;
94 } else {
95 time_deriv.loss_rates[spec_id] += -rate_contribution;
96 }
97}
98
99#ifdef CAMP_DEBUG
100double time_derivative_max_loss_precision(TimeDerivative time_deriv) {
101 return -log(time_deriv.last_max_loss_precision) / log(2.0);
102}
103#endif
104
106 free(time_deriv.production_rates);
107 free(time_deriv.loss_rates);
108}
unsigned int num_spec
long double * loss_rates
long double * production_rates
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.
void time_derivative_add_value(TimeDerivative time_deriv, unsigned int spec_id, long double rate_contribution)
Add a contribution to the time derivative.
Header for the time derivative structure and related functions.
#define MAX_PRECISION_LOSS