From 85c5a927b7d58568f3bab493b840d5131ecc7c6d Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Fri, 19 Aug 2022 13:54:23 +0200 Subject: [PATCH 01/51] Adjusted the Jacobian calculation to also include equation 6 from l'Heureux. Expressions become even more involved, unfortunately. --- Jacobian.txt | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 Jacobian.txt diff --git a/Jacobian.txt b/Jacobian.txt new file mode 100644 index 0000000..e36e4f5 --- /dev/null +++ b/Jacobian.txt @@ -0,0 +1,200 @@ + + +Index = 0 + + +-Da*(-CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + not_too_deep*not_too_shallow*(1 - CA)*Max(0, -KRat*cCO3*cCa + 1)**m2 + nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + + + + +Index = 1 + + +-CA*Da*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + + + + +Index = 2 + + +-Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + (1 - CA)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) + + + + +Index = 3 + + +-Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + (1 - CA)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) + + + + +Index = 4 + + +0 + + + + +Index = 5 + + +CC*Da*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 + + + + +Index = 6 + + +Da*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + + + + +Index = 7 + + +Da*(CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CC*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) + + + + +Index = 8 + + +Da*(CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CC*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) + + + + +Index = 9 + + +0 + + + + +Index = 10 + + +Da*not_too_deep*not_too_shallow*(1 - Phi)*(-cCa + delta)*Max(0, -KRat*cCO3*cCa + 1)**m2/Phi + + + + +Index = 11 + + +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi + + + + +Index = 12 + + +Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi - Da*(1 - Phi)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi + + + + +Index = 13 + + +Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi + + + + +Index = 14 + + +-Da*(-cCa + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi**2 + + + + +Index = 15 + + +Da*not_too_deep*not_too_shallow*(1 - Phi)*(-cCO3 + delta)*Max(0, -KRat*cCO3*cCa + 1)**m2/Phi + + + + +Index = 16 + + +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi + + + + +Index = 17 + + +Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi + + + + +Index = 18 + + +Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi - Da*(1 - Phi)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi + + + + +Index = 19 + + +-Da*(-cCO3 + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi**2 + + + + +Index = 20 + + +Da*not_too_deep*not_too_shallow*(1 - Phi)*Max(0, -KRat*cCO3*cCa + 1)**m2 + + + + +Index = 21 + + +-Da*lambda_*(1 - Phi)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + + + + +Index = 22 + + +Da*(1 - Phi)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1)) + + + + +Index = 23 + + +Da*(1 - Phi)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1)) + + + + +Index = 24 + + +-Da*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + + From 1e2b5eeb95f44096314b85c9e8712fe0456c0145 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 22 Aug 2022 10:03:54 +0200 Subject: [PATCH 02/51] Tried the Jacobian sparsity matrix, results in longer runtimes, which is the opposite of what is expected. Also end up with equally unstable solutions, i.e. the well-known oscillations along the depth axis. Apparently the sparsity matrix does result in trying to find a better solution, but ultimately fails. Also fixed a bug in Derive_Jacobian.py which luckily was not present in the actual rhs computations. Implemented first steps in setting up the structure for Jacobian computations, so beyond the sparsity matrix. A lot of Numba obviously. --- Compute_jacobian.py | 118 ++++++++++++++++++++++++++++++++++++++++++++ Jacobian.txt | 38 +++++++------- 2 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 Compute_jacobian.py diff --git a/Compute_jacobian.py b/Compute_jacobian.py new file mode 100644 index 0000000..7592988 --- /dev/null +++ b/Compute_jacobian.py @@ -0,0 +1,118 @@ +""" This returns the 25 elements (from 5 fields) of the Jacobian, +computed numerically, using the functional form from Derive_jacobian. +There is also the depth dimension. +In the current implementations of LMAHeureuxPorosityDiff.fun and +LMAHeureuxPorosityDiff.fun_numba, the five fields with each, say, 400 depths, +are treated as 2000 fields, so n = 2000 voor scipy.integrate.solve_ivp. +The solve_ivp documention says that the Jacobian will have shape (n, n), +so (2000, 2000), so calling jac(t, y) should return 4 million numbers! +But most elements will be zero, because derivatives of the five rhs +expressions (equations 40-43 from l'Heureux) wrt to the five fields will only +be non-zero for equal depths. + +Say you want to compute Jacobian element [1,4]. This is +d f_1 / d y_4. That is the derivate of the right hand side of the second +equation (equation 41 from l'Heureux) wrt to field number 5, which is Phi. +We have a functional form for that, from Derive_Jacobian.py, so we can +compute it for all 400 depths. Now where do these 400 numbers end up in +the (2000, 2000) output matrix? For depth 0, it would be element [400, 1600]. +For depth 1, it will be element [401, 1601] and so forth until element +[799, 1999]. So a diagonal within a (400, 400) cell. Ultimately we will fill +25*400 =10000 elements of the 4 million numbers with non-zero values. Actually, +a bit less, because two of the 25 elements of the Jacobian are always zero. +These correspond with the derivatives of the rhs of equations 40 and 41 wrt +Phi. So we have 23 * 400 = 9200 non-zero elements out of 2000 * 2000 = 4e6 +elements. Truly a sparse matrix!""" + +import numpy as np +from numba import njit, prange, vectorize + +@njit(parallel=True) +def Jacobian(y, KRat, m1, m2, n1, n2, nu1, nu2, \ + not_too_deep, not_too_shallow, presum, rhorat, lambda_, Da, dCa, \ + dCO3, delta, auxcon, CA_sl, CC_sl, cCa_sl, cCO3_sl, Phi_sl, \ + no_depths, no_fields): + """ Retun a sparse (n, n) matrix + The Jacobian for five field and five right-hand sides, so 25 elements + of which two are zero, so we need to evaluate 23 expressions. """ + + CA = y[CA_sl] + CC = y[CC_sl] + cCa = y[cCa_sl] + cCO3 = y[cCO3_sl] + Phi = y[Phi_sl] + + def jac00(): + jac00 = -Da * (-CA*not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1)**m2 \ + + CC * lambda_ * (-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ + np.fmax(0, cCO3*cCa - 1)**n1) + not_too_deep*not_too_shallow * (1 - CA) * \ + np.fmax(0, -KRat*cCO3*cCa + 1)**m2 + nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) + return jac00 + + def jac01(): + jac01 = -CA * Da * lambda_*(-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ + np.fmax(0, cCO3*cCa - 1)**n1) + return jac01 + + def jac02(): + jac02 = -Da * (CA * CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3*cCa - 1, 0) \ + * np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + \ + cCO3 * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) * \ + np.fmax(0, -cCO3*cCa + 1) ** (n2-1)) + \ + (1 - CA)*(-CA * KRat * cCO3 *m2 * not_too_deep * not_too_shallow * \ + np.heaviside(-KRat*cCO3*cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1) - \ + KRat * cCO3 * m1 * nu1 * np.heaviside(KRat*cCO3*cCa - 1, 0) * \ + np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1))) + return jac02 + + def jac03(): + jac03 = -Da * (CA * CC * lambda_ * (cCa * n1* np.heaviside(cCO3*cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ + np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 -1)) + \ + (1 - CA) * (-CA * KRat * cCa * m2 * not_too_deep * not_too_shallow * \ + np.heaviside(-KRat*cCO3*cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1) \ + - KRat * cCa * m1 * nu1 * np.heaviside(KRat*cCO3*cCa - 1, 0) * \ + np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1))) + return jac03 + + def jac04(): + return np.zeros(no_depths) + + def jac10(): + jac10 = CC * Da * not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 + + -CA * Da * lambda_*(-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ + np.fmax(0, cCO3*cCa - 1)**n1) + + + row_indices = np.arange(no_depths) + col_indices = np.arange(no_depths) + all_jac_values_rows_and_cols = [] + for i in prange(no_fields): + row = i * no_depths + row_indices + for j in prange(no_fields): + col = j * no_depths + col_indices + row_and_col = (row, col) + if i == 0 and j == 0: + all_jac_values_rows_and_cols.append(jac00(), row_and_col) + elif i == 0 and j == 1: + all_jac_values_rows_and_cols.append(jac01(), row_and_col) + elif i == 0 and j == 2: + all_jac_values_rows_and_cols.append(jac02(), row_and_col) + elif i == 0 and j == 3: + all_jac_values_rows_and_cols.append(jac03(), row_and_col) + elif i == 0 and j == 4: + all_jac_values_rows_and_cols.append(jac04(), row_and_col) + elif i==1 and j == 0: + + + + return all_jac_values_rows_and_cols + + + + + + + + diff --git a/Jacobian.txt b/Jacobian.txt index e36e4f5..1324483 100644 --- a/Jacobian.txt +++ b/Jacobian.txt @@ -3,7 +3,7 @@ Index = 0 --Da*(-CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + not_too_deep*not_too_shallow*(1 - CA)*Max(0, -KRat*cCO3*cCa + 1)**m2 + nu1*Max(0, KRat*cCO3*cCa - 1)**m1) +-Da*(-CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)) @@ -19,7 +19,7 @@ Index = 1 Index = 2 --Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + (1 - CA)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) +-Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) @@ -27,7 +27,7 @@ Index = 2 Index = 3 --Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + (1 - CA)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) +-Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) @@ -43,7 +43,7 @@ Index = 4 Index = 5 -CC*Da*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 +CC*Da*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) @@ -51,7 +51,7 @@ CC*Da*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 Index = 6 -Da*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) +Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) @@ -59,7 +59,7 @@ Da*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_* Index = 7 -Da*(CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CC*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) +Da*(CA*CC*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -67,7 +67,7 @@ Da*(CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n Index = 8 -Da*(CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CC*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))) +Da*(CA*CC*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -83,7 +83,7 @@ Index = 9 Index = 10 -Da*not_too_deep*not_too_shallow*(1 - Phi)*(-cCa + delta)*Max(0, -KRat*cCO3*cCa + 1)**m2/Phi +Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi @@ -99,7 +99,7 @@ Index = 11 Index = 12 -Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi - Da*(1 - Phi)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi @@ -107,7 +107,7 @@ Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heavi Index = 13 -Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi @@ -115,7 +115,7 @@ Da*(1 - Phi)*(-cCa + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heavis Index = 14 --Da*(-cCa + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi**2 +-Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 @@ -123,7 +123,7 @@ Index = 14 Index = 15 -Da*not_too_deep*not_too_shallow*(1 - Phi)*(-cCO3 + delta)*Max(0, -KRat*cCO3*cCa + 1)**m2/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi @@ -139,7 +139,7 @@ Index = 16 Index = 17 -Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi @@ -147,7 +147,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heav Index = 18 -Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1))/Phi - Da*(1 - Phi)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi @@ -155,7 +155,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heavi Index = 19 --Da*(-cCO3 + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi**2 +-Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 @@ -163,7 +163,7 @@ Index = 19 Index = 20 -Da*not_too_deep*not_too_shallow*(1 - Phi)*Max(0, -KRat*cCO3*cCa + 1)**m2 +Da*(1 - Phi)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) @@ -179,7 +179,7 @@ Index = 21 Index = 22 -Da*(1 - Phi)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1)) +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -187,7 +187,7 @@ Da*(1 - Phi)*(-CA*KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3 Index = 23 -Da*(1 - Phi)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) - KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1)) +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -195,6 +195,6 @@ Da*(1 - Phi)*(-CA*KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3* Index = 24 --Da*(CA*not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) +-Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) From ee0756c05bead9f6dea4b9548315c90c7c48f6c1 Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Mon, 22 Aug 2022 20:07:49 +0200 Subject: [PATCH 03/51] First runs using a Jacobian. Unfortunately not a spectacular improvement yet. However, it is possible to integrate over longer times without an overflow error. But also running into memory overflows. --- Compute_jacobian.py | 321 +++++++++++++++--- Jacobian.txt | 46 +-- Jacobian_adjusted_to_reuse_common_factors.txt | 200 +++++++++++ 3 files changed, 504 insertions(+), 63 deletions(-) create mode 100644 Jacobian_adjusted_to_reuse_common_factors.txt diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 7592988..490e1e4 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -25,9 +25,34 @@ elements. Truly a sparse matrix!""" import numpy as np -from numba import njit, prange, vectorize +from numba.extending import overload +from numba import njit -@njit(parallel=True) +@overload(np.heaviside) +def np_heaviside(x1, x2): + def heaviside_impl(x1, x2): + if x1 < 0: + return 0.0 + elif x1 > 0: + return 1.0 + else: + return x2 + + return heaviside_impl + +""" @overload(np.fmax) +def np_fmax(x1, x2): + def fmax_impl(x1, x2): + if x1 < x2: + return x2 + elif x1 > x2: + return x1 + else: + return x1 + + return fmax_impl """ + +# @njit(nogil=True, parallel = True) def Jacobian(y, KRat, m1, m2, n1, n2, nu1, nu2, \ not_too_deep, not_too_shallow, presum, rhorat, lambda_, Da, dCa, \ dCO3, delta, auxcon, CA_sl, CC_sl, cCa_sl, cCO3_sl, Phi_sl, \ @@ -42,70 +67,286 @@ def Jacobian(y, KRat, m1, m2, n1, n2, nu1, nu2, \ cCO3 = y[cCO3_sl] Phi = y[Phi_sl] - def jac00(): - jac00 = -Da * (-CA*not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1)**m2 \ - + CC * lambda_ * (-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ - np.fmax(0, cCO3*cCa - 1)**n1) + not_too_deep*not_too_shallow * (1 - CA) * \ - np.fmax(0, -KRat*cCO3*cCa + 1)**m2 + nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) - return jac00 + selected_depths = not_too_deep * not_too_shallow + two_factors = cCO3 * cCa + three_factors = KRat * two_factors + thr_f_m_one = three_factors - 1 + one_m_thr_f = - thr_f_m_one + + max_thr_f_m_one = np.fmax(0, thr_f_m_one) + + # @njit(nogil=true) + def jac00(): + return -Da * (-CA * (not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ + - nu1 * np.fmax(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_ * \ + (-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + \ + (1 - CA) * (not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ + - nu1 * np.fmax(0, KRat*cCO3*cCa - 1)**m1)) + + # @njit(nogil=true) def jac01(): - jac01 = -CA * Da * lambda_*(-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ - np.fmax(0, cCO3*cCa - 1)**n1) - return jac01 + return -CA * Da * lambda_ * (-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + \ + np.fmax(0, cCO3*cCa - 1)**n1) + # @njit(nogil=true) def jac02(): - jac02 = -Da * (CA * CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3*cCa - 1, 0) \ - * np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + \ - cCO3 * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) * \ - np.fmax(0, -cCO3*cCa + 1) ** (n2-1)) + \ - (1 - CA)*(-CA * KRat * cCO3 *m2 * not_too_deep * not_too_shallow * \ - np.heaviside(-KRat*cCO3*cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1) - \ - KRat * cCO3 * m1 * nu1 * np.heaviside(KRat*cCO3*cCa - 1, 0) * \ - np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1))) - return jac02 + return -Da * (CA *CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1 - 1 ) + cCO3 * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) *\ + np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)) + CA*(1 - CA) * (-KRat * cCO3 * m1 * nu1 *\ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) - \ + KRat * cCO3 * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ + np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1))) + # @njit(nogil=true) def jac03(): - jac03 = -Da * (CA * CC * lambda_ * (cCa * n1* np.heaviside(cCO3*cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ - np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 -1)) + \ - (1 - CA) * (-CA * KRat * cCa * m2 * not_too_deep * not_too_shallow * \ - np.heaviside(-KRat*cCO3*cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1) \ - - KRat * cCa * m1 * nu1 * np.heaviside(KRat*cCO3*cCa - 1, 0) * \ - np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1))) - return jac03 + return -Da * (CA * CC * lambda_ * (cCa * n1 * np.heaviside(cCO3*cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) * \ + np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)) + CA * (1 - CA) * (-KRat * cCa * m1 * nu1 * \ + np.heaviside(KRat*cCO3*cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) \ + - KRat * cCa * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ + np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1))) + # @njit(nogil=true) def jac04(): return np.zeros(no_depths) + # @njit(nogil=True) def jac10(): - jac10 = CC * Da * not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 + return CC * Da * (not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ + - nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) + + # @njit(nogil=true) + def jac11(): + return Da * (CA * (not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 - \ + nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) - CC * lambda_ * \ + (-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1) + \ + lambda_*(1 - CC)*(-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) + + # @njit(nogil=true) + def jac12(): + return Da * (CA * CC * (-KRat * cCO3 * m1 * nu1 * np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ + np.fmax(0, KRat*cCO3*cCa - 1) ** (m1- 1) - KRat * cCO3 * m2 * not_too_deep * \ + not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) + CC* lambda_ * \ + (1 - CC) * (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ + np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) + + + # @njit(nogil=true) + def jac13(): + return Da * (CA * CC * (-KRat * cCa * m1 * nu1 * np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCa * m2 * \ + not_too_deep * not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ + np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 -1)) + CC * lambda_ * \ + (1 - CC) * (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1- 1) + cCa * n2 * nu2 * \ + np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) + + # @njit(nogil=true) + def jac14(): + return np.zeros(no_depths) + + # @njit(nogil=true) + def jac20(): + return Da * (1 - Phi) * (-cCa + delta) * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1)/Phi + + # @njit(nogil=true) + def jac21(): + return -Da * lambda_ * (1 - Phi) * (-cCa + delta) * \ + (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1)/Phi - -CA * Da * lambda_*(-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + \ - np.fmax(0, cCO3*cCa - 1)**n1) + # @njit(nogil=true) + def jac22(): + return Da * (1 - Phi) * (-cCa + delta) * (CA* (-KRat * cCO3 * m1 * nu1 * \ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCO3 * m2 * \ + not_too_deep *not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * \ + (cCO3*n1*np.heaviside(cCO3*cCa - 1, 0) * \ + np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ + np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1)))/Phi - \ + Da * (1 - Phi) * (CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ + (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1)**n1))/Phi + # @njit(nogil=true) + def jac23(): + return Da * (1 - Phi) * (-cCa + delta) * (CA * (-KRat * cCa * m1 * nu1 * \ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - \ + KRat * cCa * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * (cCa * n1 * \ + np.heaviside(cCO3 * cCa - 1, 0) * np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + \ + cCa * n2 * nu2 * np.heaviside(-cCO3 * cCa + 1, 0) * \ + np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1)))/Phi + + # @njit(nogil=true) + def jac24(): + return -Da * (-cCa + delta) * (CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * (-nu2 * \ + np.fmax(0, -cCO3*cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi - Da*(1 - Phi)*(-cCa + delta) * \ + (CA*(not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ + (-nu2*np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi**2 + + # @njit(nogil=true) + def jac30(): + return Da * (1 - Phi) * (-cCO3 + delta) * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1)/Phi + + # @njit(nogil=true) + def jac31(): + return -Da * lambda_ * (1 - Phi) * (-cCO3 + delta) * (-nu2 * \ + np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1)**n1)/Phi + + # @njit(nogil=true) + def jac32(): + return Da * (1 - Phi) * (-cCO3 + delta) * (CA*(-KRat * cCO3 * m1 * nu1 * \ + np.heaviside(KRat*cCO3*cCa - 1, 0) * np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1- 1) - \ + KRat * cCO3 * m2 * not_too_deep * not_too_shallow * \ + np.heaviside(-KRat * cCO3 * cCa + 1, 0) * np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - \ + CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3*cCa - 1, 0) * \ + np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ + np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)))/Phi + + # @njit(nogil=true) + def jac33(): + return Da * (1 - Phi) * (-cCO3 + delta) * (CA* (-KRat * cCa* m1 * nu1 * \ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) - \ + KRat * cCa * m2 * not_too_deep * not_too_shallow * \ + np.heaviside(-KRat * cCO3 * cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1)) \ + - CC * lambda_ * (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ + np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)))/Phi - \ + Da * (1 - Phi) * (CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * (-nu2 * \ + np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi + + # @njit(nogil=true) + def jac34(): + return -Da * (-cCO3 + delta) * (CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC*lambda_*(-nu2 * \ + np.fmax(0, -cCO3*cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi - Da * (1 - Phi) * \ + (-cCO3 + delta) *(CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ + (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi**2 + + # @njit(nogil=true) + def jac40(): + return Da * (1 - Phi) * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) + + # @njit(nogil=true) + def jac41(): + return -Da * lambda_ * (1 - Phi) * (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1) + + # @njit(nogil=true) + def jac42(): + return Da * (1 - Phi) * (CA * (-KRat * cCO3 * m1 * nu1 * \ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCO3 * \ + m2 * not_too_deep * not_too_shallow * \ + np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * \ + (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + \ + cCO3 * n2 * nu2 * np.heaviside(-cCO3 * cCa + 1, 0) * \ + np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) + + # @njit(nogil=true) + def jac43(): + return Da * (1 - Phi) *(CA * (-KRat * cCa * m1 * nu1 * \ + np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCa * m2 * \ + not_too_deep * not_too_shallow * + np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC *lambda_ * \ + (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ + np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ + np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) + + # @njit(nogil=true) + def jac44(): + return -Da * (CA * (not_too_deep * not_too_shallow * \ + np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ + np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ + (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ + np.fmax(0, cCO3 * cCa - 1) ** n1)) row_indices = np.arange(no_depths) col_indices = np.arange(no_depths) all_jac_values_rows_and_cols = [] - for i in prange(no_fields): + for i in range(no_fields): row = i * no_depths + row_indices - for j in prange(no_fields): + for j in range(no_fields): col = j * no_depths + col_indices row_and_col = (row, col) if i == 0 and j == 0: - all_jac_values_rows_and_cols.append(jac00(), row_and_col) + all_jac_values_rows_and_cols.append((jac00(), row_and_col)) elif i == 0 and j == 1: - all_jac_values_rows_and_cols.append(jac01(), row_and_col) + all_jac_values_rows_and_cols.append((jac01(), row_and_col)) elif i == 0 and j == 2: - all_jac_values_rows_and_cols.append(jac02(), row_and_col) + all_jac_values_rows_and_cols.append((jac02(), row_and_col)) elif i == 0 and j == 3: - all_jac_values_rows_and_cols.append(jac03(), row_and_col) + all_jac_values_rows_and_cols.append((jac03(), row_and_col)) elif i == 0 and j == 4: - all_jac_values_rows_and_cols.append(jac04(), row_and_col) + all_jac_values_rows_and_cols.append((jac04(), row_and_col)) elif i==1 and j == 0: - - + all_jac_values_rows_and_cols.append((jac10(), row_and_col)) + elif i==1 and j == 1: + all_jac_values_rows_and_cols.append((jac11(), row_and_col)) + elif i==1 and j == 2: + all_jac_values_rows_and_cols.append((jac12(), row_and_col)) + elif i==1 and j == 3: + all_jac_values_rows_and_cols.append((jac13(), row_and_col)) + elif i==1 and j == 4: + all_jac_values_rows_and_cols.append((jac14(), row_and_col)) + elif i==2 and j == 0: + all_jac_values_rows_and_cols.append((jac20(), row_and_col)) + elif i==2 and j == 1: + all_jac_values_rows_and_cols.append((jac21(), row_and_col)) + elif i==2 and j == 2: + all_jac_values_rows_and_cols.append((jac22(), row_and_col)) + elif i==2 and j == 3: + all_jac_values_rows_and_cols.append((jac23(), row_and_col)) + elif i==2 and j == 4: + all_jac_values_rows_and_cols.append((jac24(), row_and_col)) + elif i==3 and j == 0: + all_jac_values_rows_and_cols.append((jac30(), row_and_col)) + elif i==3 and j == 1: + all_jac_values_rows_and_cols.append((jac31(), row_and_col)) + elif i==3 and j == 2: + all_jac_values_rows_and_cols.append((jac32(), row_and_col)) + elif i==3 and j == 3: + all_jac_values_rows_and_cols.append((jac33(), row_and_col)) + elif i==3 and j == 4: + all_jac_values_rows_and_cols.append((jac34(), row_and_col)) + elif i==4 and j == 0: + all_jac_values_rows_and_cols.append((jac40(), row_and_col)) + elif i==4 and j == 1: + all_jac_values_rows_and_cols.append((jac41(), row_and_col)) + elif i==4 and j == 2: + all_jac_values_rows_and_cols.append((jac42(), row_and_col)) + elif i==4 and j == 3: + all_jac_values_rows_and_cols.append((jac43(), row_and_col)) + elif i==4 and j == 4: + all_jac_values_rows_and_cols.append((jac44(), row_and_col)) return all_jac_values_rows_and_cols diff --git a/Jacobian.txt b/Jacobian.txt index 1324483..ae03ebe 100644 --- a/Jacobian.txt +++ b/Jacobian.txt @@ -3,7 +3,7 @@ Index = 0 --Da*(-CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)) +-Da*(-CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) + CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) + (1 - CA)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)) @@ -11,7 +11,7 @@ Index = 0 Index = 1 --CA*Da*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) +-CA*Da*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) @@ -19,7 +19,7 @@ Index = 1 Index = 2 --Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) +-Da*(CA*CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max)) @@ -27,7 +27,7 @@ Index = 2 Index = 3 --Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) +-Da*(CA*CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max)) @@ -43,7 +43,7 @@ Index = 4 Index = 5 -CC*Da*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) +CC*Da*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) @@ -51,7 +51,7 @@ CC*Da*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, Index = 6 -Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) +Da*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) + lambda_*(1 - CC)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)) @@ -59,7 +59,7 @@ Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, Index = 7 -Da*(CA*CC*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) +Da*(CA*CC*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) + CC*lambda_*(1 - CC)*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) @@ -67,7 +67,7 @@ Da*(CA*CC*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - Index = 8 -Da*(CA*CC*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) +Da*(CA*CC*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) + CC*lambda_*(1 - CC)*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) @@ -83,7 +83,7 @@ Index = 9 Index = 10 -Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCa + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi @@ -91,7 +91,7 @@ Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa Index = 11 --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)/Phi @@ -99,7 +99,7 @@ Index = 11 Index = 12 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi - Da*(1 - Phi)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi @@ -107,7 +107,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)* Index = 13 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi @@ -115,7 +115,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*M Index = 14 --Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 +-Da*(-cCa + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi**2 @@ -123,7 +123,7 @@ Index = 14 Index = 15 -Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi @@ -131,7 +131,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa Index = 16 --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)/Phi @@ -139,7 +139,7 @@ Index = 16 Index = 17 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi @@ -147,7 +147,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1) Index = 18 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi - Da*(1 - Phi)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi @@ -155,7 +155,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)* Index = 19 --Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 +-Da*(-cCO3 + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi**2 @@ -163,7 +163,7 @@ Index = 19 Index = 20 -Da*(1 - Phi)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) +Da*(1 - Phi)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) @@ -171,7 +171,7 @@ Da*(1 - Phi)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1* Index = 21 --Da*lambda_*(1 - Phi)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) +-Da*lambda_*(1 - Phi)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) @@ -179,7 +179,7 @@ Index = 21 Index = 22 -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) @@ -187,7 +187,7 @@ Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO Index = 23 -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) @@ -195,6 +195,6 @@ Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3 Index = 24 --Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) +-Da*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)) diff --git a/Jacobian_adjusted_to_reuse_common_factors.txt b/Jacobian_adjusted_to_reuse_common_factors.txt new file mode 100644 index 0000000..52fbe7b --- /dev/null +++ b/Jacobian_adjusted_to_reuse_common_factors.txt @@ -0,0 +1,200 @@ + + +Index = 0 + + +-Da*(-CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)) + + + + +Index = 1 + + +-CA*Da*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + + + + +Index = 2 + + +-Da*(CA*CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1))) + + + + +Index = 3 + + +-Da*(CA*CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1))) + + + + +Index = 4 + + +0 + + + + +Index = 5 + + +CC*Da*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) + + + + +Index = 6 + + +Da*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) + + + + +Index = 7 + + +Da*(CA*CC*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) + + + + +Index = 8 + + +Da*(CA*CC*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) + + + + +Index = 9 + + +0 + + + + +Index = 10 + + +Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)/Phi + + + + +Index = 11 + + +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)/Phi + + + + +Index = 12 + + +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi + + + + +Index = 13 + + +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi + + + + +Index = 14 + + +-Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi**2 + + + + +Index = 15 + + +Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)/Phi + + + + +Index = 16 + + +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)/Phi + + + + +Index = 17 + + +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi + + + + +Index = 18 + + +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi + + + + +Index = 19 + + +-Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi**2 + + + + +Index = 20 + + +Da*(1 - Phi)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) + + + + +Index = 21 + + +-Da*lambda_*(1 - Phi)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + + + + +Index = 22 + + +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) + + + + +Index = 23 + + +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) + + + + +Index = 24 + + +-Da*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) + + From 104b2461a925a764771db9de18e2e4cf7af9513b Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Wed, 24 Aug 2022 11:10:33 +0200 Subject: [PATCH 04/51] Managed to get @njit(parallel=True) decorator working for looping over all Jacobian indices. I had to bypass a couple of Numba's limitations to get that working. However, it ultimately leads to a memory overflow for long integrations. Removing all njit decorators in Compute_jacobian.py makes it faster! So weird. So something is still wrong at the Numba level there. It is also clear now that, even with a Jacobian, the integrations fail and lead to bogus results such as negative cCO3 concentrations and negative values for Phi, so log Phi leads to a "FloatingPointError: invalid value encountered in log". Big bummer. Perhaps try Radau instead of BDF. Or LSODA? --- Compute_jacobian.py | 581 ++++++++++-------- Jacobian.txt | 46 +- Jacobian_adjusted_to_reuse_common_factors.txt | 46 +- Try_prange_to_fill_array.py | 40 ++ 4 files changed, 404 insertions(+), 309 deletions(-) create mode 100644 Try_prange_to_fill_array.py diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 490e1e4..4c86cd7 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -25,331 +25,386 @@ elements. Truly a sparse matrix!""" import numpy as np -from numba.extending import overload -from numba import njit - -@overload(np.heaviside) -def np_heaviside(x1, x2): - def heaviside_impl(x1, x2): - if x1 < 0: - return 0.0 - elif x1 > 0: - return 1.0 - else: - return x2 - - return heaviside_impl - -""" @overload(np.fmax) -def np_fmax(x1, x2): - def fmax_impl(x1, x2): - if x1 < x2: - return x2 - elif x1 > x2: - return x1 - else: - return x1 - - return fmax_impl """ - -# @njit(nogil=True, parallel = True) -def Jacobian(y, KRat, m1, m2, n1, n2, nu1, nu2, \ - not_too_deep, not_too_shallow, presum, rhorat, lambda_, Da, dCa, \ - dCO3, delta, auxcon, CA_sl, CC_sl, cCa_sl, cCO3_sl, Phi_sl, \ - no_depths, no_fields): +from numba import prange, njit +from numba import float32 as f32 +from numba import int32 as i32 + +def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ + n1, n2, nu1, nu2, not_too_deep, \ + not_too_shallow, lambda_, Da, delta, no_depths, no_fields): """ Retun a sparse (n, n) matrix The Jacobian for five field and five right-hand sides, so 25 elements of which two are zero, so we need to evaluate 23 expressions. """ - - CA = y[CA_sl] - CC = y[CC_sl] - cCa = y[cCa_sl] - cCO3 = y[cCO3_sl] - Phi = y[Phi_sl] - selected_depths = not_too_deep * not_too_shallow two_factors = cCO3 * cCa + two_f_m_one = two_factors -1 + one_m_two_f = -two_f_m_one + max_two_f_m_one = np.fmax(0, two_f_m_one) + max_one_m_two_f = np.fmax(0, one_m_two_f) + hs_two_f_m_one = np.heaviside(two_f_m_one, 0) + hs_one_m_two_f = np.heaviside(one_m_two_f, 0) three_factors = KRat * two_factors thr_f_m_one = three_factors - 1 one_m_thr_f = - thr_f_m_one - max_thr_f_m_one = np.fmax(0, thr_f_m_one) + max_one_m_thr_f = np.fmax(0, one_m_thr_f) + hs_thr_f_m_one = np.heaviside(thr_f_m_one, 0) + hs_one_m_thr_f = np.heaviside(one_m_thr_f, 0) - # @njit(nogil=true) + # @njit(nogil=True) def jac00(): - return -Da * (-CA * (not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ - - nu1 * np.fmax(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_ * \ - (-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + \ - (1 - CA) * (not_too_deep*not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ - - nu1 * np.fmax(0, KRat*cCO3*cCa - 1)**m1)) + return -Da * (-CA * (selected_depths * max_one_m_thr_f ** m2 \ + - nu1 * max_thr_f_m_one**m1) + CC * lambda_ * \ + (-nu2 * max_one_m_two_f**n2 + max_two_f_m_one**n1) + \ + (1 - CA) * (selected_depths * max_one_m_thr_f ** m2 \ + - nu1 * max_thr_f_m_one**m1)) - # @njit(nogil=true) + # @njit(nogil=True) def jac01(): - return -CA * Da * lambda_ * (-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + \ - np.fmax(0, cCO3*cCa - 1)**n1) + return -CA * Da * lambda_ * (-nu2 * max_one_m_two_f**n2 + \ + max_two_f_m_one**n1) - # @njit(nogil=true) + # @njit(nogil=True) def jac02(): - return -Da * (CA *CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1 - 1 ) + cCO3 * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) *\ - np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)) + CA*(1 - CA) * (-KRat * cCO3 * m1 * nu1 *\ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) - \ - KRat * cCO3 * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ - np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1))) - - # @njit(nogil=true) + return -Da * (CA *CC * lambda_ * (cCO3 * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1 ) + cCO3 * n2 * nu2 * hs_one_m_two_f *\ + max_one_m_two_f ** (n2 - 1)) + CA*(1 - CA) * (-KRat * cCO3 * m1 * nu1 *\ + hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ + KRat * cCO3 * m2 * selected_depths * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1))) + + # @njit(nogil=True) def jac03(): - return -Da * (CA * CC * lambda_ * (cCa * n1 * np.heaviside(cCO3*cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * np.heaviside(-cCO3*cCa + 1, 0) * \ - np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)) + CA * (1 - CA) * (-KRat * cCa * m1 * nu1 * \ - np.heaviside(KRat*cCO3*cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) \ - - KRat * cCa * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ - np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1))) - - # @njit(nogil=true) + return -Da * (CA * CC * lambda_ * (cCa * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * hs_one_m_two_f * \ + max_one_m_two_f ** (n2 - 1)) + CA * (1 - CA) * (-KRat * cCa * m1 * nu1 * \ + hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) \ + - KRat * cCa * m2 * selected_depths * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1))) + + # @njit(nogil=True) def jac04(): return np.zeros(no_depths) # @njit(nogil=True) def jac10(): - return CC * Da * (not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 \ - - nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) + return CC * Da * (selected_depths * max_one_m_thr_f ** m2 \ + - nu1 * max_thr_f_m_one ** m1) - # @njit(nogil=true) + # @njit(nogil=True) def jac11(): - return Da * (CA * (not_too_deep * not_too_shallow * np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 - \ - nu1 * np.fmax(0, KRat*cCO3*cCa - 1) ** m1) - CC * lambda_ * \ - (-nu2 * np.fmax(0, -cCO3*cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1) + \ - lambda_*(1 - CC)*(-nu2 * np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) + return Da * (CA * (selected_depths * max_one_m_thr_f ** m2 - \ + nu1 * max_thr_f_m_one ** m1) - CC * lambda_ * \ + (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one ** n1) + \ + lambda_*(1 - CC)*(-nu2 * max_one_m_two_f**n2 + max_two_f_m_one**n1)) - # @njit(nogil=true) + # @njit(nogil=True) def jac12(): - return Da * (CA * CC * (-KRat * cCO3 * m1 * nu1 * np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ - np.fmax(0, KRat*cCO3*cCa - 1) ** (m1- 1) - KRat * cCO3 * m2 * not_too_deep * \ - not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) + CC* lambda_ * \ - (1 - CC) * (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ - np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) + return Da * (CA * CC * (-KRat * cCO3 * m1 * nu1 * hs_thr_f_m_one * \ + max_thr_f_m_one ** (m1- 1) - KRat * cCO3 * m2 * not_too_deep * \ + not_too_shallow * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1)) + CC* lambda_ * \ + (1 - CC) * (cCO3 * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - # @njit(nogil=true) + # @njit(nogil=True) def jac13(): - return Da * (CA * CC * (-KRat * cCa * m1 * nu1 * np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCa * m2 * \ - not_too_deep * not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ - np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 -1)) + CC * lambda_ * \ - (1 - CC) * (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1- 1) + cCa * n2 * nu2 * \ - np.heaviside(-cCO3*cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) - - # @njit(nogil=true) + return Da * (CA * CC * (-KRat * cCa * m1 * nu1 * hs_thr_f_m_one * \ + max_thr_f_m_one ** (m1 - 1) - KRat * cCa * m2 * \ + selected_depths * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 -1)) + CC * lambda_ * \ + (1 - CC) * (cCa * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1- 1) + cCa * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) + + # @njit(nogil=True) def jac14(): return np.zeros(no_depths) - # @njit(nogil=true) + # @njit(nogil=True) def jac20(): - return Da * (1 - Phi) * (-cCa + delta) * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1)/Phi + return Da * (1 - Phi) * (-cCa + delta) * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1)/Phi - # @njit(nogil=true) + # @njit(nogil=True) def jac21(): return -Da * lambda_ * (1 - Phi) * (-cCa + delta) * \ - (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1)/Phi + (-nu2 * max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1)/Phi - # @njit(nogil=true) + # @njit(nogil=True) def jac22(): return Da * (1 - Phi) * (-cCa + delta) * (CA* (-KRat * cCO3 * m1 * nu1 * \ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCO3 * m2 * \ - not_too_deep *not_too_shallow * np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * \ - (cCO3*n1*np.heaviside(cCO3*cCa - 1, 0) * \ - np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ - np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1)))/Phi - \ - Da * (1 - Phi) * (CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ - (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1)**n1))/Phi - - # @njit(nogil=true) + hs_thr_f_m_one * \ + max_thr_f_m_one ** (m1 - 1) - KRat * cCO3 * m2 * \ + not_too_deep *not_too_shallow * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * \ + (cCO3*n1*hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - \ + Da * (1 - Phi) * (CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC * lambda_ * \ + (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one**n1))/Phi + + # @njit(nogil=True) def jac23(): return Da * (1 - Phi) * (-cCa + delta) * (CA * (-KRat * cCa * m1 * nu1 * \ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - \ - KRat * cCa * m2 * not_too_deep * not_too_shallow * np.heaviside(-KRat*cCO3*cCa + 1, 0) * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * (cCa * n1 * \ - np.heaviside(cCO3 * cCa - 1, 0) * np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + \ - cCa * n2 * nu2 * np.heaviside(-cCO3 * cCa + 1, 0) * \ - np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1)))/Phi - - # @njit(nogil=true) + hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ + KRat * cCa * m2 * selected_depths * hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * (cCa * n1 * \ + hs_two_f_m_one * max_two_f_m_one ** (n1 - 1) + \ + cCa * n2 * nu2 * hs_one_m_two_f * \ + max_one_m_two_f ** (n2 - 1)))/Phi + + # @njit(nogil=True) def jac24(): - return -Da * (-cCa + delta) * (CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * (-nu2 * \ - np.fmax(0, -cCO3*cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi - Da*(1 - Phi)*(-cCa + delta) * \ - (CA*(not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ - (-nu2*np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi**2 - - # @njit(nogil=true) + return -Da * (-cCa + delta) * (CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC * lambda_ * (-nu2 * \ + max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1))/Phi - Da*(1 - Phi)*(-cCa + delta) * \ + (CA*(selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * + max_thr_f_m_one ** m1) - CC * lambda_ * \ + (-nu2*max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi**2 + + # @njit(nogil=True) def jac30(): - return Da * (1 - Phi) * (-cCO3 + delta) * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1)/Phi + return Da * (1 - Phi) * (-cCO3 + delta) * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1)/Phi - # @njit(nogil=true) + # @njit(nogil=True) def jac31(): return -Da * lambda_ * (1 - Phi) * (-cCO3 + delta) * (-nu2 * \ - np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1)**n1)/Phi + max_one_m_two_f ** n2 + max_two_f_m_one**n1)/Phi - # @njit(nogil=true) + # @njit(nogil=True) def jac32(): return Da * (1 - Phi) * (-cCO3 + delta) * (CA*(-KRat * cCO3 * m1 * nu1 * \ - np.heaviside(KRat*cCO3*cCa - 1, 0) * np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1- 1) - \ - KRat * cCO3 * m2 * not_too_deep * not_too_shallow * \ - np.heaviside(-KRat * cCO3 * cCa + 1, 0) * np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - \ - CC * lambda_ * (cCO3 * n1 * np.heaviside(cCO3*cCa - 1, 0) * \ - np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCO3 * n2 * nu2 * \ - np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)))/Phi - - # @njit(nogil=true) + hs_thr_f_m_one * max_thr_f_m_one ** (m1- 1) - \ + KRat * cCO3 * m2 * selected_depths * \ + hs_one_m_thr_f * max_one_m_thr_f ** (m2 - 1)) - \ + CC * lambda_ * (cCO3 * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi + + # @njit(nogil=True) def jac33(): return Da * (1 - Phi) * (-cCO3 + delta) * (CA* (-KRat * cCa* m1 * nu1 * \ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * np.fmax(0, KRat*cCO3*cCa - 1) ** (m1 - 1) - \ - KRat * cCa * m2 * not_too_deep * not_too_shallow * \ - np.heaviside(-KRat * cCO3 * cCa + 1, 0) * np.fmax(0, -KRat*cCO3*cCa + 1) ** (m2 - 1)) \ - - CC * lambda_ * (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3*cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ - np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3*cCa + 1) ** (n2 - 1)))/Phi - \ - Da * (1 - Phi) * (CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * (-nu2 * \ - np.fmax(0, -cCO3 * cCa + 1) ** n2 + np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi - - # @njit(nogil=true) + hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ + KRat * cCa * m2 * selected_depths * \ + hs_one_m_thr_f * max_one_m_thr_f ** (m2 - 1)) \ + - CC * lambda_ * (cCa * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - \ + Da * (1 - Phi) * (CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC * lambda_ * (-nu2 * \ + max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi + + # @njit(nogil=True) def jac34(): - return -Da * (-cCO3 + delta) * (CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat*cCO3*cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC*lambda_*(-nu2 * \ - np.fmax(0, -cCO3*cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi - Da * (1 - Phi) * \ - (-cCO3 + delta) *(CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ - (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1))/Phi**2 - - # @njit(nogil=true) + return -Da * (-cCO3 + delta) * (CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC*lambda_*(-nu2 * \ + max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1))/Phi - Da * (1 - Phi) * \ + (-cCO3 + delta) *(CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC * lambda_ * \ + (-nu2 * max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1))/Phi**2 + + # @njit(nogil=True) def jac40(): - return Da * (1 - Phi) * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) + return Da * (1 - Phi) * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - # @njit(nogil=true) + # @njit(nogil=True) def jac41(): - return -Da * lambda_ * (1 - Phi) * (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1) + return -Da * lambda_ * (1 - Phi) * (-nu2 * max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1) - # @njit(nogil=true) + # @njit(nogil=True) def jac42(): return Da * (1 - Phi) * (CA * (-KRat * cCO3 * m1 * nu1 * \ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCO3 * \ - m2 * not_too_deep * not_too_shallow * \ - np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC * lambda_ * \ - (cCO3 * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + \ - cCO3 * n2 * nu2 * np.heaviside(-cCO3 * cCa + 1, 0) * \ - np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) - - # @njit(nogil=true) + hs_thr_f_m_one * \ + max_thr_f_m_one ** (m1 - 1) - KRat * cCO3 * \ + m2 * selected_depths * \ + hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * \ + (cCO3 * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + \ + cCO3 * n2 * nu2 * hs_one_m_two_f * \ + max_one_m_two_f ** (n2 - 1))) + + # @njit(nogil=True) def jac43(): return Da * (1 - Phi) *(CA * (-KRat * cCa * m1 * nu1 * \ - np.heaviside(KRat * cCO3 * cCa - 1, 0) * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** (m1 - 1) - KRat * cCa * m2 * \ - not_too_deep * not_too_shallow * - np.heaviside(-KRat * cCO3 * cCa + 1, 0) * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** (m2 - 1)) - CC *lambda_ * \ - (cCa * n1 * np.heaviside(cCO3 * cCa - 1, 0) * \ - np.fmax(0, cCO3 * cCa - 1) ** (n1 - 1) + cCa * n2 * nu2 * \ - np.heaviside(-cCO3 * cCa + 1, 0) * np.fmax(0, -cCO3 * cCa + 1) ** (n2 - 1))) - - # @njit(nogil=true) + hs_thr_f_m_one * \ + max_thr_f_m_one ** (m1 - 1) - KRat * cCa * m2 * \ + selected_depths * + hs_one_m_thr_f * \ + max_one_m_thr_f ** (m2 - 1)) - CC *lambda_ * \ + (cCa * n1 * hs_two_f_m_one * \ + max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * \ + hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) + + # @njit(nogil=True) def jac44(): - return -Da * (CA * (not_too_deep * not_too_shallow * \ - np.fmax(0, -KRat * cCO3 * cCa + 1) ** m2 - nu1 * \ - np.fmax(0, KRat * cCO3 * cCa - 1) ** m1) - CC * lambda_ * \ - (-nu2 * np.fmax(0, -cCO3 * cCa + 1) ** n2 + \ - np.fmax(0, cCO3 * cCa - 1) ** n1)) + return -Da * (CA * (selected_depths * \ + max_one_m_thr_f ** m2 - nu1 * \ + max_thr_f_m_one ** m1) - CC * lambda_ * \ + (-nu2 * max_one_m_two_f ** n2 + \ + max_two_f_m_one ** n1)) - row_indices = np.arange(no_depths) - col_indices = np.arange(no_depths) - all_jac_values_rows_and_cols = [] - for i in range(no_fields): - row = i * no_depths + row_indices - for j in range(no_fields): - col = j * no_depths + col_indices - row_and_col = (row, col) - if i == 0 and j == 0: - all_jac_values_rows_and_cols.append((jac00(), row_and_col)) - elif i == 0 and j == 1: - all_jac_values_rows_and_cols.append((jac01(), row_and_col)) - elif i == 0 and j == 2: - all_jac_values_rows_and_cols.append((jac02(), row_and_col)) - elif i == 0 and j == 3: - all_jac_values_rows_and_cols.append((jac03(), row_and_col)) - elif i == 0 and j == 4: - all_jac_values_rows_and_cols.append((jac04(), row_and_col)) - elif i==1 and j == 0: - all_jac_values_rows_and_cols.append((jac10(), row_and_col)) - elif i==1 and j == 1: - all_jac_values_rows_and_cols.append((jac11(), row_and_col)) - elif i==1 and j == 2: - all_jac_values_rows_and_cols.append((jac12(), row_and_col)) - elif i==1 and j == 3: - all_jac_values_rows_and_cols.append((jac13(), row_and_col)) - elif i==1 and j == 4: - all_jac_values_rows_and_cols.append((jac14(), row_and_col)) - elif i==2 and j == 0: - all_jac_values_rows_and_cols.append((jac20(), row_and_col)) - elif i==2 and j == 1: - all_jac_values_rows_and_cols.append((jac21(), row_and_col)) - elif i==2 and j == 2: - all_jac_values_rows_and_cols.append((jac22(), row_and_col)) - elif i==2 and j == 3: - all_jac_values_rows_and_cols.append((jac23(), row_and_col)) - elif i==2 and j == 4: - all_jac_values_rows_and_cols.append((jac24(), row_and_col)) - elif i==3 and j == 0: - all_jac_values_rows_and_cols.append((jac30(), row_and_col)) - elif i==3 and j == 1: - all_jac_values_rows_and_cols.append((jac31(), row_and_col)) - elif i==3 and j == 2: - all_jac_values_rows_and_cols.append((jac32(), row_and_col)) - elif i==3 and j == 3: - all_jac_values_rows_and_cols.append((jac33(), row_and_col)) - elif i==3 and j == 4: - all_jac_values_rows_and_cols.append((jac34(), row_and_col)) - elif i==4 and j == 0: - all_jac_values_rows_and_cols.append((jac40(), row_and_col)) - elif i==4 and j == 1: - all_jac_values_rows_and_cols.append((jac41(), row_and_col)) - elif i==4 and j == 2: - all_jac_values_rows_and_cols.append((jac42(), row_and_col)) - elif i==4 and j == 3: - all_jac_values_rows_and_cols.append((jac43(), row_and_col)) - elif i==4 and j == 4: - all_jac_values_rows_and_cols.append((jac44(), row_and_col)) - - return all_jac_values_rows_and_cols - + # @njit(parallel=True, nogil=True) + def compute_all_Jacobian_elements(): + row_indices = np.arange(no_depths) + col_indices = np.arange(no_depths) + n = no_fields * no_depths + all_jac_values = np.zeros((n, n)) + for i in prange(no_fields): + row = i * no_depths + row_indices + for j in prange(no_fields): + col = j * no_depths + col_indices + # row_and_col = (row, col) + if i == 0 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = jac00() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = jac01() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = jac02() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = jac03() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = jac04() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = jac10() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = jac11() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = jac12() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = jac13() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = jac14() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = jac20() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = jac21() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = jac22() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = jac23() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = jac24() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = jac30() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = jac31() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = jac32() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = jac33() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = jac34() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = jac40() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = jac41() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = jac42() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = jac43() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = jac44() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + + return all_jac_values + + return compute_all_Jacobian_elements() diff --git a/Jacobian.txt b/Jacobian.txt index ae03ebe..1324483 100644 --- a/Jacobian.txt +++ b/Jacobian.txt @@ -3,7 +3,7 @@ Index = 0 --Da*(-CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) + CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) + (1 - CA)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)) +-Da*(-CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)) @@ -11,7 +11,7 @@ Index = 0 Index = 1 --CA*Da*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) +-CA*Da*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) @@ -19,7 +19,7 @@ Index = 1 Index = 2 --Da*(CA*CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max)) +-Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) @@ -27,7 +27,7 @@ Index = 2 Index = 3 --Da*(CA*CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max)) +-Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) @@ -43,7 +43,7 @@ Index = 4 Index = 5 -CC*Da*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) +CC*Da*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) @@ -51,7 +51,7 @@ CC*Da*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) Index = 6 -Da*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) + lambda_*(1 - CC)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)) +Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) @@ -59,7 +59,7 @@ Da*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax Index = 7 -Da*(CA*CC*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) + CC*lambda_*(1 - CC)*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) +Da*(CA*CC*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -67,7 +67,7 @@ Da*(CA*CC*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_d Index = 8 -Da*(CA*CC*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) + CC*lambda_*(1 - CC)*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) +Da*(CA*CC*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -83,7 +83,7 @@ Index = 9 Index = 10 -Da*(1 - Phi)*(-cCa + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi +Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi @@ -91,7 +91,7 @@ Da*(1 - Phi)*(-cCa + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi Index = 11 --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi @@ -99,7 +99,7 @@ Index = 11 Index = 12 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi - Da*(1 - Phi)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi @@ -107,7 +107,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max Index = 13 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi @@ -115,7 +115,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - Index = 14 --Da*(-cCa + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi**2 +-Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 @@ -123,7 +123,7 @@ Index = 14 Index = 15 -Da*(1 - Phi)*(-cCO3 + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi @@ -131,7 +131,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1)/Phi Index = 16 --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi @@ -139,7 +139,7 @@ Index = 16 Index = 17 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi @@ -147,7 +147,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max Index = 18 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1)))/Phi - Da*(1 - Phi)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi @@ -155,7 +155,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max Index = 19 --Da*(-cCO3 + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1))/Phi**2 +-Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 @@ -163,7 +163,7 @@ Index = 19 Index = 20 -Da*(1 - Phi)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) +Da*(1 - Phi)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) @@ -171,7 +171,7 @@ Da*(1 - Phi)*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) Index = 21 --Da*lambda_*(1 - Phi)*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1) +-Da*lambda_*(1 - Phi)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) @@ -179,7 +179,7 @@ Index = 21 Index = 22 -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCO3*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCO3*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -187,7 +187,7 @@ Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCO3*m2* Index = 23 -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*right_depth*hsmtfm1*mtfm1_max**m2/mtfm1_max) - CC*lambda_*(cCa*n1*np.heaviside(two_factors - 1)*np.fmax(0, two_factors - 1)**n1/np.fmax(0, two_factors - 1) + cCa*n2*nu2*np.heaviside(-two_factors + 1)*np.fmax(0, -two_factors + 1)**n2/np.fmax(0, -two_factors + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) @@ -195,6 +195,6 @@ Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hstfm1*tfm1_max**m1/tfm1_max - KRat*cCa*m2*ri Index = 24 --Da*(CA*(right_depth*mtfm1_max**m2 - nu1*tfm1_max**m1) - CC*lambda_*(-nu2*np.fmax(0, -two_factors + 1)**n2 + np.fmax(0, two_factors - 1)**n1)) +-Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) diff --git a/Jacobian_adjusted_to_reuse_common_factors.txt b/Jacobian_adjusted_to_reuse_common_factors.txt index 52fbe7b..c104bee 100644 --- a/Jacobian_adjusted_to_reuse_common_factors.txt +++ b/Jacobian_adjusted_to_reuse_common_factors.txt @@ -3,7 +3,7 @@ Index = 0 --Da*(-CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)) +-Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) @@ -11,7 +11,7 @@ Index = 0 Index = 1 --CA*Da*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) +-CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) @@ -19,7 +19,7 @@ Index = 1 Index = 2 --Da*(CA*CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1))) +-Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f)) @@ -27,7 +27,7 @@ Index = 2 Index = 3 --Da*(CA*CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1))) +-Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f)) @@ -43,7 +43,7 @@ Index = 4 Index = 5 -CC*Da*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) +CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) @@ -51,7 +51,7 @@ CC*Da*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np. Index = 6 -Da*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) +Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) @@ -59,7 +59,7 @@ Da*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np Index = 7 -Da*(CA*CC*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) +Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) @@ -67,7 +67,7 @@ Da*(CA*CC*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO Index = 8 -Da*(CA*CC*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) +Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) @@ -83,7 +83,7 @@ Index = 9 Index = 10 -Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi @@ -91,7 +91,7 @@ Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3* Index = 11 --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi @@ -99,7 +99,7 @@ Index = 11 Index = 12 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi @@ -107,7 +107,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - Index = 13 -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi @@ -115,7 +115,7 @@ Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1 Index = 14 --Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi**2 +-Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 @@ -123,7 +123,7 @@ Index = 14 Index = 15 -Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1)/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi @@ -131,7 +131,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3 Index = 16 --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)/Phi +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi @@ -139,7 +139,7 @@ Index = 16 Index = 17 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi @@ -147,7 +147,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - Index = 18 -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi @@ -155,7 +155,7 @@ Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - Index = 19 --Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1))/Phi**2 +-Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 @@ -163,7 +163,7 @@ Index = 19 Index = 20 -Da*(1 - Phi)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) +Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) @@ -171,7 +171,7 @@ Da*(1 - Phi)*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - Index = 21 --Da*lambda_*(1 - Phi)*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1) +-Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) @@ -179,7 +179,7 @@ Index = 21 Index = 22 -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCO3*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) @@ -187,7 +187,7 @@ Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, K Index = 23 -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KRat*cCO3*cCa - 1)**m1/np.fmax(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*np.heaviside(-KRat*cCO3*cCa + 1)*np.fmax(0, -KRat*cCO3*cCa + 1)**m2/np.fmax(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*np.heaviside(cCO3*cCa - 1)*np.fmax(0, cCO3*cCa - 1)**n1/np.fmax(0, cCO3*cCa - 1) + cCa*n2*nu2*np.heaviside(-cCO3*cCa + 1)*np.fmax(0, -cCO3*cCa + 1)**n2/np.fmax(0, -cCO3*cCa + 1))) +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) @@ -195,6 +195,6 @@ Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*np.heaviside(KRat*cCO3*cCa - 1)*np.fmax(0, KR Index = 24 --Da*(CA*(not_too_deep*not_too_shallow*np.fmax(0, -KRat*cCO3*cCa + 1)**m2 - nu1*np.fmax(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*np.fmax(0, -cCO3*cCa + 1)**n2 + np.fmax(0, cCO3*cCa - 1)**n1)) +-Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) diff --git a/Try_prange_to_fill_array.py b/Try_prange_to_fill_array.py new file mode 100644 index 0000000..c5b5505 --- /dev/null +++ b/Try_prange_to_fill_array.py @@ -0,0 +1,40 @@ +from numba import jit, njit, float32 +import numpy as np + +no_depths = 400 +no_fields = 5 + +@njit(nogil=True) +def jac00(): + return np.zeros((no_depths)) + +@njit(nogil=True) +def jac01(): + return np.ones((no_depths)) + +@njit(parallel=True) +def loop_over_all_Jacobian_indices(): + row_indices = np.arange(no_depths) + col_indices = np.arange(no_depths) + n = no_fields * no_depths + all_jac_values = np.empty((n, n)) + for i in range(no_fields): + row = i * no_depths + row_indices + for j in range(no_fields): + col = j * no_depths + col_indices + # row_and_col = (row, col) + if i == 0 and j == 0: + jac_values = jac00() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 1: + jac_values = jac01() + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + # all_jac_values[row, col] = jac01() + else: + for k in range(no_depths): + all_jac_values[row[k], col[k]] = 2 + +loop_over_all_Jacobian_indices() + \ No newline at end of file From 960565168f2be1e5d5865914dc468b71ed491e66 Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Wed, 31 Aug 2022 10:20:29 +0200 Subject: [PATCH 05/51] A jit compiled compiled compute_all_Jacobian_elements function is much slower than the noncompiled version. I still do not understand why and I tried some things to figure this out, e.g. by not using the jac00...jac44 functions, but that did not make a difference. The Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt file should have all the correct Jacobian terms since it comes directly from Derive_Jacobian.py after which I substituted some terms in an editor. --- Compute_jacobian.py | 104 ++++----- ...euse_common_factors_and_powers_cleared.txt | 200 ++++++++++++++++++ 2 files changed, 252 insertions(+), 52 deletions(-) create mode 100644 Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 4c86cd7..2e31f2a 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -52,7 +52,7 @@ def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ hs_thr_f_m_one = np.heaviside(thr_f_m_one, 0) hs_one_m_thr_f = np.heaviside(one_m_thr_f, 0) - # @njit(nogil=True) + """ @njit(nogil=True) def jac00(): return -Da * (-CA * (selected_depths * max_one_m_thr_f ** m2 \ - nu1 * max_thr_f_m_one**m1) + CC * lambda_ * \ @@ -60,12 +60,12 @@ def jac00(): (1 - CA) * (selected_depths * max_one_m_thr_f ** m2 \ - nu1 * max_thr_f_m_one**m1)) - # @njit(nogil=True) + @njit(nogil=True) def jac01(): return -CA * Da * lambda_ * (-nu2 * max_one_m_two_f**n2 + \ max_two_f_m_one**n1) - # @njit(nogil=True) + @njit(nogil=True) def jac02(): return -Da * (CA *CC * lambda_ * (cCO3 * n1 * hs_two_f_m_one * \ max_two_f_m_one ** (n1 - 1 ) + cCO3 * n2 * nu2 * hs_one_m_two_f *\ @@ -74,7 +74,7 @@ def jac02(): KRat * cCO3 * m2 * selected_depths * hs_one_m_thr_f * \ max_one_m_thr_f ** (m2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac03(): return -Da * (CA * CC * lambda_ * (cCa * n1 * hs_two_f_m_one * \ max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * hs_one_m_two_f * \ @@ -83,23 +83,23 @@ def jac03(): - KRat * cCa * m2 * selected_depths * hs_one_m_thr_f * \ max_one_m_thr_f ** (m2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac04(): return np.zeros(no_depths) - # @njit(nogil=True) + @njit(nogil=True) def jac10(): return CC * Da * (selected_depths * max_one_m_thr_f ** m2 \ - nu1 * max_thr_f_m_one ** m1) - # @njit(nogil=True) + @njit(nogil=True) def jac11(): return Da * (CA * (selected_depths * max_one_m_thr_f ** m2 - \ nu1 * max_thr_f_m_one ** m1) - CC * lambda_ * \ (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one ** n1) + \ lambda_*(1 - CC)*(-nu2 * max_one_m_two_f**n2 + max_two_f_m_one**n1)) - # @njit(nogil=True) + @njit(nogil=True) def jac12(): return Da * (CA * CC * (-KRat * cCO3 * m1 * nu1 * hs_thr_f_m_one * \ max_thr_f_m_one ** (m1- 1) - KRat * cCO3 * m2 * not_too_deep * \ @@ -110,7 +110,7 @@ def jac12(): hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac13(): return Da * (CA * CC * (-KRat * cCa * m1 * nu1 * hs_thr_f_m_one * \ max_thr_f_m_one ** (m1 - 1) - KRat * cCa * m2 * \ @@ -120,23 +120,23 @@ def jac13(): max_two_f_m_one ** (n1- 1) + cCa * n2 * nu2 * \ hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac14(): return np.zeros(no_depths) - # @njit(nogil=True) + @njit(nogil=True) def jac20(): return Da * (1 - Phi) * (-cCa + delta) * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ max_thr_f_m_one ** m1)/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac21(): return -Da * lambda_ * (1 - Phi) * (-cCa + delta) * \ (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1)/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac22(): return Da * (1 - Phi) * (-cCa + delta) * (CA* (-KRat * cCO3 * m1 * nu1 * \ hs_thr_f_m_one * \ @@ -151,7 +151,7 @@ def jac22(): max_thr_f_m_one ** m1) - CC * lambda_ * \ (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one**n1))/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac23(): return Da * (1 - Phi) * (-cCa + delta) * (CA * (-KRat * cCa * m1 * nu1 * \ hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ @@ -161,7 +161,7 @@ def jac23(): cCa * n2 * nu2 * hs_one_m_two_f * \ max_one_m_two_f ** (n2 - 1)))/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac24(): return -Da * (-cCa + delta) * (CA * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ @@ -173,18 +173,18 @@ def jac24(): max_thr_f_m_one ** m1) - CC * lambda_ * \ (-nu2*max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi**2 - # @njit(nogil=True) + @njit(nogil=True) def jac30(): return Da * (1 - Phi) * (-cCO3 + delta) * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ max_thr_f_m_one ** m1)/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac31(): return -Da * lambda_ * (1 - Phi) * (-cCO3 + delta) * (-nu2 * \ max_one_m_two_f ** n2 + max_two_f_m_one**n1)/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac32(): return Da * (1 - Phi) * (-cCO3 + delta) * (CA*(-KRat * cCO3 * m1 * nu1 * \ hs_thr_f_m_one * max_thr_f_m_one ** (m1- 1) - \ @@ -194,7 +194,7 @@ def jac32(): max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac33(): return Da * (1 - Phi) * (-cCO3 + delta) * (CA* (-KRat * cCa* m1 * nu1 * \ hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ @@ -208,7 +208,7 @@ def jac33(): max_thr_f_m_one ** m1) - CC * lambda_ * (-nu2 * \ max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi - # @njit(nogil=True) + @njit(nogil=True) def jac34(): return -Da * (-cCO3 + delta) * (CA * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ @@ -221,18 +221,18 @@ def jac34(): (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1))/Phi**2 - # @njit(nogil=True) + @njit(nogil=True) def jac40(): return Da * (1 - Phi) * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ max_thr_f_m_one ** m1) - # @njit(nogil=True) + @njit(nogil=True) def jac41(): return -Da * lambda_ * (1 - Phi) * (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1) - # @njit(nogil=True) + @njit(nogil=True) def jac42(): return Da * (1 - Phi) * (CA * (-KRat * cCO3 * m1 * nu1 * \ hs_thr_f_m_one * \ @@ -245,7 +245,7 @@ def jac42(): cCO3 * n2 * nu2 * hs_one_m_two_f * \ max_one_m_two_f ** (n2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac43(): return Da * (1 - Phi) *(CA * (-KRat * cCa * m1 * nu1 * \ hs_thr_f_m_one * \ @@ -257,15 +257,15 @@ def jac43(): max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * \ hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - # @njit(nogil=True) + @njit(nogil=True) def jac44(): return -Da * (CA * (selected_depths * \ max_one_m_thr_f ** m2 - nu1 * \ max_thr_f_m_one ** m1) - CC * lambda_ * \ (-nu2 * max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1)) + max_two_f_m_one ** n1)) """ - # @njit(parallel=True, nogil=True) + @njit(parallel=True, nogil=True, cache = True) def compute_all_Jacobian_elements(): row_indices = np.arange(no_depths) col_indices = np.arange(no_depths) @@ -278,127 +278,127 @@ def compute_all_Jacobian_elements(): # row_and_col = (row, col) if i == 0 and j == 0: # Need this extra loop because of Numba limitations. - jac_values = jac00() + jac_values = -Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i == 0 and j == 1: # Need this extra loop because of Numba limitations. - jac_values = jac01() + jac_values = -CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i == 0 and j == 2: # Need this extra loop because of Numba limitations. - jac_values = jac02() + jac_values = -Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i == 0 and j == 3: # Need this extra loop because of Numba limitations. - jac_values = jac03() + jac_values = -Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i == 0 and j == 4: # Need this extra loop because of Numba limitations. - jac_values = jac04() + jac_values = np.zeros(no_depths) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==1 and j == 0: # Need this extra loop because of Numba limitations. - jac_values = jac10() + jac_values = CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==1 and j == 1: # Need this extra loop because of Numba limitations. - jac_values = jac11() + jac_values = Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==1 and j == 2: # Need this extra loop because of Numba limitations. - jac_values = jac12() + jac_values = Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==1 and j == 3: # Need this extra loop because of Numba limitations. - jac_values = jac13() + jac_values = Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==1 and j == 4: # Need this extra loop because of Numba limitations. - jac_values = jac14() + jac_values = np.zeros(no_depths) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==2 and j == 0: # Need this extra loop because of Numba limitations. - jac_values = jac20() + jac_values = Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==2 and j == 1: # Need this extra loop because of Numba limitations. - jac_values = jac21() + jac_values = -Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==2 and j == 2: # Need this extra loop because of Numba limitations. - jac_values = jac22() + jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==2 and j == 3: # Need this extra loop because of Numba limitations. - jac_values = jac23() + jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==2 and j == 4: # Need this extra loop because of Numba limitations. - jac_values = jac24() + jac_values = -Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==3 and j == 0: # Need this extra loop because of Numba limitations. - jac_values = jac30() + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==3 and j == 1: # Need this extra loop because of Numba limitations. - jac_values = jac31() + jac_values = -Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==3 and j == 2: # Need this extra loop because of Numba limitations. - jac_values = jac32() + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==3 and j == 3: # Need this extra loop because of Numba limitations. - jac_values = jac33() + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==3 and j == 4: # Need this extra loop because of Numba limitations. - jac_values = jac34() + jac_values = -Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==4 and j == 0: # Need this extra loop because of Numba limitations. - jac_values = jac40() + jac_values = Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==4 and j == 1: # Need this extra loop because of Numba limitations. - jac_values = jac41() + jac_values = -Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==4 and j == 2: # Need this extra loop because of Numba limitations. - jac_values = jac42() + jac_values = Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==4 and j == 3: # Need this extra loop because of Numba limitations. - jac_values = jac43() + jac_values = Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] elif i==4 and j == 4: # Need this extra loop because of Numba limitations. - jac_values = jac44() + jac_values = -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) for k in range(no_depths): all_jac_values[row[k], col[k]] = jac_values[k] diff --git a/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt b/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt new file mode 100644 index 0000000..c062b14 --- /dev/null +++ b/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt @@ -0,0 +1,200 @@ + + +Index = 0 + + +-Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) + + + + +Index = 1 + + +-CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + + + + +Index = 2 + + +-Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) + + + + +Index = 3 + + +-Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) + + + + +Index = 4 + + +0 + + + + +Index = 5 + + +CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + + + + +Index = 6 + + +Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) + + + + +Index = 7 + + +Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + + + + +Index = 8 + + +Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + + + + +Index = 9 + + +0 + + + + +Index = 10 + + +Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi + + + + +Index = 11 + + +-Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi + + + + +Index = 12 + + +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi + + + + +Index = 13 + + +Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi + + + + +Index = 14 + + +-Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 + + + + +Index = 15 + + +Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi + + + + +Index = 16 + + +-Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi + + + + +Index = 17 + + +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi + + + + +Index = 18 + + +Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi + + + + +Index = 19 + + +-Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 + + + + +Index = 20 + + +Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + + + + +Index = 21 + + +-Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + + + + +Index = 22 + + +Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + + + + +Index = 23 + + +Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + + + + +Index = 24 + + +-Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) + + From 783b81cf8401b0b9676ef4c7faaf88a259992c3b Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 5 Sep 2022 10:25:42 +0200 Subject: [PATCH 06/51] Finally managed to jit compile the entire Jacobian function by adding a vectorize decorator to the overloaded np.heaviside function with the help of https://github.com/numba/numba/pull/6552/commits/2ae154f92a5807e53e926386d4238418e29b28ee --- Compute_jacobian.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 2e31f2a..958fd3d 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -25,10 +25,34 @@ elements. Truly a sparse matrix!""" import numpy as np -from numba import prange, njit +from numba import prange, njit, vectorize from numba import float32 as f32 from numba import int32 as i32 +from numba.extending import overload +@vectorize +def _heaviside(x1, x2): + """ vectorized implementation of the heaviside function """ + if np.isnan(x1): + return np.nan + elif x1 == 0: + return x2 + elif x1 < 0: + return 0.0 + else: + return 1.0 + + +@overload(np.heaviside) +def np_heaviside(x1, x2): + + def heaviside_impl(x1, x2): + """ numba implementation of the heaviside function """ + return _heaviside(x1, x2) + + return heaviside_impl + +@njit(nogil= True, parallel = True, cache=True) def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ n1, n2, nu1, nu2, not_too_deep, \ not_too_shallow, lambda_, Da, delta, no_depths, no_fields): @@ -265,7 +289,7 @@ def jac44(): (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1)) """ - @njit(parallel=True, nogil=True, cache = True) + # @njit(parallel=True, nogil=True, cache = True) def compute_all_Jacobian_elements(): row_indices = np.arange(no_depths) col_indices = np.arange(no_depths) From 0db41b789553a2c1507feaa93ffcb33bd47d5204 Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Tue, 6 Sep 2022 14:41:00 +0200 Subject: [PATCH 07/51] Experimenting with speedups from fastmath = True and pip install icc-rt --- Compute_jacobian.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 958fd3d..b969b37 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -52,7 +52,7 @@ def heaviside_impl(x1, x2): return heaviside_impl -@njit(nogil= True, parallel = True, cache=True) +@njit(nogil= True, parallel = True, fastmath=True, cache = True) def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ n1, n2, nu1, nu2, not_too_deep, \ not_too_shallow, lambda_, Da, delta, no_depths, no_fields): @@ -288,8 +288,7 @@ def jac44(): max_thr_f_m_one ** m1) - CC * lambda_ * \ (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1)) """ - - # @njit(parallel=True, nogil=True, cache = True) + def compute_all_Jacobian_elements(): row_indices = np.arange(no_depths) col_indices = np.arange(no_depths) From a49bb4da15c0004ec9da03e0e3dd8c3aedb2ac81 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Wed, 21 Dec 2022 13:32:34 +0100 Subject: [PATCH 08/51] With these changes all computations will be single threaded, since prange has been replaced by range. This is done to investigate if there is an effect on memory use and run time. Less memory use is expected single threaded and perhaps the run times will not increase since integrations seem to scale very poorly with the number of available cores. --- Compute_jacobian.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index b969b37..5961467 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -25,7 +25,7 @@ elements. Truly a sparse matrix!""" import numpy as np -from numba import prange, njit, vectorize +from numba import njit, vectorize from numba import float32 as f32 from numba import int32 as i32 from numba.extending import overload @@ -294,9 +294,9 @@ def compute_all_Jacobian_elements(): col_indices = np.arange(no_depths) n = no_fields * no_depths all_jac_values = np.zeros((n, n)) - for i in prange(no_fields): + for i in range(no_fields): row = i * no_depths + row_indices - for j in prange(no_fields): + for j in range(no_fields): col = j * no_depths + col_indices # row_and_col = (row, col) if i == 0 and j == 0: From 4e0a2668e8c1f5ba279377e6110d8ba4e7b1a599 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Wed, 21 Dec 2022 13:39:13 +0100 Subject: [PATCH 09/51] 'parallel = True' does not make sense in Numba decorators for single threaded computations. --- Compute_jacobian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 5961467..2c02659 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -52,7 +52,7 @@ def heaviside_impl(x1, x2): return heaviside_impl -@njit(nogil= True, parallel = True, fastmath=True, cache = True) +@njit(nogil= True, fastmath=True, cache = True) def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ n1, n2, nu1, nu2, not_too_deep, \ not_too_shallow, lambda_, Da, delta, no_depths, no_fields): From fb795b3a2d18508776b35d7fa3f10ec96011e9a1 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Wed, 21 Dec 2022 14:00:00 +0100 Subject: [PATCH 10/51] fastmath may lead to an accumulation of errors in integrating, so turning that off may lead to more accurate results. Also, 'nogil = True' is no longer needed for single core computations. --- Compute_jacobian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 2c02659..960ac93 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -52,7 +52,7 @@ def heaviside_impl(x1, x2): return heaviside_impl -@njit(nogil= True, fastmath=True, cache = True) +@njit def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ n1, n2, nu1, nu2, not_too_deep, \ not_too_shallow, lambda_, Da, delta, no_depths, no_fields): From 2fd8658d85f22021f29c9a249b3292bce6cf725c Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 8 Jul 2024 14:47:44 +0200 Subject: [PATCH 11/51] This branch showed slow integrations with the use of implicit solvers in combination with calling functional Jacobians. This was attributed to repeated Numba compilations, possibly from Numba problems with nested functions. That is why the compute_all_Jacobian_elements nested function has been removed (as a separate function), but slowness persisted. --- Compute_jacobian.py | 282 +++++++++++++++++++++----------------------- 1 file changed, 136 insertions(+), 146 deletions(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 960ac93..232d398 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -289,149 +289,139 @@ def jac44(): (-nu2 * max_one_m_two_f ** n2 + \ max_two_f_m_one ** n1)) """ - def compute_all_Jacobian_elements(): - row_indices = np.arange(no_depths) - col_indices = np.arange(no_depths) - n = no_fields * no_depths - all_jac_values = np.zeros((n, n)) - for i in range(no_fields): - row = i * no_depths + row_indices - for j in range(no_fields): - col = j * no_depths + col_indices - # row_and_col = (row, col) - if i == 0 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = np.zeros(no_depths) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = np.zeros(no_depths) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - - return all_jac_values - - return compute_all_Jacobian_elements() - - - - - - - + # def compute_all_Jacobian_elements(): + row_indices = np.arange(no_depths) + col_indices = np.arange(no_depths) + n = no_fields * no_depths + all_jac_values = np.zeros((n, n)) + for i in range(no_fields): + row = i * no_depths + row_indices + for j in range(no_fields): + col = j * no_depths + col_indices + # row_and_col = (row, col) + if i == 0 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = -CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i == 0 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = np.zeros(no_depths) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==1 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = np.zeros(no_depths) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = -Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==2 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = -Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==3 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 0: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 1: + # Need this extra loop because of Numba limitations. + jac_values = -Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 2: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 3: + # Need this extra loop because of Numba limitations. + jac_values = Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + elif i==4 and j == 4: + # Need this extra loop because of Numba limitations. + jac_values = -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) + for k in range(no_depths): + all_jac_values[row[k], col[k]] = jac_values[k] + return all_jac_values From 5e58f4ee092414a0f104133347be9955182357a8 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 8 Jul 2024 15:06:49 +0200 Subject: [PATCH 12/51] Hoped to achieve a speedup with cache=True, but this is not the case. --- Compute_jacobian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Compute_jacobian.py b/Compute_jacobian.py index 232d398..0ba031d 100644 --- a/Compute_jacobian.py +++ b/Compute_jacobian.py @@ -52,7 +52,7 @@ def heaviside_impl(x1, x2): return heaviside_impl -@njit +@njit(cache=True) def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ n1, n2, nu1, nu2, not_too_deep, \ not_too_shallow, lambda_, Da, delta, no_depths, no_fields): From 3a5430d4b34609eab22f235671f3d87e68e5ddec Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 29 Aug 2024 14:49:08 +0200 Subject: [PATCH 13/51] =?UTF-8?q?I=20do=20not=20recall=20what=20our=20resu?= =?UTF-8?q?lts=20were=20when=20we=20provided=20analytical=20Jacobians,=20s?= =?UTF-8?q?ince=20that=20was=20a=20long=20time=20ago,=20but=20as=20far=20a?= =?UTF-8?q?s=20I=20remember=20none=20of=20these=20runs=20were=20successful?= =?UTF-8?q?.=20This=20is=20confirmed=20by=20more=20recent=20results=20when?= =?UTF-8?q?=20we=20provided=20a=20Jacobian=20sparsity=20matrix,=20see=20co?= =?UTF-8?q?mmit=202197188:=20the=20diagonals=20should=20be=20banded,=20i.e?= =?UTF-8?q?.=20have=20a=20width=20of=20more=20than=201=20element,=20in=20o?= =?UTF-8?q?rder=20for=20the=20Jacobian=20sparsity=20matrix=20to=20enhance?= =?UTF-8?q?=20integration.=20The=20same=20should=20apply=20for=20analytica?= =?UTF-8?q?l=20Jacobians.=20However,=20the=20off-diagional=20elements=20of?= =?UTF-8?q?=20an=20analytical=20Jacobian=20matrix=20will=20be=20very=20har?= =?UTF-8?q?d=20to=20compute.=20This=20means=20that=20at=20this=20point=20w?= =?UTF-8?q?e=20will=20stop=20our=20efforts=20on=20deriving=20analytical=20?= =?UTF-8?q?Jacobian=20matrices=20and=20only=20provide=20Jacobian=20sparsit?= =?UTF-8?q?y=20matrices.=20For=20some=20background=20on=20why=20Jacobian?= =?UTF-8?q?=20matrices=20are=20banded,=20please=20see=20the=20literature,?= =?UTF-8?q?=20e.g.=20equation=202.58=20(page=2028)=20from=20Finite=20Di?= =?UTF-8?q?=EF=AC=80erence=20Methods=20Finite=20Di=EF=AC=80erence=20Method?= =?UTF-8?q?=20for=20Differential=20Equationsby=20Randall=20J.=20Leveque=20?= =?UTF-8?q?(https://edisciplinas.usp.br/pluginfile.php/41896/mod=5Fresourc?= =?UTF-8?q?e/content/1/LeVeque%20Finite%20Diff.pdf).=20This=20example=20is?= =?UTF-8?q?=20about=20the=20Jacobian=20for=20solving=20the=20pde=20describ?= =?UTF-8?q?ing=20the=20motion=20of=20a=20pendulum=20with=20a=20certain=20m?= =?UTF-8?q?ass=20at=20the=20end=20of=20a=20rigid=20(but=20massless)=20bar.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Compute_jacobian.py | 427 ------------------ Jacobian.txt | 200 -------- Jacobian_adjusted_to_reuse_common_factors.txt | 200 -------- ...euse_common_factors_and_powers_cleared.txt | 200 -------- Try_prange_to_fill_array.py | 40 -- 5 files changed, 1067 deletions(-) delete mode 100644 Compute_jacobian.py delete mode 100644 Jacobian.txt delete mode 100644 Jacobian_adjusted_to_reuse_common_factors.txt delete mode 100644 Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt delete mode 100644 Try_prange_to_fill_array.py diff --git a/Compute_jacobian.py b/Compute_jacobian.py deleted file mode 100644 index 0ba031d..0000000 --- a/Compute_jacobian.py +++ /dev/null @@ -1,427 +0,0 @@ -""" This returns the 25 elements (from 5 fields) of the Jacobian, -computed numerically, using the functional form from Derive_jacobian. -There is also the depth dimension. -In the current implementations of LMAHeureuxPorosityDiff.fun and -LMAHeureuxPorosityDiff.fun_numba, the five fields with each, say, 400 depths, -are treated as 2000 fields, so n = 2000 voor scipy.integrate.solve_ivp. -The solve_ivp documention says that the Jacobian will have shape (n, n), -so (2000, 2000), so calling jac(t, y) should return 4 million numbers! -But most elements will be zero, because derivatives of the five rhs -expressions (equations 40-43 from l'Heureux) wrt to the five fields will only -be non-zero for equal depths. - -Say you want to compute Jacobian element [1,4]. This is -d f_1 / d y_4. That is the derivate of the right hand side of the second -equation (equation 41 from l'Heureux) wrt to field number 5, which is Phi. -We have a functional form for that, from Derive_Jacobian.py, so we can -compute it for all 400 depths. Now where do these 400 numbers end up in -the (2000, 2000) output matrix? For depth 0, it would be element [400, 1600]. -For depth 1, it will be element [401, 1601] and so forth until element -[799, 1999]. So a diagonal within a (400, 400) cell. Ultimately we will fill -25*400 =10000 elements of the 4 million numbers with non-zero values. Actually, -a bit less, because two of the 25 elements of the Jacobian are always zero. -These correspond with the derivatives of the rhs of equations 40 and 41 wrt -Phi. So we have 23 * 400 = 9200 non-zero elements out of 2000 * 2000 = 4e6 -elements. Truly a sparse matrix!""" - -import numpy as np -from numba import njit, vectorize -from numba import float32 as f32 -from numba import int32 as i32 -from numba.extending import overload - -@vectorize -def _heaviside(x1, x2): - """ vectorized implementation of the heaviside function """ - if np.isnan(x1): - return np.nan - elif x1 == 0: - return x2 - elif x1 < 0: - return 0.0 - else: - return 1.0 - - -@overload(np.heaviside) -def np_heaviside(x1, x2): - - def heaviside_impl(x1, x2): - """ numba implementation of the heaviside function """ - return _heaviside(x1, x2) - - return heaviside_impl - -@njit(cache=True) -def Jacobian(CA, CC, cCa, cCO3, Phi, KRat, m1, m2, \ - n1, n2, nu1, nu2, not_too_deep, \ - not_too_shallow, lambda_, Da, delta, no_depths, no_fields): - """ Retun a sparse (n, n) matrix - The Jacobian for five field and five right-hand sides, so 25 elements - of which two are zero, so we need to evaluate 23 expressions. """ - selected_depths = not_too_deep * not_too_shallow - two_factors = cCO3 * cCa - two_f_m_one = two_factors -1 - one_m_two_f = -two_f_m_one - max_two_f_m_one = np.fmax(0, two_f_m_one) - max_one_m_two_f = np.fmax(0, one_m_two_f) - hs_two_f_m_one = np.heaviside(two_f_m_one, 0) - hs_one_m_two_f = np.heaviside(one_m_two_f, 0) - - three_factors = KRat * two_factors - thr_f_m_one = three_factors - 1 - one_m_thr_f = - thr_f_m_one - max_thr_f_m_one = np.fmax(0, thr_f_m_one) - max_one_m_thr_f = np.fmax(0, one_m_thr_f) - hs_thr_f_m_one = np.heaviside(thr_f_m_one, 0) - hs_one_m_thr_f = np.heaviside(one_m_thr_f, 0) - - """ @njit(nogil=True) - def jac00(): - return -Da * (-CA * (selected_depths * max_one_m_thr_f ** m2 \ - - nu1 * max_thr_f_m_one**m1) + CC * lambda_ * \ - (-nu2 * max_one_m_two_f**n2 + max_two_f_m_one**n1) + \ - (1 - CA) * (selected_depths * max_one_m_thr_f ** m2 \ - - nu1 * max_thr_f_m_one**m1)) - - @njit(nogil=True) - def jac01(): - return -CA * Da * lambda_ * (-nu2 * max_one_m_two_f**n2 + \ - max_two_f_m_one**n1) - - @njit(nogil=True) - def jac02(): - return -Da * (CA *CC * lambda_ * (cCO3 * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1 ) + cCO3 * n2 * nu2 * hs_one_m_two_f *\ - max_one_m_two_f ** (n2 - 1)) + CA*(1 - CA) * (-KRat * cCO3 * m1 * nu1 *\ - hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ - KRat * cCO3 * m2 * selected_depths * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1))) - - @njit(nogil=True) - def jac03(): - return -Da * (CA * CC * lambda_ * (cCa * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * hs_one_m_two_f * \ - max_one_m_two_f ** (n2 - 1)) + CA * (1 - CA) * (-KRat * cCa * m1 * nu1 * \ - hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) \ - - KRat * cCa * m2 * selected_depths * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1))) - - @njit(nogil=True) - def jac04(): - return np.zeros(no_depths) - - @njit(nogil=True) - def jac10(): - return CC * Da * (selected_depths * max_one_m_thr_f ** m2 \ - - nu1 * max_thr_f_m_one ** m1) - - @njit(nogil=True) - def jac11(): - return Da * (CA * (selected_depths * max_one_m_thr_f ** m2 - \ - nu1 * max_thr_f_m_one ** m1) - CC * lambda_ * \ - (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one ** n1) + \ - lambda_*(1 - CC)*(-nu2 * max_one_m_two_f**n2 + max_two_f_m_one**n1)) - - @njit(nogil=True) - def jac12(): - return Da * (CA * CC * (-KRat * cCO3 * m1 * nu1 * hs_thr_f_m_one * \ - max_thr_f_m_one ** (m1- 1) - KRat * cCO3 * m2 * not_too_deep * \ - not_too_shallow * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1)) + CC* lambda_ * \ - (1 - CC) * (cCO3 * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - - - @njit(nogil=True) - def jac13(): - return Da * (CA * CC * (-KRat * cCa * m1 * nu1 * hs_thr_f_m_one * \ - max_thr_f_m_one ** (m1 - 1) - KRat * cCa * m2 * \ - selected_depths * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 -1)) + CC * lambda_ * \ - (1 - CC) * (cCa * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1- 1) + cCa * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - - @njit(nogil=True) - def jac14(): - return np.zeros(no_depths) - - @njit(nogil=True) - def jac20(): - return Da * (1 - Phi) * (-cCa + delta) * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1)/Phi - - @njit(nogil=True) - def jac21(): - return -Da * lambda_ * (1 - Phi) * (-cCa + delta) * \ - (-nu2 * max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1)/Phi - - @njit(nogil=True) - def jac22(): - return Da * (1 - Phi) * (-cCa + delta) * (CA* (-KRat * cCO3 * m1 * nu1 * \ - hs_thr_f_m_one * \ - max_thr_f_m_one ** (m1 - 1) - KRat * cCO3 * m2 * \ - not_too_deep *not_too_shallow * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * \ - (cCO3*n1*hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - \ - Da * (1 - Phi) * (CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC * lambda_ * \ - (-nu2 * max_one_m_two_f ** n2 + max_two_f_m_one**n1))/Phi - - @njit(nogil=True) - def jac23(): - return Da * (1 - Phi) * (-cCa + delta) * (CA * (-KRat * cCa * m1 * nu1 * \ - hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ - KRat * cCa * m2 * selected_depths * hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * (cCa * n1 * \ - hs_two_f_m_one * max_two_f_m_one ** (n1 - 1) + \ - cCa * n2 * nu2 * hs_one_m_two_f * \ - max_one_m_two_f ** (n2 - 1)))/Phi - - @njit(nogil=True) - def jac24(): - return -Da * (-cCa + delta) * (CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC * lambda_ * (-nu2 * \ - max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1))/Phi - Da*(1 - Phi)*(-cCa + delta) * \ - (CA*(selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * - max_thr_f_m_one ** m1) - CC * lambda_ * \ - (-nu2*max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi**2 - - @njit(nogil=True) - def jac30(): - return Da * (1 - Phi) * (-cCO3 + delta) * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1)/Phi - - @njit(nogil=True) - def jac31(): - return -Da * lambda_ * (1 - Phi) * (-cCO3 + delta) * (-nu2 * \ - max_one_m_two_f ** n2 + max_two_f_m_one**n1)/Phi - - @njit(nogil=True) - def jac32(): - return Da * (1 - Phi) * (-cCO3 + delta) * (CA*(-KRat * cCO3 * m1 * nu1 * \ - hs_thr_f_m_one * max_thr_f_m_one ** (m1- 1) - \ - KRat * cCO3 * m2 * selected_depths * \ - hs_one_m_thr_f * max_one_m_thr_f ** (m2 - 1)) - \ - CC * lambda_ * (cCO3 * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCO3 * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - - @njit(nogil=True) - def jac33(): - return Da * (1 - Phi) * (-cCO3 + delta) * (CA* (-KRat * cCa* m1 * nu1 * \ - hs_thr_f_m_one * max_thr_f_m_one ** (m1 - 1) - \ - KRat * cCa * m2 * selected_depths * \ - hs_one_m_thr_f * max_one_m_thr_f ** (m2 - 1)) \ - - CC * lambda_ * (cCa * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1)))/Phi - \ - Da * (1 - Phi) * (CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC * lambda_ * (-nu2 * \ - max_one_m_two_f ** n2 + max_two_f_m_one ** n1))/Phi - - @njit(nogil=True) - def jac34(): - return -Da * (-cCO3 + delta) * (CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC*lambda_*(-nu2 * \ - max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1))/Phi - Da * (1 - Phi) * \ - (-cCO3 + delta) *(CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC * lambda_ * \ - (-nu2 * max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1))/Phi**2 - - @njit(nogil=True) - def jac40(): - return Da * (1 - Phi) * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - - @njit(nogil=True) - def jac41(): - return -Da * lambda_ * (1 - Phi) * (-nu2 * max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1) - - @njit(nogil=True) - def jac42(): - return Da * (1 - Phi) * (CA * (-KRat * cCO3 * m1 * nu1 * \ - hs_thr_f_m_one * \ - max_thr_f_m_one ** (m1 - 1) - KRat * cCO3 * \ - m2 * selected_depths * \ - hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1)) - CC * lambda_ * \ - (cCO3 * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + \ - cCO3 * n2 * nu2 * hs_one_m_two_f * \ - max_one_m_two_f ** (n2 - 1))) - - @njit(nogil=True) - def jac43(): - return Da * (1 - Phi) *(CA * (-KRat * cCa * m1 * nu1 * \ - hs_thr_f_m_one * \ - max_thr_f_m_one ** (m1 - 1) - KRat * cCa * m2 * \ - selected_depths * - hs_one_m_thr_f * \ - max_one_m_thr_f ** (m2 - 1)) - CC *lambda_ * \ - (cCa * n1 * hs_two_f_m_one * \ - max_two_f_m_one ** (n1 - 1) + cCa * n2 * nu2 * \ - hs_one_m_two_f * max_one_m_two_f ** (n2 - 1))) - - @njit(nogil=True) - def jac44(): - return -Da * (CA * (selected_depths * \ - max_one_m_thr_f ** m2 - nu1 * \ - max_thr_f_m_one ** m1) - CC * lambda_ * \ - (-nu2 * max_one_m_two_f ** n2 + \ - max_two_f_m_one ** n1)) """ - - # def compute_all_Jacobian_elements(): - row_indices = np.arange(no_depths) - col_indices = np.arange(no_depths) - n = no_fields * no_depths - all_jac_values = np.zeros((n, n)) - for i in range(no_fields): - row = i * no_depths + row_indices - for j in range(no_fields): - col = j * no_depths + col_indices - # row_and_col = (row, col) - if i == 0 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = np.zeros(no_depths) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==1 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = np.zeros(no_depths) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==2 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==3 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 0: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 1: - # Need this extra loop because of Numba limitations. - jac_values = -Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 2: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 3: - # Need this extra loop because of Numba limitations. - jac_values = Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i==4 and j == 4: - # Need this extra loop because of Numba limitations. - jac_values = -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - return all_jac_values diff --git a/Jacobian.txt b/Jacobian.txt deleted file mode 100644 index 1324483..0000000 --- a/Jacobian.txt +++ /dev/null @@ -1,200 +0,0 @@ - - -Index = 0 - - --Da*(-CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) + CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + (1 - CA)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)) - - - - -Index = 1 - - --CA*Da*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - - - - -Index = 2 - - --Da*(CA*CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) - - - - -Index = 3 - - --Da*(CA*CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1))) - - - - -Index = 4 - - -0 - - - - -Index = 5 - - -CC*Da*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - - - - -Index = 6 - - -Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) + lambda_*(1 - CC)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) - - - - -Index = 7 - - -Da*(CA*CC*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) - - - - -Index = 8 - - -Da*(CA*CC*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) + CC*lambda_*(1 - CC)*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) - - - - -Index = 9 - - -0 - - - - -Index = 10 - - -Da*(1 - Phi)*(-cCa + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - - - - -Index = 11 - - --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi - - - - -Index = 12 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - - - - -Index = 13 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - - - - -Index = 14 - - --Da*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 - - - - -Index = 15 - - -Da*(1 - Phi)*(-cCO3 + delta)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1)/Phi - - - - -Index = 16 - - --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)/Phi - - - - -Index = 17 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - - - - -Index = 18 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1)))/Phi - Da*(1 - Phi)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - - - - -Index = 19 - - --Da*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1))/Phi**2 - - - - -Index = 20 - - -Da*(1 - Phi)*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - - - - -Index = 21 - - --Da*lambda_*(1 - Phi)*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1) - - - - -Index = 22 - - -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCO3*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCO3*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCO3*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) - - - - -Index = 23 - - -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*Heaviside(KRat*cCO3*cCa - 1)*Max(0, KRat*cCO3*cCa - 1)**m1/Max(0, KRat*cCO3*cCa - 1) - KRat*cCa*m2*not_too_deep*not_too_shallow*Heaviside(-KRat*cCO3*cCa + 1)*Max(0, -KRat*cCO3*cCa + 1)**m2/Max(0, -KRat*cCO3*cCa + 1)) - CC*lambda_*(cCa*n1*Heaviside(cCO3*cCa - 1)*Max(0, cCO3*cCa - 1)**n1/Max(0, cCO3*cCa - 1) + cCa*n2*nu2*Heaviside(-cCO3*cCa + 1)*Max(0, -cCO3*cCa + 1)**n2/Max(0, -cCO3*cCa + 1))) - - - - -Index = 24 - - --Da*(CA*(not_too_deep*not_too_shallow*Max(0, -KRat*cCO3*cCa + 1)**m2 - nu1*Max(0, KRat*cCO3*cCa - 1)**m1) - CC*lambda_*(-nu2*Max(0, -cCO3*cCa + 1)**n2 + Max(0, cCO3*cCa - 1)**n1)) - - diff --git a/Jacobian_adjusted_to_reuse_common_factors.txt b/Jacobian_adjusted_to_reuse_common_factors.txt deleted file mode 100644 index c104bee..0000000 --- a/Jacobian_adjusted_to_reuse_common_factors.txt +++ /dev/null @@ -1,200 +0,0 @@ - - -Index = 0 - - --Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) - - - - -Index = 1 - - --CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - - - - -Index = 2 - - --Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f)) - - - - -Index = 3 - - --Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f)) - - - - -Index = 4 - - -0 - - - - -Index = 5 - - -CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - - - - -Index = 6 - - -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - - - - -Index = 7 - - -Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) - - - - -Index = 8 - - -Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) - - - - -Index = 9 - - -0 - - - - -Index = 10 - - -Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - - - - -Index = 11 - - --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - - - - -Index = 12 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - - - - -Index = 13 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - - - - -Index = 14 - - --Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - - - - -Index = 15 - - -Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - - - - -Index = 16 - - --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - - - - -Index = 17 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - - - - -Index = 18 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - - - - -Index = 19 - - --Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - - - - -Index = 20 - - -Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - - - - -Index = 21 - - --Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - - - - -Index = 22 - - -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) - - - - -Index = 23 - - -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**m1/max_thr_f_m_one - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**m2/max_one_m_thr_f) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**n1/max_two_f_m_one + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**n2/max_one_m_two_f)) - - - - -Index = 24 - - --Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - - diff --git a/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt b/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt deleted file mode 100644 index c062b14..0000000 --- a/Jacobian_adjusted_to_reuse_common_factors_and_powers_cleared.txt +++ /dev/null @@ -1,200 +0,0 @@ - - -Index = 0 - - --Da*(-CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) + CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + (1 - CA)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)) - - - - -Index = 1 - - --CA*Da*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - - - - -Index = 2 - - --Da*(CA*CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - - - - -Index = 3 - - --Da*(CA*CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)) + CA*(1 - CA)*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1))) - - - - -Index = 4 - - -0 - - - - -Index = 5 - - -CC*Da*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - - - - -Index = 6 - - -Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) + lambda_*(1 - CC)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - - - - -Index = 7 - - -Da*(CA*CC*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - - - - -Index = 8 - - -Da*(CA*CC*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) + CC*lambda_*(1 - CC)*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - - - - -Index = 9 - - -0 - - - - -Index = 10 - - -Da*(1 - Phi)*(-cCa + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - - - - -Index = 11 - - --Da*lambda_*(1 - Phi)*(-cCa + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - - - - -Index = 12 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - - - - -Index = 13 - - -Da*(1 - Phi)*(-cCa + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - - - - -Index = 14 - - --Da*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCa + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - - - - -Index = 15 - - -Da*(1 - Phi)*(-cCO3 + delta)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1)/Phi - - - - -Index = 16 - - --Da*lambda_*(1 - Phi)*(-cCO3 + delta)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)/Phi - - - - -Index = 17 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - - - - -Index = 18 - - -Da*(1 - Phi)*(-cCO3 + delta)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1)))/Phi - Da*(1 - Phi)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - - - - -Index = 19 - - --Da*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi - Da*(1 - Phi)*(-cCO3 + delta)*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1))/Phi**2 - - - - -Index = 20 - - -Da*(1 - Phi)*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - - - - -Index = 21 - - --Da*lambda_*(1 - Phi)*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1) - - - - -Index = 22 - - -Da*(1 - Phi)*(CA*(-KRat*cCO3*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCO3*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCO3*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCO3*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - - - - -Index = 23 - - -Da*(1 - Phi)*(CA*(-KRat*cCa*m1*nu1*hs_thr_f_m_one*max_thr_f_m_one**(m1-1) - KRat*cCa*m2*selected_depths*hs_one_m_thr_f*max_one_m_thr_f**(m2-1)) - CC*lambda_*(cCa*n1*hs_two_f_m_one*max_two_f_m_one**(n1-1) + cCa*n2*nu2*hs_one_m_two_f*max_one_m_two_f**(n2-1))) - - - - -Index = 24 - - --Da*(CA*(selected_depths*max_one_m_thr_f**m2 - nu1*max_thr_f_m_one**m1) - CC*lambda_*(-nu2*max_one_m_two_f**n2 + max_two_f_m_one**n1)) - - diff --git a/Try_prange_to_fill_array.py b/Try_prange_to_fill_array.py deleted file mode 100644 index c5b5505..0000000 --- a/Try_prange_to_fill_array.py +++ /dev/null @@ -1,40 +0,0 @@ -from numba import jit, njit, float32 -import numpy as np - -no_depths = 400 -no_fields = 5 - -@njit(nogil=True) -def jac00(): - return np.zeros((no_depths)) - -@njit(nogil=True) -def jac01(): - return np.ones((no_depths)) - -@njit(parallel=True) -def loop_over_all_Jacobian_indices(): - row_indices = np.arange(no_depths) - col_indices = np.arange(no_depths) - n = no_fields * no_depths - all_jac_values = np.empty((n, n)) - for i in range(no_fields): - row = i * no_depths + row_indices - for j in range(no_fields): - col = j * no_depths + col_indices - # row_and_col = (row, col) - if i == 0 and j == 0: - jac_values = jac00() - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - elif i == 0 and j == 1: - jac_values = jac01() - for k in range(no_depths): - all_jac_values[row[k], col[k]] = jac_values[k] - # all_jac_values[row, col] = jac01() - else: - for k in range(no_depths): - all_jac_values[row[k], col[k]] = 2 - -loop_over_all_Jacobian_indices() - \ No newline at end of file From 7f8cde8df47538409256e0755c195b516de5f7ec Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 29 Aug 2024 15:00:29 +0200 Subject: [PATCH 14/51] We are updating this branch to provide for the same modularity as 'main'. This means that parameters will be in a separate file and not in ScenarioA.py. Also, we want to include the marlpde folder. --- marlpde/Evolve_scenario.py | 125 ++++--- marlpde/LHeureux_model.py | 698 ++++++++++++++++++++++--------------- marlpde/parameters.py | 57 +-- 3 files changed, 532 insertions(+), 348 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index a8ac670..2e006ae 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -1,13 +1,15 @@ #!/usr/bin/env python from datetime import datetime +import time import os from dataclasses import asdict import inspect +from scipy.integrate import solve_ivp import matplotlib.pyplot as plt +from tqdm import tqdm import h5py -from pde import CartesianGrid, ScalarField, FileStorage, LivePlotTracker -from pde import DataTracker +from pde import CartesianGrid, ScalarField, FileStorage from pde.grids.operators.cartesian import _make_derivative from parameters import Map_Scenario, Solver, Tracker from LHeureux_model import LMAHeureuxPorosityDiff @@ -41,12 +43,24 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): depths.register_operator("grad_forw", \ lambda grid: _make_derivative(grid, method="forward")) + # Setting initial values for all five fields in three steps. + # This is perhaps more involved than necessary, since the + # end result is a 1D Numpy array with a length of five times + # the number of depths. The number five comes from the five + # fields we are tracking, by integrating five pdes. + # First step. AragoniteSurface = ScalarField(depths, CAIni) CalciteSurface = ScalarField(depths, CCIni) CaSurface = ScalarField(depths, cCaIni) CO3Surface = ScalarField(depths, cCO3Ini) PorSurface = ScalarField(depths, PhiIni) + # Second step. + state = eq.get_state(AragoniteSurface, CalciteSurface, CaSurface, + CO3Surface, PorSurface) + # Third step. + y0 = state.data.ravel() + # I need those two fields for computing coA, which is rather involved. # There may be a simpler way of selecting these depths, but I haven't # found one yet. For now these two Heaviside step functions. @@ -55,20 +69,77 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): not_too_deep = ScalarField.from_expression(depths, f"heaviside({DeepLimit/Xstar}-x, 0)") - # Not all keys from kwargs are LMAHeureuxPorosityDiff arguments. + # Not all keys from pde_parms are LMAHeureuxPorosityDiff arguments. # Taken from https://stackoverflow.com/questions/334655/passing-a-\ # dictionary-to-a-function-as-keyword-parameters - filtered_kwargs = {k: v for k, v in pde_parms.items() if k in [p.name for p - in inspect.signature(LMAHeureuxPorosityDiff).parameters.\ - values()]} + filtered_pde_parms = {k: v for k, v in pde_parms.items() if k in [p.name for + p in + inspect.signature(LMAHeureuxPorosityDiff).parameters.\ + values()]} - eq = LMAHeureuxPorosityDiff(AragoniteSurface, CalciteSurface, CaSurface, - CO3Surface, PorSurface, not_too_shallow, - not_too_deep, **filtered_kwargs) + slices_for_all_fields = [slice(i * number_of_depths, (i+1) * number_of_depths) \ + for i in range(5)] - state = eq.get_state(AragoniteSurface, CalciteSurface, CaSurface, - CO3Surface, PorSurface) + eq = LMAHeureuxPorosityDiff(depths, slices_for_all_fields, not_too_shallow, + not_too_deep, **filtered_pde_parms) + + start_computing = time.time() + with tqdm(total=number_of_progress_updates) as pbar: + t0 = solver_parms["t_span"][0] + end_time = solver_parms["t_span"][1] + no_progress_updates = tracker_parms["no_progress_updates"] + progress_bar_args = [pbar, (end_time - t0) / no_progress_updates, t0] + + sol = solve_ivp(fun=eq.fun_numba, y0=y0, **solver_parms, + t_eval= tracker_parms["t_eval"], + events = [eq.zeros, eq.zeros_CA, eq.zeros_CC, \ + eq.ones_CA_plus_CC, eq.ones_Phi, eq.zeros_U, eq.zeros_W], + args=progress_bar_args) + end_computing = time.time() + print() + print("Number of rhs evaluations = {0} \n".format(sol.nfev)) + print("Number of Jacobian evaluations = {0} \n".format(sol.njev)) + print("Number of LU decompositions = {0} \n".format(sol.nlu)) + print("Status = {0} \n".format(sol.status)) + print("Success = {0} \n".format(sol.success)) + f = sol.t_events[0] + print(("Times, in years, at which any field at any depth crossed zero: "\ + +', '.join(['%.2f']*len(f))+"") % tuple([Tstar * time for time in f])) + print() + g = sol.t_events[1] + print(("Times, in years, at which CA at any depth crossed zero: "\ + +', '.join(['%.2f']*len(g))+"") % tuple([Tstar * time for time in g])) + print() + h = sol.t_events[2] + print(("Times, in years, at which CC at any depth crossed zero: "\ + +', '.join(['%.2f']*len(h))+"") % tuple([Tstar * time for time in h])) + print() + k = sol.t_events[3] + print(("Times, in years, at which CA + CC at any depth crossed one: "\ + +', '.join(['%.2f']*len(k))+"") % tuple([Tstar * time for time in k])) + print() + l = sol.t_events[4] + print(("Times, in years, at which the porosity at any depth crossed one: "\ + +', '.join(['%.2f']*len(l))+"") % tuple([Tstar * time for time in l])) + print() + m = sol.t_events[5] + print(("Times, in years, at which U at any depth crossed zero: "\ + +', '.join(['%.2f']*len(m))+"") % tuple([Tstar * time for time in m])) + print() + n = sol.t_events[6] + print(("Times, in years, at which W at any depth crossed zero: "\ + +', '.join(['%.2f']*len(n))+"") % tuple([Tstar * time for time in n])) + print() + + print("Message from solve_ivp = {0} \n".format(sol.message)) + print(("Time taken for solve_ivp is " + "{0:.2f}s. \n".format(end_computing - start_computing))) + + if sol.status == 0: + covered_time = Tstar * end_time + else: + covered_time = pbar.n * Tstar * end_time /number_of_progress_updates # Store your results somewhere in a subdirectory of a parent directory. store_folder = "../Results/" + \ datetime.now().strftime("%d_%m_%Y_%H_%M_%S" + "/") @@ -78,37 +149,6 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): storage_parms = solver_parms | tracker_parms | pde_parms storage = FileStorage(stored_results, info=storage_parms) - if tracker_parms["live_plotting"]: - live_plots = LivePlotTracker(interval=\ - tracker_parms["plotting_interval"], \ - title="Integration results", - show=True, max_fps=1, \ - plot_args ={"ax_style": {"ylim": (0, 1.5)}}) - else: - live_plots = None - - if tracker_parms["track_U_at_bottom"]: - data_tracker = DataTracker(eq.track_U_at_bottom, \ - interval = tracker_parms["data_tracker_interval"]) - else: - data_tracker = None - - sol, info = eq.solve(state, **solver_parms, tracker=["progress", \ - storage.tracker(\ - tracker_parms["progress_tracker_interval"]),\ - live_plots, data_tracker]) - - print() - print(f"Meta-information about the solution : {info} \n") - - covered_time_span = Tstar * info["controller"]["t_final"] - - if tracker_parms["track_U_at_bottom"]: - with h5py.File(stored_results, 'a') as hf: - U_grp = hf.create_group("U") - U_grp.create_dataset("U_at_bottom", \ - data=data_tracker.dataframe.to_numpy()) - return sol, covered_time_span, depths, Xstar, store_folder def Plot_results(sol, covered_time, depths, Xstar, store_folder): @@ -138,3 +178,4 @@ def Plot_results(sol, covered_time, depths, Xstar, store_folder): solution, covered_time, depths, Xstar, store_folder = \ integrate_equations(solver_parms, tracker_parms, pde_parms) Plot_results(solution, covered_time, depths, Xstar, store_folder) + diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index b5422ac..89b65d4 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,26 +1,33 @@ import numpy as np -from pde import FieldCollection, PDEBase, ScalarField +import line_profiler +from pde import FieldCollection, PDEBase, ScalarField, FieldBase from numba import njit -np.seterr(divide="raise", over="raise", under="raise", invalid="raise") - -class LMAHeureuxPorosityDiff(PDEBase): - - def __init__(self, AragoniteSurface, CalciteSurface, CaSurface, - CO3Surface, PorSurface, not_too_shallow, not_too_deep, CA0, CC0, - cCa0, cCO30, Phi0, sedimentationrate, Xstar, Tstar, k1, k2, k3, - k4, m1, m2, n1, n2, b, beta, rhos, rhow, rhos0, KA, KC, muA, - D0Ca, PhiNR, PhiInfty, PhiIni, DCa, DCO3): - - self.AragoniteSurface = AragoniteSurface - self.CalciteSurface = CalciteSurface - self.CaSurface = CaSurface - self.CO3Surface = CO3Surface - self.PorSurface = PorSurface - self.bc_CA = [{"value": CA0}, {"curvature": 0}] - self.bc_CC = [{"value": CC0}, {"curvature": 0}] +np.seterr(divide="raise", over="raise", under="warn", invalid="raise") +from scipy.sparse import dia_matrix, lil_matrix, csr_matrix, find +from Compute_jacobian import Jacobian +from pde.grids.operators.cartesian import _make_derivative + +class LMAHeureuxPorosityDiff(): + + def __init__(self, Depths, slices_all_fields, CA0, CC0, cCa0, cCO30, Phi0, + sedimentationrate, Xstar, Tstar, k1, k2, k3, k4, m1, m2, n1, + n2, b, beta, rhos, rhow, rhos0, KA, KC, muA, D0Ca, PhiNR, + PhiInfty, PhiIni, DCa, DCO3, not_too_shallow, not_too_deep, + FV_switch): + self.no_fields = 5 + self.Depths = Depths + self.Depths.register_operator("grad_back", \ + lambda grid: _make_derivative(grid, method="backward")) + self.Depths.register_operator("grad_forw", \ + lambda grid: _make_derivative(grid, method="forward")) + self.delta_x = self.Depths._axes_coords[0][1] - \ + self.Depths._axes_coords[0][0] + self.slices_all_fields = slices_all_fields + self.bc_CA = [{"value": CA0}, {"curvature" : 0}] + self.bc_CC = [{"value": CC0}, {"curvature": 0}] self.bc_cCa = [{"value": cCa0}, {"derivative": 0}] self.bc_cCO3 = [{"value": cCO30}, {"derivative": 0}] - self.bc_Phi = [{"value": Phi0}, {"derivative": 0}] + self.bc_Phi = [{"value": Phi0}, {"derivative": 0}] self.sedimentationrate = sedimentationrate self.Xstar = Xstar self.Tstar = Tstar @@ -49,9 +56,6 @@ def __init__(self, AragoniteSurface, CalciteSurface, CaSurface, self.Phi0 = Phi0 self.DCa = DCa self.DCO3 = DCO3 - self.not_too_shallow = not_too_shallow - self.not_too_deep = not_too_deep - self.g = 100 * 9.81 self.dCa = self.DCa / self.D0Ca self.dCO3 = self.DCO3 / self.D0Ca @@ -65,27 +69,72 @@ def __init__(self, AragoniteSurface, CalciteSurface, CaSurface, self.rhorat = (self.rhos / self.rhow - 1) * self.beta / \ self.sedimentationrate self.presum = 1 - self.rhorat0 * self.Phi0 ** 3 * \ - (1 - np.exp(10 - 10 / self.Phi0)) / (1 - self.Phi0) - - # Fiadeiro-Veronis differentiation involves a coth and a reciprocal, which can + (1 - np.exp(10 - 10 / self.Phi0)) / (1 - self.Phi0) + self.not_too_shallow = not_too_shallow.data + self.not_too_deep = not_too_deep.data + self.FV_switch = FV_switch + + self.CA_sl= self.slices_all_fields[0] + self.CC_sl = self.slices_all_fields[1] + self.cCa_sl = self.slices_all_fields[2] + self.cCO3_sl = self.slices_all_fields[3] + self.Phi_sl = self.slices_all_fields[4] + + # Fiadeiro-Veronis integration involves a coth and a reciprocal, which can # easily lead to FloatingPointError: overflow encountered in double_scalars. # To avoid this, better revert to either backwards or central differencing # the Peclet number is very large or very small. self.Peclet_min = 1e-2 self.Peclet_max = 1/self.Peclet_min - # Need this number for Fiadeiro-Veronis differentiation. - self.delta_x = self.AragoniteSurface.grid._axes_coords[0][1] - \ - self.AragoniteSurface.grid._axes_coords[0][0] + + self.last_t = 0. # Helper variable for progress bar. + + # Make operators for use in Numba compiled (i.e. jit compiled) functions. + # Instead of the default central differenced gradient from py-pde + # construct forward and backward differenced gradients and apply + # either one of them, based on the sign of U. + self.CA_grad_back_op = self.Depths.make_operator("grad_back", self.bc_CA) + self.CA_grad_forw_op = self.Depths.make_operator("grad_forw", self.bc_CA) + self.CC_grad_back_op = self.Depths.make_operator("grad_back", self.bc_CC) + self.CC_grad_forw_op = self.Depths.make_operator("grad_forw", self.bc_CC) + # Instead of the default central differenced gradient from py-pde + # construct forward and backward differenced gradients and give them + # appropriate weights according to a Fiadeiro-Veronis scheme. + self.cCa_grad_back_op = self.Depths.make_operator("grad_back", self.bc_cCa) + self.cCa_grad_forw_op = self.Depths.make_operator("grad_forw", self.bc_cCa) + self.cCa_laplace_op = self.Depths.make_operator("laplace", self.bc_cCa) + self.cCO3_grad_back_op = self.Depths.make_operator("grad_back", self.bc_cCO3) + self.cCO3_grad_forw_op = self.Depths.make_operator("grad_forw", self.bc_cCO3) + self.cCO3_laplace_op = self.Depths.make_operator("laplace", self.bc_cCO3) + self.Phi_grad_back_op = self.Depths.make_operator("grad_back", self.bc_Phi) + self.Phi_grad_forw_op = self.Depths.make_operator("grad_forw", self.bc_Phi) + self.Phi_laplace_op = self.Depths.make_operator("laplace", self.bc_Phi) + + # Make sure integration stops when we field values become less than zero + # or more than one, in some cases. Or just register that this is happening + # and continue integration, which corresponds to "False". + setattr(self.zeros.__func__, "terminal", False) + setattr(self.zeros_CA.__func__, "terminal", False) + setattr(self.zeros_CC.__func__, "terminal", False) + setattr(self.ones_CA_plus_CC.__func__, "terminal", False) + setattr(self.ones_Phi.__func__, "terminal", False) + setattr(self.zeros_U.__func__, "terminal", False) + setattr(self.zeros_W.__func__, "terminal", False) + + # Accommodate for fixed porosity diffusion coefficient. + # Beware that the functional Jacobian has not been aligned with this, + # i.e. it was derived using a porosity diffusion coefficient depending + # on a time-varying porosity. This will all be fine if you do not set + # 'jac=eq.jac' in solve_ivp, but leave it empty such that a numerically + # approximated Jacobian will be used. self.PhiIni = PhiIni self.F_fixed = 1 - np.exp(10 - 10 / self.PhiIni) self.dPhi_fixed = self.auxcon * self.F_fixed *\ - self.PhiIni ** 3 / (1 - self.PhiIni) - + self.PhiIni ** 3 / (1 - self.PhiIni) def get_state(self, AragoniteSurface, CalciteSurface, CaSurface, CO3Surface, PorSurface): - # Return initial state and register forward and backward difference - # operators. + """generate a suitable initial state""" AragoniteSurface.label = "ARA" CalciteSurface.label = "CAL" CaSurface.label = "Ca" @@ -95,39 +144,10 @@ def get_state(self, AragoniteSurface, CalciteSurface, CaSurface, CO3Surface, return FieldCollection([AragoniteSurface, CalciteSurface, CaSurface, CO3Surface, PorSurface]) - - def track_U_at_bottom(self, state, t): - # First, extract the porosity at the bottom of the system. - # The derived quantities will then also be at the bottom of the system. - Phi = state.data[4][-1] - F = 1 - np.exp(10 - 10 / Phi) - one_minus_Phi = 1 - Phi - U_bottom = self.presum + self.rhorat * Phi ** 3 * F /one_minus_Phi - return {"U at bottom": U_bottom} - @staticmethod @njit def calculate_sigma(Peclet, W_data, Peclet_min, Peclet_max): - ''' Calculate sigma following formula 8.73 from Boudreau: - "Diagenetic Models and their implementation" - - Parameters - ---------- - Peclet: ndarray(dtype=float, ndim=1) - Array along depth of the Peclet numbers. - W-data: ndarray(dtype=float, ndim=1) - Array along depth of the velocity of the pore water - (counted positive downwards) - Peclet_min: float - Lower limit for calculating 1/tanh(Peclet) - Peclet_max: float - Upper limit for calculating 1/tanh(Peclet) - - Returns - ------- - sigma: ndarray(dtype=float, ndim=1) - Array along depth with sigma values - ''' + # Assuming the arrays are 1D. sigma = np.empty(Peclet.size) for i in range(sigma.size): if np.abs(Peclet[i]) < Peclet_min: @@ -137,10 +157,26 @@ def calculate_sigma(Peclet, W_data, Peclet_min, Peclet_max): else: sigma[i] = np.cosh(Peclet[i])/np.sinh(Peclet[i]) - \ 1/Peclet[i] - return sigma - - def evolution_rate(self, state, t=0): - CA, CC, cCa, cCO3, Phi = state + return sigma + + @line_profiler.profile + def fun(self, t, y, progress_proxy, progress_dt, t0): + """ + For tqdm to monitor progress. + From + https://stackoverflow.com/questions/59047892/ + how-to-monitor-the-process-of-scipy-odeint """ + if self.last_t == 0.: + self.last_t = t0 + n = int((t - self.last_t) / progress_dt) + progress_proxy.update(n) + self.last_t += n * progress_dt + + CA = ScalarField(self.Depths, y[self.slices_all_fields[0]]) + CC = ScalarField(self.Depths, y[self.slices_all_fields[1]]) + cCa = ScalarField(self.Depths, y[self.slices_all_fields[2]]) + cCO3 = ScalarField(self.Depths, y[self.slices_all_fields[3]]) + Phi = ScalarField(self.Depths, y[self.slices_all_fields[4]]) two_factors = cCa * cCO3 two_factors_upp_lim = two_factors.to_scalar(lambda f: np.fmin(f,1)) @@ -158,20 +194,20 @@ def evolution_rate(self, state, t=0): (1 - two_factors_upp_lim) ** self.n2) F = 1 - np.exp(10 - 10 / Phi) - one_minus_Phi = 1 - Phi - U = self.presum + self.rhorat * Phi ** 3 * F /one_minus_Phi - - # Choose either forward or backward differencing for CA and CC - # depending on the sign of U + U = self.presum + self.rhorat * Phi ** 3 * F / (1 - Phi) + + # Instead of the default central differenced gradient from py-pde + # construct forward and backward differenced gradients and apply + # either one of them, based on the sign of U. CA_grad_back = CA.apply_operator("grad_back", self.bc_CA) CA_grad_forw = CA.apply_operator("grad_forw", self.bc_CA) - CA_grad = ScalarField(state.grid, np.where(U.data>0, CA_grad_back.data, \ + CA_grad = ScalarField(self.Depths, np.where(U.data>0, CA_grad_back.data, \ CA_grad_forw.data)) CC_grad_back = CC.apply_operator("grad_back", self.bc_CC) - CC_grad_forw = CC.apply_operator("grad_forw", self.bc_CC) - CC_grad = ScalarField(state.grid, np.where(U.data>0, CC_grad_back.data, \ + CC_grad_forw = CC.apply_operator("grad_forw", self.bc_CC) + CC_grad = ScalarField(self.Depths, np.where(U.data>0, CC_grad_back.data, \ CC_grad_forw.data)) W = self.presum - self.rhorat * Phi ** 2 * F @@ -184,182 +220,219 @@ def evolution_rate(self, state, t=0): # Implementing equation 6 from l'Heureux. denominator = 1 - 2 * np.log(Phi) - - # Fiadeiro-Veronis scheme for equations 42 and 43 - # from l'Heureux. - common_Peclet = W * self.delta_x / 2. - Peclet_cCa = common_Peclet * denominator/ self.dCa - sigma_cCa_data = LMAHeureuxPorosityDiff.calculate_sigma(\ - Peclet_cCa.data, W.data, self.Peclet_min, self.Peclet_max) - sigma_cCa = ScalarField(state.grid, sigma_cCa_data) - - Peclet_cCO3 = common_Peclet * denominator/ self.dCO3 - sigma_cCO3_data = LMAHeureuxPorosityDiff.calculate_sigma(\ - Peclet_cCO3.data, W.data, self.Peclet_min, self.Peclet_max) - sigma_cCO3 = ScalarField(state.grid, sigma_cCO3_data) - - # dPhi = self.auxcon * F * (Phi ** 3) / one_minus_Phi + # dPhi = self.auxcon * F * (Phi ** 3) / (1 - Phi) dPhi = self.dPhi_fixed - Peclet_Phi = common_Peclet / dPhi - sigma_Phi_data = LMAHeureuxPorosityDiff.calculate_sigma(\ - Peclet_Phi.data, W.data, self.Peclet_min, self.Peclet_max) - sigma_Phi = ScalarField(state.grid, sigma_Phi_data) - + if self.FV_switch: + # Fiadeiro-Veronis scheme for equations 42 and 43 + # from l'Heureux. + common_Peclet = W * self.delta_x / 2. + Peclet_cCa = common_Peclet * denominator/ self.dCa + sigma_cCa_data = LMAHeureuxPorosityDiff.calculate_sigma(\ + Peclet_cCa.data, W.data, self.Peclet_min, self.Peclet_max) + sigma_cCa = ScalarField(self.Depths, sigma_cCa_data) + + Peclet_cCO3 = common_Peclet * denominator/ self.dCO3 + sigma_cCO3_data = LMAHeureuxPorosityDiff.calculate_sigma(\ + Peclet_cCO3.data, W.data, self.Peclet_min, self.Peclet_max) + sigma_cCO3 = ScalarField(self.Depths, sigma_cCO3_data) + + Peclet_Phi = common_Peclet / dPhi + sigma_Phi_data = LMAHeureuxPorosityDiff.calculate_sigma(\ + Peclet_Phi.data, W.data, self.Peclet_min, self.Peclet_max) + sigma_Phi = ScalarField(self.Depths, sigma_Phi_data) + else: + sigma_cCa = 0 + sigma_cCO3 = 0 + sigma_Phi = 0 + + # Instead of the default central differenced gradient from py-pde + # construct forward and backward differenced gradients and give them + # appropriate weights according to a Fiadeiro-Veronis scheme. cCa_grad_back = cCa.apply_operator("grad_back", self.bc_cCa) - cCa_grad_forw = cCa.apply_operator("grad_forw", self.bc_cCa) + cCa_grad_forw = cCa.apply_operator("grad_forw", self.bc_cCa) cCa_grad = 0.5 * ((1-sigma_cCa) * cCa_grad_forw +\ (1+sigma_cCa) * cCa_grad_back) + cCa_laplace = cCa.laplace(self.bc_cCa) cCO3_grad_back = cCO3.apply_operator("grad_back", self.bc_cCO3) cCO3_grad_forw = cCO3.apply_operator("grad_forw", self.bc_cCO3) cCO3_grad = 0.5 * ((1-sigma_cCO3) * cCO3_grad_forw +\ (1+sigma_cCO3) * cCO3_grad_back) + cCO3_laplace = cCO3.laplace(self.bc_cCO3) Phi_grad_back = Phi.apply_operator("grad_back", self.bc_Phi) Phi_grad_forw = Phi.apply_operator("grad_forw", self.bc_Phi) Phi_grad = 0.5 * ((1-sigma_Phi) * Phi_grad_forw +\ (1+sigma_Phi) * Phi_grad_back) + Phi_laplace = Phi.laplace(self.bc_Phi) Phi_denom = Phi/denominator grad_Phi_denom = Phi_grad * (denominator + 2) / denominator ** 2 common_helper = coA - self.lambda_ * coC + + dcCa_dt = (cCa_grad * grad_Phi_denom + Phi_denom * cCa_laplace) \ + * self.dCa /Phi - W * cCa_grad \ + + self.Da * (1 - Phi) * (self.delta - cCa) * common_helper / Phi - dcCa_dt = (cCa_grad * grad_Phi_denom + Phi_denom * cCa.laplace(self.bc_cCa)) \ - * self.dCa /Phi -W * cCa_grad \ - + self.Da * one_minus_Phi * (self.delta - cCa) * common_helper / Phi - - dcCO3_dt = (cCO3_grad * grad_Phi_denom + Phi_denom * cCO3.laplace(self.bc_cCO3)) \ - * self.dCO3/Phi -W * cCO3_grad \ - + self.Da * one_minus_Phi * (self.delta - cCO3) * common_helper / Phi + dcCO3_dt = (cCO3_grad * grad_Phi_denom + Phi_denom * cCO3_laplace) \ + * self.dCO3/Phi - W * cCO3_grad \ + + self.Da * (1 - Phi) * (self.delta - cCO3) * common_helper / Phi dW_dx = -self.rhorat * Phi_grad * (2 * Phi * F + 10 * (F - 1)) - # This is closer to the original form of (43) from l' Heureux than - # the Matlab implementation. dPhi_dt = - (Phi * dW_dx + W * Phi_grad) \ - + dPhi * Phi.laplace(self.bc_Phi) \ - + self.Da * one_minus_Phi * common_helper - - return FieldCollection([dCA_dt, dCC_dt, dcCa_dt, dcCO3_dt, dPhi_dt]) - - def _make_pde_rhs_numba(self, state): - """ the numba-accelerated evolution equation """ - # make attributes locally available + + dPhi * Phi_laplace \ + + self.Da * (1 - Phi) * common_helper + + return FieldCollection([dCA_dt, dCC_dt, dcCa_dt, dcCO3_dt, dPhi_dt]).data.ravel() + + @line_profiler.profile + def fun_numba(self, t, y, progress_proxy, progress_dt, t0): + """ For tqdm to monitor progress. + From + https://stackoverflow.com/questions/59047892/ + how-to-monitor-the-process-of-scipy-odeint """ + if self.last_t == 0.: + self.last_t = t0 + n = int((t - self.last_t) / progress_dt) + progress_proxy.update(n) + self.last_t += n * progress_dt + + """ the numba-accelerated evolution equation """ KRat = self.KRat m1 = self.m1 - m2 = self.m2 + m2 = self.m2 n1 = self.n1 n2 = self.n2 nu1 = self.nu1 nu2 = self.nu2 - not_too_deep = self.not_too_deep.data - not_too_shallow = self.not_too_shallow.data + not_too_deep = self.not_too_deep + not_too_shallow = self.not_too_shallow presum = self.presum - rhorat= self.rhorat + rhorat = self.rhorat lambda_ = self.lambda_ - Da = self.Da + Da= self.Da dCa = self.dCa dCO3 = self.dCO3 delta = self.delta - # The following three numbers are also needed for Fiadeiro-Veronis. - dPhi_fixed = self.dPhi_fixed + auxcon = self.auxcon + delta_x = self.delta_x Peclet_min = self.Peclet_min Peclet_max = self.Peclet_max - delta_x = state.grid._axes_coords[0][1] - state.grid._axes_coords[0][0] - grad_back_CA = state.grid.make_operator("grad_back", bc = self.bc_CA) - grad_forw_CA = state.grid.make_operator("grad_forw", bc = self.bc_CA) - grad_back_CC = state.grid.make_operator("grad_back", bc = self.bc_CC) - grad_forw_CC = state.grid.make_operator("grad_forw", bc = self.bc_CC) - grad_back_cCa = state.grid.make_operator("grad_back", bc = self.bc_cCa) - grad_forw_cCa = state.grid.make_operator("grad_forw", bc = self.bc_cCa) - laplace_cCa = state.grid.make_operator("laplace", bc = self.bc_cCa) - grad_back_cCO3 = state.grid.make_operator("grad_back", bc = self.bc_cCO3) - grad_forw_cCO3 = state.grid.make_operator("grad_forw", bc = self.bc_cCO3) - laplace_cCO3 = state.grid.make_operator("laplace", bc = self.bc_cCO3) - grad_back_Phi = state.grid.make_operator("grad_back", bc = self.bc_Phi) - grad_forw_Phi = state.grid.make_operator("grad_forw", bc = self.bc_Phi) - laplace_Phi = state.grid.make_operator("laplace", bc = self.bc_Phi) - - @njit - def pde_rhs(state_data, t=0): - """ compiled helper function evaluating right hand side """ - # Instead of the default central differenced gradient from py-pde - # construct forward and backward differenced gradients and apply - # either one of them, based on the sign of U. - CA = state_data[0] - CA_grad_back = grad_back_CA(CA) - CA_grad_forw = grad_forw_CA(CA) - - CC = state_data[1] - CC_grad_back = grad_back_CC(CC) - CC_grad_forw = grad_forw_CC(CC) - - cCa = state_data[2] - cCa_grad_back = grad_back_cCa(cCa) - cCa_grad_forw = grad_forw_cCa(cCa) - cCa_laplace = laplace_cCa(cCa) - - cCO3 = state_data[3] - cCO3_grad_back = grad_back_cCO3(cCO3) - cCO3_grad_forw = grad_forw_cCO3(cCO3) - cCO3_laplace = laplace_cCO3(cCO3) - - Phi = state_data[4] - Phi_grad_back = grad_back_Phi(Phi) - Phi_grad_forw = grad_forw_Phi(Phi) - Phi_laplace = laplace_Phi(Phi) - - rate = np.empty_like(state_data) - - # state_data.size should be the same as len(CA) or len(CC), check this. - # So the number of depths, really. - no_depths = state_data[0].size - - denominator = np.empty(no_depths) - common_helper1 = np.empty(no_depths) - common_helper2 = np.empty(no_depths) - helper_cCa_grad = np.empty(no_depths) - helper_cCO3_grad = np.empty(no_depths) - F = np.empty(no_depths) - U = np.empty(no_depths) - W = np.empty(no_depths) - two_factors = np.empty(no_depths) - two_factors_upp_lim = np.empty(no_depths) - two_factors_low_lim = np.empty(no_depths) - three_factors = np.empty(no_depths) - three_factors_upp_lim = np.empty(no_depths) - three_factors_low_lim = np.empty(no_depths) - coA = np.empty(no_depths) - coC = np.empty(no_depths) - common_helper3 = np.empty(no_depths) - dPhi = np.empty(no_depths) - dW_dx = np.empty(no_depths) - one_minus_Phi = np.empty(no_depths) - CA_grad = np.empty(no_depths) - CC_grad = np.empty(no_depths) - cCa_grad = np.empty(no_depths) - cCO3_grad = np.empty(no_depths) - Phi_grad = np.empty(no_depths) - - for i in range(no_depths): - F[i] = 1 - np.exp(10 - 10 / Phi[i]) - - U[i] = presum + rhorat * Phi[i] ** 3 * F[i]/ (1 - Phi[i]) - - if U[i] > 0: - CA_grad[i] = CA_grad_back[i] - CC_grad[i] = CC_grad_back[i] - else: - CA_grad[i] = CA_grad_forw[i] - CC_grad[i] = CC_grad_forw[i] + no_depths = self.Depths.shape[0] + dPhi_fixed = self.dPhi_fixed + FV_switch = self.FV_switch + + CA = y[self.CA_sl] + CC = y[self.CC_sl] + cCa = y[self.cCa_sl] + cCO3 = y[self.cCO3_sl] + Phi = y[self.Phi_sl] + + CA_grad_back_op = self.CA_grad_back_op + CA_grad_forw_op = self.CA_grad_forw_op + CC_grad_back_op = self.CC_grad_back_op + CC_grad_forw_op = self.CC_grad_forw_op + cCa_grad_back_op = self.cCa_grad_back_op + cCa_grad_forw_op = self.cCa_grad_forw_op + cCa_laplace_op = self.cCa_laplace_op + cCO3_grad_back_op = self.cCO3_grad_back_op + cCO3_grad_forw_op = self.cCO3_grad_forw_op + cCO3_laplace_op = self.cCO3_laplace_op + Phi_grad_back_op = self.Phi_grad_back_op + Phi_grad_forw_op = self.Phi_grad_forw_op + Phi_laplace_op = self.Phi_laplace_op + + return LMAHeureuxPorosityDiff.pde_rhs(CA, CC, cCa, cCO3, Phi, + CA_grad_back_op, CA_grad_forw_op, + CC_grad_back_op, CC_grad_forw_op, + cCa_grad_back_op, cCa_grad_forw_op, + cCa_laplace_op, cCO3_grad_back_op, + cCO3_grad_forw_op, cCO3_laplace_op, + Phi_grad_back_op, Phi_grad_forw_op, + Phi_laplace_op, KRat, m1, m2, n1, + n2, nu1, nu2, not_too_deep, + not_too_shallow, presum, rhorat, + lambda_, Da, dCa, dCO3, delta, + auxcon, delta_x, Peclet_min, + Peclet_max, no_depths, dPhi_fixed, + FV_switch) - W[i] = presum - rhorat * Phi[i] ** 2 * F[i] + @staticmethod + @njit(cache=True) + def pde_rhs(CA, CC, cCa, cCO3, Phi, CA_grad_back_op, CA_grad_forw_op, + CC_grad_back_op, CC_grad_forw_op, + cCa_grad_back_op, cCa_grad_forw_op, cCa_laplace_op, + cCO3_grad_back_op, cCO3_grad_forw_op, cCO3_laplace_op, + Phi_grad_back_op, Phi_grad_forw_op, Phi_laplace_op, + KRat, m1, m2, n1, n2, nu1, nu2, not_too_deep, not_too_shallow, + presum, rhorat, lambda_, Da, dCa, dCO3, delta, auxcon, delta_x, + Peclet_min, Peclet_max, no_depths, dPhi_fixed, FV_switch): + + CA_grad_back = CA_grad_back_op(CA) + CA_grad_forw = CA_grad_forw_op(CA) + CC_grad_back = CC_grad_back_op(CC) + CC_grad_forw = CC_grad_forw_op(CC) + cCa_grad_back = cCa_grad_back_op(cCa) + cCa_grad_forw = cCa_grad_forw_op(cCa) + cCa_laplace = cCa_laplace_op(cCa) + cCO3_grad_back = cCO3_grad_back_op(cCO3) + cCO3_grad_forw = cCO3_grad_forw_op(cCO3) + cCO3_laplace = cCO3_laplace_op(cCO3) + Phi_grad_back = Phi_grad_back_op(Phi) + Phi_grad_forw = Phi_grad_forw_op(Phi) + Phi_laplace = Phi_laplace_op(Phi) + + denominator = np.empty(no_depths) + common_helper1 = np.empty(no_depths) + common_helper2 = np.empty(no_depths) + helper_cCa_grad = np.empty(no_depths) + helper_cCO3_grad = np.empty(no_depths) + F = np.empty(no_depths) + U = np.empty(no_depths) + W = np.empty(no_depths) + two_factors = np.empty(no_depths) + two_factors_upp_lim = np.empty(no_depths) + two_factors_low_lim = np.empty(no_depths) + three_factors = np.empty(no_depths) + three_factors_upp_lim = np.empty(no_depths) + three_factors_low_lim = np.empty(no_depths) + coA = np.empty(no_depths) + coC = np.empty(no_depths) + common_helper3 = np.empty(no_depths) + rate = np.empty(5 * no_depths) + dPhi = np.empty(no_depths) + dW_dx = np.empty(no_depths) + one_minus_Phi = np.empty(no_depths) + CA_grad = np.empty(no_depths) + CC_grad = np.empty(no_depths) + cCa_grad = np.empty(no_depths) + cCO3_grad = np.empty(no_depths) + Phi_grad = np.empty(no_depths) + + for i in range(no_depths): + F[i] = 1 - np.exp(10 - 10 / Phi[i]) + + U[i] = presum + rhorat * Phi[i] ** 3 * F[i]/ (1 - Phi[i]) + + if U[i] > 0: + CA_grad[i] = CA_grad_back[i] + CC_grad[i] = CC_grad_back[i] + else: + CA_grad[i] = CA_grad_forw[i] + CC_grad[i] = CC_grad_forw[i] + + W[i] = presum - rhorat * Phi[i] ** 2 * F[i] - # Implementing equation 6 from l'Heureux. - denominator[i] = 1 - 2 * np.log(Phi[i]) + # Implementing equation 6 from l'Heureux. + denominator[i] = 1 - 2 * np.log(Phi[i]) + one_minus_Phi[i] = 1 - Phi[i] + # dPhi[i] = auxcon * F[i] * (Phi[i] ** 3) / one_minus_Phi[i] + dPhi[i] = dPhi_fixed + if FV_switch: # Fiadeiro-Veronis scheme for equations 42 and 43 # from l'Heureux. Peclet_cCa = W[i] * delta_x * denominator[i]/ (2. * dCa ) @@ -368,8 +441,7 @@ def pde_rhs(state_data, t=0): elif np.abs(Peclet_cCa) > Peclet_max: sigma_cCa = np.sign(W[i]) else: - sigma_cCa = np.cosh(Peclet_cCa)/np.sinh(Peclet_cCa) - \ - 1/Peclet_cCa + sigma_cCa = np.cosh(Peclet_cCa)/np.sinh(Peclet_cCa) - 1/Peclet_cCa Peclet_cCO3 = W[i] * delta_x * denominator[i]/ (2. * dCO3) if np.abs(Peclet_cCO3) < Peclet_min: @@ -377,78 +449,148 @@ def pde_rhs(state_data, t=0): elif np.abs(Peclet_cCO3) > Peclet_max: sigma_cCO3 = np.sign(W[i]) else: - sigma_cCO3 = np.cosh(Peclet_cCO3)/np.sinh(Peclet_cCO3) - \ - 1/Peclet_cCO3 + sigma_cCO3 = np.cosh(Peclet_cCO3)/np.sinh(Peclet_cCO3) - 1/Peclet_cCO3 - one_minus_Phi[i] = 1 - Phi[i] - dPhi[i] = dPhi_fixed Peclet_Phi = W[i] * delta_x / (2. * dPhi[i]) if np.abs(Peclet_Phi) < Peclet_min: sigma_Phi = 0 elif np.abs(Peclet_Phi) > Peclet_max: sigma_Phi = np.sign(W[i]) else: - sigma_Phi = np.cosh(Peclet_Phi)/np.sinh(Peclet_Phi) - \ - 1/Peclet_Phi - - cCa_grad[i] = 0.5 * ((1-sigma_cCa) * cCa_grad_forw[i] + \ - (1+sigma_cCa) * cCa_grad_back[i]) - cCO3_grad[i] = 0.5 * ((1-sigma_cCO3) * cCO3_grad_forw[i] + \ - (1+sigma_cCO3) * cCO3_grad_back[i]) - Phi_grad[i] = 0.5 * ((1-sigma_Phi) * Phi_grad_forw [i]+ \ - (1+sigma_Phi) * Phi_grad_back[i]) - - common_helper1[i] = Phi[i]/denominator[i] - common_helper2[i] = Phi_grad[i] * (2 + denominator[i]) \ - / denominator[i] ** 2 - helper_cCa_grad[i] = dCa * (common_helper2[i] * cCa_grad[i] \ - + common_helper1[i] * cCa_laplace[i]) - helper_cCO3_grad[i] = dCO3 * (common_helper2[i] * cCO3_grad[i] \ - + common_helper1[i] * cCO3_laplace[i]) - - two_factors[i] = cCa[i] * cCO3[i] - two_factors_upp_lim[i] = min(two_factors[i],1) - two_factors_low_lim[i] = max(two_factors[i],1) - three_factors[i] = two_factors[i] * KRat - three_factors_upp_lim[i] = min(three_factors[i],1) - three_factors_low_lim[i] = max(three_factors[i],1) - - coA[i] = CA[i] * (((1 - three_factors_upp_lim[i]) ** m2) * \ - (not_too_deep[i] * not_too_shallow[i]) - nu1 * \ - (three_factors_low_lim[i] - 1) ** m1) - - coC[i] = CC[i] * (((two_factors_low_lim[i] - 1) ** n1) - nu2 * \ - (1 - two_factors_upp_lim[i]) ** n2) - - common_helper3[i] = coA[i] - lambda_* coC[i] - - dW_dx[i] = -rhorat * Phi_grad[i] * (2 * Phi[i] * F[i] + 10 * (F[i] - 1)) + sigma_Phi = np.cosh(Peclet_Phi)/np.sinh(Peclet_Phi) - 1/Peclet_Phi + else: + sigma_cCa = 0 + sigma_cCO3 = 0 + sigma_Phi = 0 + + cCa_grad[i] = 0.5 * ((1-sigma_cCa) * cCa_grad_forw[i] + \ + (1+sigma_cCa) * cCa_grad_back[i]) + cCO3_grad[i] = 0.5 * ((1-sigma_cCO3) * cCO3_grad_forw[i] + \ + (1+sigma_cCO3) * cCO3_grad_back[i]) + Phi_grad[i] = 0.5 * ((1-sigma_Phi) * Phi_grad_forw [i]+ \ + (1+sigma_Phi) * Phi_grad_back[i]) + + common_helper1[i] = Phi[i]/denominator[i] + common_helper2[i] = Phi_grad[i] * (2 + denominator[i]) \ + / denominator[i] ** 2 + helper_cCa_grad[i] = dCa * (common_helper2[i] * cCa_grad[i] \ + + common_helper1[i] * cCa_laplace[i]) + helper_cCO3_grad[i] = dCO3 * (common_helper2[i] * cCO3_grad[i] \ + + common_helper1[i] * cCO3_laplace[i]) + + two_factors[i] = cCa[i] * cCO3[i] + two_factors_upp_lim[i] = min(two_factors[i],1) + two_factors_low_lim[i] = max(two_factors[i],1) + three_factors[i] = two_factors[i] * KRat + three_factors_upp_lim[i] = min(three_factors[i],1) + three_factors_low_lim[i] = max(three_factors[i],1) + + coA[i] = CA[i] * (((1 - three_factors_upp_lim[i]) ** m2) * \ + (not_too_deep[i] * not_too_shallow[i]) - nu1 * \ + (three_factors_low_lim[i] - 1) ** m1) + + coC[i] = CC[i] * (((two_factors_low_lim[i] - 1) ** n1) - nu2 * \ + (1 - two_factors_upp_lim[i]) ** n2) + + common_helper3[i] = coA[i] - lambda_* coC[i] + + dW_dx[i] = -rhorat * Phi_grad[i] * (2 * Phi[i] * F[i] + 10 * (F[i] - 1)) - # This is dCA_dt - rate[0][i] = - U[i] * CA_grad[i] - Da * ((1 - CA[i]) \ - * coA[i] + lambda_ * CA[i] * coC[i]) - - # This is dCC_dt - rate[1][i] = - U[i] * CC_grad[i] + Da * (lambda_ * \ - (1 - CC[i]) * coC[i] + CC[i] * coA[i]) - - # This is dcCa_dt - rate[2][i] = helper_cCa_grad[i]/Phi[i] - W[i] * \ - cCa_grad[i] + Da * one_minus_Phi[i] * \ - (delta - cCa[i]) * common_helper3[i] \ - /Phi[i] - - # This is dcCO3_dt - rate[3][i] = helper_cCO3_grad[i]/Phi[i] - W[i] * \ - cCO3_grad[i] + Da * one_minus_Phi[i] * \ - (delta - cCO3[i]) * common_helper3[i] \ - /Phi[i] - - # This is dPhi_dt - rate[4][i] = - (dW_dx[i] * Phi[i] + W[i] * Phi_grad[i]) \ - + dPhi[i] * Phi_laplace[i] + Da * one_minus_Phi[i] \ - * common_helper3[i] - - return rate - - return pde_rhs \ No newline at end of file + # This is dCA_dt + rate[i] = - U[i] * CA_grad[i] - Da * ((1 - CA[i]) \ + * coA[i] + lambda_ * CA[i] * coC[i]) + + # This is dCC_dt + rate[no_depths + i] = - U[i] * CC_grad[i] + Da * (lambda_ * \ + (1 - CC[i]) * coC[i] + CC[i] * coA[i]) + + # This is dcCa_dt + rate[2 * no_depths + i] = helper_cCa_grad[i]/Phi[i] - W[i] * \ + cCa_grad[i] + Da * one_minus_Phi[i] * \ + (delta - cCa[i]) * common_helper3[i] \ + /Phi[i] + + # This is dcCO3_dt + rate[3 * no_depths + i] = helper_cCO3_grad[i]/Phi[i] - W[i] * \ + cCO3_grad[i] + Da * one_minus_Phi[i] * \ + (delta - cCO3[i]) * common_helper3[i] \ + /Phi[i] + + # This is dPhi_dt + rate[4 * no_depths + i] = - (dW_dx[i] * Phi[i] + W[i] * Phi_grad[i]) \ + + dPhi[i] * Phi_laplace[i] + Da * one_minus_Phi[i] \ + * common_helper3[i] + + return rate + + def zeros(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + return np.amin(y) + + def zeros_CA(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + return np.amin(y[self.CA_sl]) + + def zeros_CC(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + return np.amin(y[self.CC_sl]) + + def ones_CA_plus_CC(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + CA = y[self.CA_sl] + CC = y[self.CC_sl] + return np.amax(CA + CC) - 1 + + def ones_Phi(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + Phi = y[self.Phi_sl] + return np.amax(Phi) - 1 + + def zeros_U(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + Phi = y[self.Phi_sl] + F = 1 - np.exp(10 - 10 / Phi) + U = self.presum + self.rhorat * Phi ** 3 * F / (1 - Phi) + # Assume that U is positive at every depth at the beginning + # of the integration, so U will become zero first where it + # is smallest. + return np.amin(U) + + def zeros_W(self, t, y, progress_proxy, progress_dt, t0): + """ solve_ivp demands that I add these two extra aguments, i.e. + pbar and state, as in jac, where I need them for + tqdm progress display. + However, for this rhs calculation, they are redundant. """ + + Phi = y[self.Phi_sl] + F = 1 - np.exp(10 - 10 / Phi) + W = self.presum - self.rhorat * Phi ** 2 * F + # Assume that W is negative at every depth at the beginning + # of the integration, so U will become zero first where it is + # largest or least negative. + return np.amax(W) + diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 6cce6eb..1466646 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -139,7 +139,10 @@ def post_init(self): self.DCa = self.D0Ca self.PhiNR = self.PhiIni self.N = 200 - + # It could be that F-V caused instabilities instead of resolving them, + # e.g. in the case of oscillations. + # FV_switch = 1 will use the Fiadeiro-Veronis scheme for spatial derivatives. + FV_switch = 1 derived_dataclass = make_dataclass("Mapped parameters", derived_fields, namespace={"__post_init__": post_init}) @@ -203,40 +206,37 @@ class Solver(): Initialises all the parameters for the solver. So parameters like time interval, time step and tolerance. ''' - dt: float = 1.e-6 - # t_range is the integration time in units of T*. - t_range: int = 1 - solver: str = "scipy" - # Beware that "scheme" and "adaptive" will only be propagated if you have - # chosen py-pde's native "explicit" solver above. - scheme: str = "euler" - adaptive: bool = True + first_step: float = 1e-6 + atol: float = 1e-3 + rtol: float = 1e-3 + # t_span is a tuple (begin time, end time) of integration in units of T*. + t_span: tuple = (0, 1) # solve_ivp from scipy offers six methods. They can be set here. - method: str = "LSODA" + method: str = "Radau" # Setting lband and uband for method="LSODA" leads to tremendous performance # increase. See Scipy's solve_ivp documentation for background. Consider it # equivalent to providing a sparsity matrix for the "Radau" and "BDF" # implicit methods. lband: int = 1 uband: int = 1 - backend: str = "numba" - ret_info: bool = True - + dense_output: bool = False + jac_sparsity: csr_matrix = None + def __post_init__(self): ''' Filter out solver settings that are mutually incompatible. ''' try: - if self.solver != "scipy": - del self.__dataclass_fields__["method"] + if self.method == "LSODA": + del self.__dataclass_fields__["jac_sparsity"] + else: del self.__dataclass_fields__["lband"] del self.__dataclass_fields__["uband"] - else: - del self.__dataclass_fields__["scheme"] - del self.__dataclass_fields__["adaptive"] - if self.method != "LSODA": - del self.__dataclass_fields__["lband"] - del self.__dataclass_fields__["uband"] + + if self.method == "Radau" or self.method == "BDF": + self.jac_sparsity = jacobian_sparsity() + else: + del self.__dataclass_fields__["jac_sparsity"] except KeyError: pass @@ -244,11 +244,12 @@ def __post_init__(self): @dataclass class Tracker: ''' - Initialises all the tracking parameters, such as tracker interval. - Also indicates the quantities to be tracked, as boolean values. + Settings for tracking progress and for storing intermediate results when + solve_ivp runs. ''' - progress_tracker_interval: float = Solver().t_range / 1_000 - live_plotting: bool = False - plotting_interval: str = '0:05' - data_tracker_interval: float = 0.01 - track_U_at_bottom: bool = False + # Number of progress updates + no_progress_updates: int = 100_000 + + # Number of times to evaluate, for storage. + no_t_eval: int = 1_000 + t_eval: np.ndarray = np.linspace(*Solver().t_span, num = no_t_eval) From 89d285f140d596b70d83ff592ed4f72de093952d Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 29 Aug 2024 15:51:59 +0200 Subject: [PATCH 15/51] A ChatGPT comment is irreproducible, so I looked for a similar remark in the literature. --- marlpde/parameters.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 1466646..3266238 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -161,14 +161,12 @@ def jacobian_sparsity(): matrix computed by `solve_ivp` (when neither the Jacobian nor the Jacobian sparsity matrix was provided) has non-zero elements not only on the diagonals but also on adjacent positions along the - diagonals. This was confirmed by ChatGPT: - "It is indeed common for the Jacobian matrix of coupled partial - differential equations (PDEs), such as advection-diffusion equations, - to have non-zero elements beyond the main diagonal. This phenomenon, - where adjacent elements in the Jacobian are non-zero, is often due - to the spatial discretization of the differential equations." - Likewise computing a functional Jacobian is only feasible for the - diagonals, for positions near the diagonals it is very hard. + diagonals. + See equation 2.58 from "Finite Difference Methods Finite for Differential + Equations by Randall J. Leveque for an example of off-diagonal Jacobian + matrix elements. This example is about the Jacobian for solving the pde + describing the motion of a pendulum with a certain mass at the end of a + rigid (but massless) bar. Here we will choose diagonals of width 3. ''' From 2c14ddf0c2ad16f7d85f8c810c549d8b6ac212b4 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 10:32:39 +0200 Subject: [PATCH 16/51] Apparently, one has to use 'default_factory' in this case. --- marlpde/parameters.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 3266238..d25a93a 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -1,6 +1,6 @@ import configparser from pathlib import Path -from dataclasses import (dataclass, asdict, make_dataclass, fields) +from dataclasses import (dataclass, asdict, make_dataclass, fields, field) from subprocess import (run) import h5py as h5 from pint import UnitRegistry @@ -250,4 +250,5 @@ class Tracker: # Number of times to evaluate, for storage. no_t_eval: int = 1_000 - t_eval: np.ndarray = np.linspace(*Solver().t_span, num = no_t_eval) + t_eval: np.ndarray = field(default_factory = lambda: \ + np.linspace(*Solver().t_span, num = no_t_eval)) From 0edaf5dcfb3d3647cd1c6bfd9e570b3341d40646 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 10:37:00 +0200 Subject: [PATCH 17/51] Compute_Jacobian will yield a Jacobian with only values on the diagonals, i.e. the diagonals will have the width of only one depth node. We now know that due to discretisation, there should also be non-zero elements adjacent to the diagonals, but these are very hard to compute. --- marlpde/LHeureux_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index 89b65d4..e7f40f0 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -4,7 +4,6 @@ from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") from scipy.sparse import dia_matrix, lil_matrix, csr_matrix, find -from Compute_jacobian import Jacobian from pde.grids.operators.cartesian import _make_derivative class LMAHeureuxPorosityDiff(): From d83275dc30db791cd378e8fcd6092520d2c05bce Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 10:52:27 +0200 Subject: [PATCH 18/51] 'y0' is derived using a call to a method from 'eq', so 'y0' needs to be derived after 'eq' has been defined. 'number_of_depths' --> 'Number_of_depths'. --- marlpde/Evolve_scenario.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 2e006ae..fa32fce 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -43,24 +43,6 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): depths.register_operator("grad_forw", \ lambda grid: _make_derivative(grid, method="forward")) - # Setting initial values for all five fields in three steps. - # This is perhaps more involved than necessary, since the - # end result is a 1D Numpy array with a length of five times - # the number of depths. The number five comes from the five - # fields we are tracking, by integrating five pdes. - # First step. - AragoniteSurface = ScalarField(depths, CAIni) - CalciteSurface = ScalarField(depths, CCIni) - CaSurface = ScalarField(depths, cCaIni) - CO3Surface = ScalarField(depths, cCO3Ini) - PorSurface = ScalarField(depths, PhiIni) - - # Second step. - state = eq.get_state(AragoniteSurface, CalciteSurface, CaSurface, - CO3Surface, PorSurface) - # Third step. - y0 = state.data.ravel() - # I need those two fields for computing coA, which is rather involved. # There may be a simpler way of selecting these depths, but I haven't # found one yet. For now these two Heaviside step functions. @@ -77,12 +59,30 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): inspect.signature(LMAHeureuxPorosityDiff).parameters.\ values()]} - slices_for_all_fields = [slice(i * number_of_depths, (i+1) * number_of_depths) \ + slices_for_all_fields = [slice(i * Number_of_depths, (i+1) * Number_of_depths) \ for i in range(5)] eq = LMAHeureuxPorosityDiff(depths, slices_for_all_fields, not_too_shallow, not_too_deep, **filtered_pde_parms) + # Setting initial values for all five fields in three steps. + # This is perhaps more involved than necessary, since the + # end result is a 1D Numpy array with a length of five times + # the number of depths. The number five comes from the five + # fields we are tracking, by integrating five pdes. + # First step. + AragoniteSurface = ScalarField(depths, CAIni) + CalciteSurface = ScalarField(depths, CCIni) + CaSurface = ScalarField(depths, cCaIni) + CO3Surface = ScalarField(depths, cCO3Ini) + PorSurface = ScalarField(depths, PhiIni) + + # Second step. + state = eq.get_state(AragoniteSurface, CalciteSurface, CaSurface, + CO3Surface, PorSurface) + # Third step. + y0 = state.data.ravel() + start_computing = time.time() with tqdm(total=number_of_progress_updates) as pbar: t0 = solver_parms["t_span"][0] From 23173aad993315cc57e4013fc80018eab8e346ee Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:05:39 +0200 Subject: [PATCH 19/51] PyLint seems to prefer f-string formatting here. --- marlpde/Evolve_scenario.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index fa32fce..bd629e8 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -132,9 +132,9 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): +', '.join(['%.2f']*len(n))+"") % tuple([Tstar * time for time in n])) print() - print("Message from solve_ivp = {0} \n".format(sol.message)) + print(f"Message from solve_ivp = {sol.message} \n") print(("Time taken for solve_ivp is " - "{0:.2f}s. \n".format(end_computing - start_computing))) + f"{end_computing - start_computing:.2f}s. \n")) if sol.status == 0: covered_time = Tstar * end_time From 499c27970f0cf7da1751017c1da799a4573a2e7c Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:06:59 +0200 Subject: [PATCH 20/51] This variable was too long and therefore renamed. --- marlpde/Evolve_scenario.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index bd629e8..85ae02f 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -139,7 +139,7 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): if sol.status == 0: covered_time = Tstar * end_time else: - covered_time = pbar.n * Tstar * end_time /number_of_progress_updates + covered_time = pbar.n * Tstar * end_time /no_progress_updates # Store your results somewhere in a subdirectory of a parent directory. store_folder = "../Results/" + \ datetime.now().strftime("%d_%m_%Y_%H_%M_%S" + "/") From cd2965e62f3285764180316db3690d982131daf1 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:10:02 +0200 Subject: [PATCH 21/51] This variable needs to be defined before the context can be created. --- marlpde/Evolve_scenario.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 85ae02f..525f190 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -83,11 +83,12 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): # Third step. y0 = state.data.ravel() + no_progress_updates = tracker_parms["no_progress_updates"] + start_computing = time.time() - with tqdm(total=number_of_progress_updates) as pbar: + with tqdm(total=no_progress_updates) as pbar: t0 = solver_parms["t_span"][0] end_time = solver_parms["t_span"][1] - no_progress_updates = tracker_parms["no_progress_updates"] progress_bar_args = [pbar, (end_time - t0) / no_progress_updates, t0] sol = solve_ivp(fun=eq.fun_numba, y0=y0, **solver_parms, From 24af80fe7fcbd49a2429c24b85825aa2512cd086 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:14:37 +0200 Subject: [PATCH 22/51] Again, PyLint seems to prefer f-string formatting here. --- marlpde/Evolve_scenario.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 525f190..86348fb 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -99,11 +99,11 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): end_computing = time.time() print() - print("Number of rhs evaluations = {0} \n".format(sol.nfev)) - print("Number of Jacobian evaluations = {0} \n".format(sol.njev)) - print("Number of LU decompositions = {0} \n".format(sol.nlu)) - print("Status = {0} \n".format(sol.status)) - print("Success = {0} \n".format(sol.success)) + print(f"Number of rhs evaluations = {sol.nfev} \n") + print(f"Number of Jacobian evaluations = {sol.njev} \n") + print(f"Number of LU decompositions = {sol.nlu} \n") + print(f"Status = {sol.status} \n") + print(f"Success = {sol.success} \n") f = sol.t_events[0] print(("Times, in years, at which any field at any depth crossed zero: "\ +', '.join(['%.2f']*len(f))+"") % tuple([Tstar * time for time in f])) From d421b0890849803cacddb6214afba7f7dd01e57e Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:19:20 +0200 Subject: [PATCH 23/51] This branch does not use PDEBase. --- marlpde/LHeureux_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index e7f40f0..ebe12a1 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,6 +1,6 @@ import numpy as np import line_profiler -from pde import FieldCollection, PDEBase, ScalarField, FieldBase +from pde import FieldCollection, ScalarField, FieldBase from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") from scipy.sparse import dia_matrix, lil_matrix, csr_matrix, find From e848928fd7106a0d27455e7aa63908185be218a6 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:20:16 +0200 Subject: [PATCH 24/51] This branch does not use FieldBase. --- marlpde/LHeureux_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index ebe12a1..7ad77c2 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,6 +1,6 @@ import numpy as np import line_profiler -from pde import FieldCollection, ScalarField, FieldBase +from pde import FieldCollection, ScalarField from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") from scipy.sparse import dia_matrix, lil_matrix, csr_matrix, find From 417289601e4b0d109daba8a6a675cbd4f9d4cdcf Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:22:25 +0200 Subject: [PATCH 25/51] We needed these imports when the Jacobian sparsity matrix was computed in this module. However, it is now calculated in the parameters module, so we no longer need these imports here. --- marlpde/LHeureux_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index 7ad77c2..aea68fb 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -3,7 +3,6 @@ from pde import FieldCollection, ScalarField from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") -from scipy.sparse import dia_matrix, lil_matrix, csr_matrix, find from pde.grids.operators.cartesian import _make_derivative class LMAHeureuxPorosityDiff(): From 1e730153ef93c7bb45e6fe08041e8bf78950fdb3 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:24:24 +0200 Subject: [PATCH 26/51] PyLint apparently wants this import at the top, i.e. first. --- marlpde/LHeureux_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index aea68fb..e2c4991 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,9 +1,9 @@ +from pde.grids.operators.cartesian import _make_derivative import numpy as np import line_profiler from pde import FieldCollection, ScalarField from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") -from pde.grids.operators.cartesian import _make_derivative class LMAHeureuxPorosityDiff(): From 8bf3b05496479561646ee40e66115cd5b7555a26 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:25:38 +0200 Subject: [PATCH 27/51] PyLint demands imports to be grouped. --- marlpde/LHeureux_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index e2c4991..6f78a83 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,8 +1,9 @@ from pde.grids.operators.cartesian import _make_derivative +from pde import FieldCollection, ScalarField import numpy as np import line_profiler -from pde import FieldCollection, ScalarField from numba import njit + np.seterr(divide="raise", over="raise", under="warn", invalid="raise") class LMAHeureuxPorosityDiff(): From 17eeef175d2c4e0d9f36e773cde0244dd61f1fe9 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:27:51 +0200 Subject: [PATCH 28/51] I guess a minimal doctring should be helpful here. --- marlpde/LHeureux_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index 6f78a83..47d27b6 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -7,7 +7,10 @@ np.seterr(divide="raise", over="raise", under="warn", invalid="raise") class LMAHeureuxPorosityDiff(): - + ''' + This class defines all the parameters for the diagenetic model. + ''' + def __init__(self, Depths, slices_all_fields, CA0, CC0, cCa0, cCO30, Phi0, sedimentationrate, Xstar, Tstar, k1, k2, k3, k4, m1, m2, n1, n2, b, beta, rhos, rhow, rhos0, KA, KC, muA, D0Ca, PhiNR, From 27eef33cc6f35614fc0a19c1dcb861baa9251d4b Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:28:50 +0200 Subject: [PATCH 29/51] Trailing whitespace. --- marlpde/LHeureux_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index 47d27b6..a056f44 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -10,7 +10,6 @@ class LMAHeureuxPorosityDiff(): ''' This class defines all the parameters for the diagenetic model. ''' - def __init__(self, Depths, slices_all_fields, CA0, CC0, cCa0, cCO30, Phi0, sedimentationrate, Xstar, Tstar, k1, k2, k3, k4, m1, m2, n1, n2, b, beta, rhos, rhow, rhos0, KA, KC, muA, D0Ca, PhiNR, From 6d8017ffb665446d7a202dbed454d29efc8d490c Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:34:34 +0200 Subject: [PATCH 30/51] If 't_eval' is defined in the regular way, i.e. not in a '__post_init__' it will complain that it does not know 'no_t_eval'. --- marlpde/parameters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index d25a93a..6d19ac3 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -250,5 +250,8 @@ class Tracker: # Number of times to evaluate, for storage. no_t_eval: int = 1_000 - t_eval: np.ndarray = field(default_factory = lambda: \ - np.linspace(*Solver().t_span, num = no_t_eval)) + + def __post_init__(self): + t_eval: np.ndarray = field(default_factory = lambda: \ + np.linspace(*Solver().t_span, \ + num = no_t_eval)) From 659f8de08cccbda480f1e43233da8a0726c7ef57 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:35:47 +0200 Subject: [PATCH 31/51] Trailing whitespace. --- marlpde/Evolve_scenario.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 86348fb..b5f754a 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -55,7 +55,7 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): # Taken from https://stackoverflow.com/questions/334655/passing-a-\ # dictionary-to-a-function-as-keyword-parameters filtered_pde_parms = {k: v for k, v in pde_parms.items() if k in [p.name for - p in + p in inspect.signature(LMAHeureuxPorosityDiff).parameters.\ values()]} From fbd1dab32f94cab5a016145969b00ca496d37356 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:37:07 +0200 Subject: [PATCH 32/51] Order of the arguments did not match the order of the call. --- marlpde/LHeureux_model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index a056f44..cfb665d 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -10,10 +10,10 @@ class LMAHeureuxPorosityDiff(): ''' This class defines all the parameters for the diagenetic model. ''' - def __init__(self, Depths, slices_all_fields, CA0, CC0, cCa0, cCO30, Phi0, - sedimentationrate, Xstar, Tstar, k1, k2, k3, k4, m1, m2, n1, - n2, b, beta, rhos, rhow, rhos0, KA, KC, muA, D0Ca, PhiNR, - PhiInfty, PhiIni, DCa, DCO3, not_too_shallow, not_too_deep, + def __init__(self, Depths, slices_all_fields, not_too_shallow, not_too_deep, + CA0, CC0, cCa0, cCO30, Phi0, sedimentationrate, Xstar, Tstar, + k1, k2, k3, k4, m1, m2, n1, n2, b, beta, rhos, rhow, rhos0, + KA, KC, muA, D0Ca, PhiNR, PhiInfty, PhiIni, DCa, DCO3, FV_switch): self.no_fields = 5 self.Depths = Depths From 438a12f797060f3610d22f7e443b67e583a2d439 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:48:32 +0200 Subject: [PATCH 33/51] Typo: 'FV_switch' --> 'self.FV_switch' and had to be added to 'Map_Scenario'. --- marlpde/parameters.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 6d19ac3..63e0455 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -118,7 +118,8 @@ def Map_Scenario(): ("n2", float, None), ("DCa", float, None), ("PhiNR", float, None), - ("N", int, None)]) + ("N", int, None), + ("FV_switch", int, None)]) def post_init(self): # The Python parameters that need additional conversion @@ -138,11 +139,12 @@ def post_init(self): self.n2 = self.n1 self.DCa = self.D0Ca self.PhiNR = self.PhiIni + # The number of cells that comprise the grid. self.N = 200 # It could be that F-V caused instabilities instead of resolving them, # e.g. in the case of oscillations. # FV_switch = 1 will use the Fiadeiro-Veronis scheme for spatial derivatives. - FV_switch = 1 + self.FV_switch = 1 derived_dataclass = make_dataclass("Mapped parameters", derived_fields, namespace={"__post_init__": post_init}) From 69f58106f76ae99bb955f6d67a86d310f1613bf8 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 11:54:47 +0200 Subject: [PATCH 34/51] 'e' was not applied, this will hopefully field a more specific error message. --- marlpde/parameters.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 63e0455..d72b8b6 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -191,7 +191,9 @@ def jacobian_sparsity(): try: assert len(offsets) == diagonals.shape[0] except AssertionError as e: + print(f'Assertion failed at the {str(e)} line. \n') print('Setup of diagonals incorrect.') + # Construct the sparse matrix. raw_matrix = lil_matrix(dia_matrix((diagonals, offsets), shape=(n, n))) # Set the Jacobian elements to zero that correspond with the derivatives From 5424065c64431fbec0580c062057d8de2e2175c7 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 12:14:55 +0200 Subject: [PATCH 35/51] 't_eval' was effectively not defined at all. --- marlpde/parameters.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index d72b8b6..bb7d8fb 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -255,7 +255,9 @@ class Tracker: # Number of times to evaluate, for storage. no_t_eval: int = 1_000 + + # Array with all times that solutions from solve_ivp should be recorded. + t_eval: np.ndarray = None + def __post_init__(self): - t_eval: np.ndarray = field(default_factory = lambda: \ - np.linspace(*Solver().t_span, \ - num = no_t_eval)) + self.t_eval = np.linspace(*Solver().t_span, num = self.no_t_eval) From db8c9de05deb33ebf749aefd5d35c734d9396829 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 12:17:47 +0200 Subject: [PATCH 36/51] 'covered_time_span' --> 'covered_time'. --- marlpde/Evolve_scenario.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index b5f754a..540e79a 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -150,7 +150,7 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): storage_parms = solver_parms | tracker_parms | pde_parms storage = FileStorage(stored_results, info=storage_parms) - return sol, covered_time_span, depths, Xstar, store_folder + return sol, covered_time, depths, Xstar, store_folder def Plot_results(sol, covered_time, depths, Xstar, store_folder): ''' From 602a27c21bd65780d8fc20fd2845b80899c65da6 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 13:07:25 +0200 Subject: [PATCH 37/51] =?UTF-8?q?Trying=20to=20fix=20'gi.repository.GLib.G?= =?UTF-8?q?Error:=20gdk-pixbuf-error-quark:=20Couldn=E2=80=99t=20recognize?= =?UTF-8?q?=20the=20image=20file=20format=20for=20file'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- marlpde/Evolve_scenario.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 540e79a..2a67ce8 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -8,7 +8,7 @@ from scipy.integrate import solve_ivp import matplotlib.pyplot as plt from tqdm import tqdm -import h5py +import matplotlib from pde import CartesianGrid, ScalarField, FileStorage from pde.grids.operators.cartesian import _make_derivative from parameters import Map_Scenario, Solver, Tracker @@ -170,7 +170,7 @@ def Plot_results(sol, covered_time, depths, Xstar, store_folder): ax.set_xlabel("Depth (cm)") ax.set_ylabel("Compositions and concentrations (dimensionless)") ax.legend(loc='upper right') - fig.savefig(store_folder + 'Final_distributions.pdf', bbox_inches="tight") + fig.savefig(store_folder + 'Final_distributions.png', bbox_inches="tight") if __name__ == '__main__': pde_parms = asdict(Map_Scenario()) From 1d17ff08e3d2105c51fe24ad87e52f8620cec06d Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 13:47:53 +0200 Subject: [PATCH 38/51] =?UTF-8?q?'slices=5Fall=5Ffields'=20is=20shorter.?= =?UTF-8?q?=20'fig,=20ax=20=3D=20plt.subplots()'=20gave=20the=20'gi.reposi?= =?UTF-8?q?tory.GLib.GError:=20gdk-pixbuf-error-quark:=20Couldn=E2=80=99t?= =?UTF-8?q?=20recognize=20the=20image=20file=20format'=20error,=20no=20mat?= =?UTF-8?q?ter=20which=20output=20format=20was=20chosen.=20This=20can=20ap?= =?UTF-8?q?parently=20only=20be=20fixed=20by=20choosing=20a=20matplotlib?= =?UTF-8?q?=20backend=20upfront.=20The=20solution=20data=20from=20solve=5F?= =?UTF-8?q?ivp=20was=20not=20selected=20in=20the=20right=20way,=20which=20?= =?UTF-8?q?showed=20up=20when=20trying=20to=20plot.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- marlpde/Evolve_scenario.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 2a67ce8..c78d7a7 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -9,6 +9,7 @@ import matplotlib.pyplot as plt from tqdm import tqdm import matplotlib +matplotlib.use("AGG") from pde import CartesianGrid, ScalarField, FileStorage from pde.grids.operators.cartesian import _make_derivative from parameters import Map_Scenario, Solver, Tracker @@ -59,10 +60,10 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): inspect.signature(LMAHeureuxPorosityDiff).parameters.\ values()]} - slices_for_all_fields = [slice(i * Number_of_depths, (i+1) * Number_of_depths) \ + slices_all_fields = [slice(i * Number_of_depths, (i+1) * Number_of_depths) \ for i in range(5)] - eq = LMAHeureuxPorosityDiff(depths, slices_for_all_fields, not_too_shallow, + eq = LMAHeureuxPorosityDiff(depths, slices_all_fields, not_too_shallow, not_too_deep, **filtered_pde_parms) # Setting initial values for all five fields in three steps. @@ -140,7 +141,8 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): if sol.status == 0: covered_time = Tstar * end_time else: - covered_time = pbar.n * Tstar * end_time /no_progress_updates + covered_time = pbar.n * Tstar * end_time / no_progress_updates + # Store your results somewhere in a subdirectory of a parent directory. store_folder = "../Results/" + \ datetime.now().strftime("%d_%m_%Y_%H_%M_%S" + "/") @@ -150,9 +152,10 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): storage_parms = solver_parms | tracker_parms | pde_parms storage = FileStorage(stored_results, info=storage_parms) - return sol, covered_time, depths, Xstar, store_folder + return sol, covered_time, depths, Xstar, slices_all_fields, store_folder -def Plot_results(sol, covered_time, depths, Xstar, store_folder): +def Plot_results(sol, covered_time, depths, Xstar, slices_all_fields, + store_folder): ''' Plot the five fields at the end of the integration interval as a function of depth. @@ -162,21 +165,27 @@ def Plot_results(sol, covered_time, depths, Xstar, store_folder): # Marker size ms = 5 plotting_depths = ScalarField.from_expression(depths, "x").data * Xstar - ax.plot(plotting_depths, sol.data[0], "v", ms = ms, label = "CA") - ax.plot(plotting_depths, sol.data[1], "^", ms = ms, label = "CC") - ax.plot(plotting_depths, sol.data[2], ">", ms = ms, label = "cCa") - ax.plot(plotting_depths, sol.data[3], "<", ms = ms, label = "cCO3") - ax.plot(plotting_depths, sol.data[4], "o", ms = ms, label = "Phi") + ax.plot(plotting_depths, (sol.y)[slices_all_fields[0], -1], + "v", ms = ms, label = "CA") + ax.plot(plotting_depths, (sol.y)[slices_all_fields[1], -1], + "^", ms = ms, label = "CC") + ax.plot(plotting_depths, (sol.y)[slices_all_fields[2], -1], + ">", ms = ms, label = "cCa") + ax.plot(plotting_depths, (sol.y)[slices_all_fields[3], -1], + "<", ms = ms, label = "cCO3") + ax.plot(plotting_depths, (sol.y)[slices_all_fields[4], -1], + "o", ms = ms, label = "Phi") ax.set_xlabel("Depth (cm)") ax.set_ylabel("Compositions and concentrations (dimensionless)") ax.legend(loc='upper right') - fig.savefig(store_folder + 'Final_distributions.png', bbox_inches="tight") + fig.savefig(store_folder + 'Final_distributions.pdf', bbox_inches="tight") if __name__ == '__main__': pde_parms = asdict(Map_Scenario()) solver_parms = asdict(Solver()) tracker_parms = asdict(Tracker()) - solution, covered_time, depths, Xstar, store_folder = \ + solution, covered_time, depths, Xstar, slices_all_fields, store_folder = \ integrate_equations(solver_parms, tracker_parms, pde_parms) - Plot_results(solution, covered_time, depths, Xstar, store_folder) + Plot_results(solution, covered_time, depths, Xstar, slices_all_fields, + store_folder) From f878b8c9860a5aae70b06622902250f36835cb4c Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 13:54:21 +0200 Subject: [PATCH 39/51] Might as well pass the return values from the integration directly to the plotting routine. --- marlpde/Evolve_scenario.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index c78d7a7..e6317f1 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -184,8 +184,4 @@ def Plot_results(sol, covered_time, depths, Xstar, slices_all_fields, pde_parms = asdict(Map_Scenario()) solver_parms = asdict(Solver()) tracker_parms = asdict(Tracker()) - solution, covered_time, depths, Xstar, slices_all_fields, store_folder = \ - integrate_equations(solver_parms, tracker_parms, pde_parms) - Plot_results(solution, covered_time, depths, Xstar, slices_all_fields, - store_folder) - + Plot_results(*integrate_equations(solver_parms, tracker_parms, pde_parms)) \ No newline at end of file From 8bf5a30dc6e395d7fc16fe3f6738fd89e188374d Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 15:31:54 +0200 Subject: [PATCH 40/51] A lot of unused imports here. --- marlpde/parameters.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index bb7d8fb..37da0fc 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -1,8 +1,4 @@ -import configparser -from pathlib import Path -from dataclasses import (dataclass, asdict, make_dataclass, fields, field) -from subprocess import (run) -import h5py as h5 +from dataclasses import (dataclass, make_dataclass, fields) from pint import UnitRegistry import numpy as np from scipy.sparse import lil_matrix, dia_matrix, csr_matrix From a9159a303e3939c3b65ca69b63e4293ceb1dc394 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 15:41:46 +0200 Subject: [PATCH 41/51] PyLint complaining about the order of the imports. Storing the solutions, times and metadata using py-pde's FileStorage class seems cumbersome when no tracking is applied. Therefore I reverted to the regular way of saving Numpy arrays in an hdf5 file. All the metadata, i.e. 'stored_parms', which is a single dict, can be stored as well, except for the Jacobian sparsity matrix, since that will give rise to 'TypeError: Object dtype dtype('O') has no native HDF5 equivalent'. This csr_matrix has to be converted to a ndarray first, I reckon. --- marlpde/Evolve_scenario.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index e6317f1..85d0aab 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -1,19 +1,20 @@ #!/usr/bin/env python -from datetime import datetime -import time -import os from dataclasses import asdict import inspect +import os +import time +from datetime import datetime +import h5py +from LHeureux_model import LMAHeureuxPorosityDiff +from parameters import Map_Scenario, Solver, Tracker +from pde import CartesianGrid, ScalarField +from pde.grids.operators.cartesian import _make_derivative from scipy.integrate import solve_ivp -import matplotlib.pyplot as plt from tqdm import tqdm import matplotlib +import matplotlib.pyplot as plt matplotlib.use("AGG") -from pde import CartesianGrid, ScalarField, FileStorage -from pde.grids.operators.cartesian import _make_derivative -from parameters import Map_Scenario, Solver, Tracker -from LHeureux_model import LMAHeureuxPorosityDiff def integrate_equations(solver_parms, tracker_parms, pde_parms): ''' @@ -149,8 +150,15 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): os.makedirs(store_folder) stored_results = store_folder + "LMAHeureuxPorosityDiff.hdf5" # Keep a record of all parameters. - storage_parms = solver_parms | tracker_parms | pde_parms - storage = FileStorage(stored_results, info=storage_parms) + stored_parms = solver_parms | tracker_parms | pde_parms + # Remove items which will raise a problem when storing as metadata in an + # hdf5 file + del stored_parms["jac_sparsity"] + + with h5py.File(stored_results, "w") as stored: + stored.create_dataset("solutions", data=sol.y) + stored.create_dataset("times", data=sol.t) + stored.attrs.update(stored_parms) return sol, covered_time, depths, Xstar, slices_all_fields, store_folder From 04455193cf9f7584fd218767cebd19da6100912c Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 17:37:46 +0200 Subject: [PATCH 42/51] ipython is only useful for debugging and prototyping. pandas is not needed for this branch. --- Pipfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Pipfile b/Pipfile index 27905f1..3469c3d 100644 --- a/Pipfile +++ b/Pipfile @@ -15,8 +15,6 @@ py-pde = "*" tqdm = "*" h5py = "*" pint = "*" -ipython = "*" -pandas = "*" [dev-packages] pylint = "*" From 882d9c56e05955e6a48b4872357f87fd82b3da99 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 17:43:06 +0200 Subject: [PATCH 43/51] Profiling has been done, so the line profiler is no longer needed. cache=False may be noticeably slower for short runs, but sometimes causes a run to halt from start, when a compiled object is missing. --- marlpde/LHeureux_model.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/marlpde/LHeureux_model.py b/marlpde/LHeureux_model.py index cfb665d..80b6f4d 100644 --- a/marlpde/LHeureux_model.py +++ b/marlpde/LHeureux_model.py @@ -1,7 +1,6 @@ from pde.grids.operators.cartesian import _make_derivative from pde import FieldCollection, ScalarField import numpy as np -import line_profiler from numba import njit np.seterr(divide="raise", over="raise", under="warn", invalid="raise") @@ -160,7 +159,6 @@ def calculate_sigma(Peclet, W_data, Peclet_min, Peclet_max): 1/Peclet[i] return sigma - @line_profiler.profile def fun(self, t, y, progress_proxy, progress_dt, t0): """ For tqdm to monitor progress. @@ -289,7 +287,6 @@ def fun(self, t, y, progress_proxy, progress_dt, t0): return FieldCollection([dCA_dt, dCC_dt, dcCa_dt, dcCO3_dt, dPhi_dt]).data.ravel() - @line_profiler.profile def fun_numba(self, t, y, progress_proxy, progress_dt, t0): """ For tqdm to monitor progress. From @@ -362,7 +359,7 @@ def fun_numba(self, t, y, progress_proxy, progress_dt, t0): FV_switch) @staticmethod - @njit(cache=True) + @njit(cache=False) def pde_rhs(CA, CC, cCa, cCO3, Phi, CA_grad_back_op, CA_grad_forw_op, CC_grad_back_op, CC_grad_forw_op, cCa_grad_back_op, cCa_grad_forw_op, cCa_laplace_op, @@ -429,7 +426,7 @@ def pde_rhs(CA, CC, cCa, cCO3, Phi, CA_grad_back_op, CA_grad_forw_op, # Implementing equation 6 from l'Heureux. denominator[i] = 1 - 2 * np.log(Phi[i]) - one_minus_Phi[i] = 1 - Phi[i] + one_minus_Phi[i] = 1 - Phi[i] # dPhi[i] = auxcon * F[i] * (Phi[i] ** 3) / one_minus_Phi[i] dPhi[i] = dPhi_fixed From 657a3f56487232567e3f21f8e8bde0a6de918b70 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 17:51:50 +0200 Subject: [PATCH 44/51] These regression tests copied from the main branch have to handle the slightly different data format that solve_ivp returns, i.e. solution.y contains the solutions for the five fields and the [:, -1] indexing gives the last ones across all depths. integrate_equations now gives six return values instead of five. solve_ivp uses 'first_step' instead of 'dt'. --- tests/Regression_test/test_regression.py | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/Regression_test/test_regression.py b/tests/Regression_test/test_regression.py index 216bad7..c6f09d4 100644 --- a/tests/Regression_test/test_regression.py +++ b/tests/Regression_test/test_regression.py @@ -43,13 +43,13 @@ def test_integration_Scenario_A(): Scenario_parameters = asdict(Map_Scenario()) | \ {"Phi0": 0.6, "PhiIni": 0.5, "PhiNR": 0.6} # integrate_equations returns four variables, we only need the first one. - solution, _, _, _, _ = integrate_equations(asdict(Solver()), - asdict(Tracker()), - Scenario_parameters) + solution, _, _, _, _, _ = integrate_equations(asdict(Solver()), + asdict(Tracker()), + Scenario_parameters) # Test the final distribution of all five fields over depths - assert_allclose(solution.data, Scenario_A_data[-1, :, :], + assert_allclose((solution.y)[:, -1], Scenario_A_data[-1, :, :], rtol=rtol, atol=atol) def test_high_porosity_integration(): @@ -75,16 +75,16 @@ def test_high_porosity_integration(): # Smaller initial time step needed for these high porosities. # If not, we get a ZeroDivisionError from "wrapped_stepper". - Solver_parms = replace(Solver(), dt = 5e-7) + Solver_parms = replace(Solver(), first_step = 5e-7) # Concatenate the dict containing the Scenario parameters with the # dict containing the solver parameters (such as required tolerance). # integrate_equations returns four variables, we only need the first one. - solution, _, _, _, _ = integrate_equations(asdict(Solver_parms), - asdict(Tracker()), - Scenario_parameters) + solution, _, _, _, _, _ = integrate_equations(asdict(Solver_parms), + asdict(Tracker()), + Scenario_parameters) # Test the final distribution of all five fields over depths - assert_allclose(solution.data, high_porosity_data[-1, :, :], + assert_allclose((solution.y)[:, -1], high_porosity_data[-1, :, :], rtol=rtol, atol=atol) def test_cross_check_with_Matlab_output(): @@ -114,13 +114,13 @@ def test_cross_check_with_Matlab_output(): Scenario_parameters = asdict(Map_Scenario()) |\ {"Phi0": 0.5, "PhiIni": 0.5, "PhiNR": 0.5, \ "k3": 0.01, "k4": 0.01} - Xstar = Scenario_parameters["Xstar"] + Xstar = Scenario_parameters["Xstar"] max_depth = Scenario_parameters["max_depth"] - solution, _, _, _, _ = integrate_equations(asdict(Solver()), - asdict(Tracker()), - Scenario_parameters) + solution, _, _, _, _, _ = integrate_equations(asdict(Solver()), + asdict(Tracker()), + Scenario_parameters) Number_of_depths = Scenario_parameters["N"] @@ -143,7 +143,8 @@ def test_cross_check_with_Matlab_output(): # Willem Hundsdorfer: "Numerical Solution of Advection-Diffusion-Reaction Equations". # Consequently, both the Matlab and Python solutions for the concentrations and the # porosity jump a bit up and down near the surface, due to the high Peclet numbers. - assert_allclose(solution.data[:, 2:], Matlab_output_interpolated[:, 2:], atol = atol) + assert_allclose((solution.y)[:, -1][:, 2:], + Matlab_output_interpolated[:, 2:], atol = atol) From 246832f24765a2446e6b94a4aa2241b7446ae7ec Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Mon, 2 Sep 2024 17:57:07 +0200 Subject: [PATCH 45/51] Users should still be allowed to use the Numpy backend instead of the Numba-based evaluations of the right-hand sides. The Solver dataclass now provides for that. A conditional has been added to check if the 'jac_sparsity' attribute exists. It will not exist for explicit solvers. --- marlpde/Evolve_scenario.py | 24 +++++++++++++++++------- marlpde/parameters.py | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 85d0aab..7e7e6e1 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -92,12 +92,21 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): t0 = solver_parms["t_span"][0] end_time = solver_parms["t_span"][1] progress_bar_args = [pbar, (end_time - t0) / no_progress_updates, t0] - - sol = solve_ivp(fun=eq.fun_numba, y0=y0, **solver_parms, - t_eval= tracker_parms["t_eval"], - events = [eq.zeros, eq.zeros_CA, eq.zeros_CC, \ - eq.ones_CA_plus_CC, eq.ones_Phi, eq.zeros_U, eq.zeros_W], - args=progress_bar_args) + + # The backend parameter determines which function should be called to + # determine the right-hand sides of the five pdes. It can be either + # a Numpy-based function or a Numba-based function. The latter is + # faster. + backend = solver_parms["backend"] + # "backend" is not an argument for solve_ivp, so remove it now. + del solver_parms["backend"] + + sol = solve_ivp(eq.fun if backend=="numpy" else eq.fun_numba, + y0=y0, **solver_parms, + t_eval= tracker_parms["t_eval"], + events = [eq.zeros, eq.zeros_CA, eq.zeros_CC, \ + eq.ones_CA_plus_CC, eq.ones_Phi, eq.zeros_U, \ + eq.zeros_W], args=progress_bar_args) end_computing = time.time() print() @@ -153,7 +162,8 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): stored_parms = solver_parms | tracker_parms | pde_parms # Remove items which will raise a problem when storing as metadata in an # hdf5 file - del stored_parms["jac_sparsity"] + if "jac_sparsity" in stored_parms: + del stored_parms["jac_sparsity"] with h5py.File(stored_results, "w") as stored: stored.create_dataset("solutions", data=sol.y) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 37da0fc..73151b4 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -217,6 +217,7 @@ class Solver(): # implicit methods. lband: int = 1 uband: int = 1 + backend: str = "numba" dense_output: bool = False jac_sparsity: csr_matrix = None From 653a702787016b18baee6486152e1d1da304fb4c Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Tue, 3 Sep 2024 12:06:41 +0200 Subject: [PATCH 46/51] Reshape the solve_ivp solutions such that you arrive at one row per field, this is more convenient than a single dimension covering all depths for all fields. Also store in this way, as an hdf5. Have 'integrate_equations' only return the final solution, since we only use that for plotting. --- marlpde/Evolve_scenario.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 7e7e6e1..15094ba 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -165,15 +165,21 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): if "jac_sparsity" in stored_parms: del stored_parms["jac_sparsity"] + # Reshape the solutions such that you get one row per field. + # The third axis, i.e.the time axis, can remain unchanged. + field_solutions = sol.y.reshape(5, Number_of_depths, sol.y.shape[-1]) + with h5py.File(stored_results, "w") as stored: - stored.create_dataset("solutions", data=sol.y) + stored.create_dataset("solutions", data=field_solutions) stored.create_dataset("times", data=sol.t) stored.attrs.update(stored_parms) - return sol, covered_time, depths, Xstar, slices_all_fields, store_folder + # We will be plotting only the distributions corresponding to the last time. + # Thus no point in returning all data. Moreover, all data have been saved. + + return field_solutions[:, :, -1], covered_time, depths, Xstar, store_folder -def Plot_results(sol, covered_time, depths, Xstar, slices_all_fields, - store_folder): +def Plot_results(last_field_sol, covered_time, depths, Xstar, store_folder): ''' Plot the five fields at the end of the integration interval as a function of depth. @@ -183,16 +189,13 @@ def Plot_results(sol, covered_time, depths, Xstar, slices_all_fields, # Marker size ms = 5 plotting_depths = ScalarField.from_expression(depths, "x").data * Xstar - ax.plot(plotting_depths, (sol.y)[slices_all_fields[0], -1], - "v", ms = ms, label = "CA") - ax.plot(plotting_depths, (sol.y)[slices_all_fields[1], -1], - "^", ms = ms, label = "CC") - ax.plot(plotting_depths, (sol.y)[slices_all_fields[2], -1], - ">", ms = ms, label = "cCa") - ax.plot(plotting_depths, (sol.y)[slices_all_fields[3], -1], - "<", ms = ms, label = "cCO3") - ax.plot(plotting_depths, (sol.y)[slices_all_fields[4], -1], - "o", ms = ms, label = "Phi") + + ax.plot(plotting_depths, last_field_sol[0], "v", ms = ms, label = "CA") + ax.plot(plotting_depths, last_field_sol[1], "^", ms = ms, label = "CC") + ax.plot(plotting_depths, last_field_sol[2], ">", ms = ms, label = "cCa") + ax.plot(plotting_depths, last_field_sol[3], "<", ms = ms, label = "cCO3") + ax.plot(plotting_depths, last_field_sol[4], "o", ms = ms, label = "Phi") + ax.set_xlabel("Depth (cm)") ax.set_ylabel("Compositions and concentrations (dimensionless)") ax.legend(loc='upper right') From c339393590e0d795f2c1edac94704a36b00e0a0d Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Tue, 3 Sep 2024 12:10:33 +0200 Subject: [PATCH 47/51] Clarification for users. Set default 'no_t_eval' really low to avoid stored results taking excessive disk space. --- marlpde/parameters.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/marlpde/parameters.py b/marlpde/parameters.py index 73151b4..021e62e 100644 --- a/marlpde/parameters.py +++ b/marlpde/parameters.py @@ -246,11 +246,12 @@ class Tracker: Settings for tracking progress and for storing intermediate results when solve_ivp runs. ''' - # Number of progress updates + # Number of progress updates. This only affects the progress bar. no_progress_updates: int = 100_000 # Number of times to evaluate, for storage. - no_t_eval: int = 1_000 + # 2 means only initial and end values. + no_t_eval: int = 2 # Array with all times that solutions from solve_ivp should be recorded. From 366b5231657428a59e41c4772e3a28aea9e3f1e2 Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Tue, 3 Sep 2024 12:14:27 +0200 Subject: [PATCH 48/51] Now we are back to 'integrate_equations' returning 5 objects instead of 6. And only the final solutions, which makes comparison with the ground truth somewhat simpler in terms of indexing. --- tests/Regression_test/test_regression.py | 35 ++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/Regression_test/test_regression.py b/tests/Regression_test/test_regression.py index c6f09d4..5fd174f 100644 --- a/tests/Regression_test/test_regression.py +++ b/tests/Regression_test/test_regression.py @@ -43,13 +43,13 @@ def test_integration_Scenario_A(): Scenario_parameters = asdict(Map_Scenario()) | \ {"Phi0": 0.6, "PhiIni": 0.5, "PhiNR": 0.6} # integrate_equations returns four variables, we only need the first one. - solution, _, _, _, _, _ = integrate_equations(asdict(Solver()), - asdict(Tracker()), - Scenario_parameters) + last_field_sol, _, _, _, _ = integrate_equations(asdict(Solver()), + asdict(Tracker()), + Scenario_parameters) # Test the final distribution of all five fields over depths - assert_allclose((solution.y)[:, -1], Scenario_A_data[-1, :, :], + assert_allclose(last_field_sol, Scenario_A_data[-1, :, :], rtol=rtol, atol=atol) def test_high_porosity_integration(): @@ -79,12 +79,12 @@ def test_high_porosity_integration(): # Concatenate the dict containing the Scenario parameters with the # dict containing the solver parameters (such as required tolerance). # integrate_equations returns four variables, we only need the first one. - solution, _, _, _, _, _ = integrate_equations(asdict(Solver_parms), - asdict(Tracker()), - Scenario_parameters) + last_field_sol, _, _, _, _ = integrate_equations(asdict(Solver_parms), + asdict(Tracker()), + Scenario_parameters) # Test the final distribution of all five fields over depths - assert_allclose((solution.y)[:, -1], high_porosity_data[-1, :, :], + assert_allclose(last_field_sol, high_porosity_data[-1, :, :], rtol=rtol, atol=atol) def test_cross_check_with_Matlab_output(): @@ -118,9 +118,9 @@ def test_cross_check_with_Matlab_output(): max_depth = Scenario_parameters["max_depth"] - solution, _, _, _, _, _ = integrate_equations(asdict(Solver()), - asdict(Tracker()), - Scenario_parameters) + last_field_sol, _, _, _, _ = integrate_equations(asdict(Solver()), + asdict(Tracker()), + Scenario_parameters) Number_of_depths = Scenario_parameters["N"] @@ -138,12 +138,13 @@ def test_cross_check_with_Matlab_output(): Matlab_output_interpolated[field, :] = np.interp(Python_plotting_depths, Matlab_depths, \ Matlab_output[field, :, 0]) - # Compare the Python and Matlab output over all depths, except for close to the surface, - # since we are dealing with a boundary layer near the surface - see chapter 7, page 56 of - # Willem Hundsdorfer: "Numerical Solution of Advection-Diffusion-Reaction Equations". - # Consequently, both the Matlab and Python solutions for the concentrations and the - # porosity jump a bit up and down near the surface, due to the high Peclet numbers. - assert_allclose((solution.y)[:, -1][:, 2:], + # Compare the Python and Matlab output over all depths, except for close to + # the surface, since we are dealing with a boundary layer near the surface + # - see chapter 7, page 56 of Willem Hundsdorfer: "Numerical Solution of + # Advection-Diffusion-Reaction Equations". Consequently, both the Matlab and + # Python solutions for the concentrations and the porosity jump a bit up and + # down near the surface, due to the high Peclet numbers. + assert_allclose(last_field_sol[:, 2:], Matlab_output_interpolated[:, 2:], atol = atol) From f5aafc64a2f8162cf41f3f3a7b45e28dc64d1bac Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Wed, 4 Sep 2024 17:50:06 +0200 Subject: [PATCH 49/51] Store the events as well, it will take little disk space. Exponential formatting of floats is often more readable. --- marlpde/Evolve_scenario.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 15094ba..07644fe 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -146,7 +146,7 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): print(f"Message from solve_ivp = {sol.message} \n") print(("Time taken for solve_ivp is " - f"{end_computing - start_computing:.2f}s. \n")) + f"{end_computing - start_computing:.2e}s. \n")) if sol.status == 0: covered_time = Tstar * end_time @@ -172,6 +172,7 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): with h5py.File(stored_results, "w") as stored: stored.create_dataset("solutions", data=field_solutions) stored.create_dataset("times", data=sol.t) + stored.create_dataset("events", data=sol.t_events) stored.attrs.update(stored_parms) # We will be plotting only the distributions corresponding to the last time. @@ -185,7 +186,7 @@ def Plot_results(last_field_sol, covered_time, depths, Xstar, store_folder): of depth. ''' fig, ax = plt.subplots() - fig.suptitle(f"Distributions after {covered_time:.2f} years") + fig.suptitle(f"Distributions after {covered_time:.2e} years") # Marker size ms = 5 plotting_depths = ScalarField.from_expression(depths, "x").data * Xstar From 477d7e9cb7f6e0eb300c746fdf5e11c203cb8f60 Mon Sep 17 00:00:00 2001 From: HannoSpreeuw Date: Wed, 4 Sep 2024 20:38:22 +0200 Subject: [PATCH 50/51] 'sol.t_events' is a list of ndarrays of different sizes. In order to store them in the hdf5 file, one has to iterate over this list and create a separate dataset for each list item, i.e. for each ndarray. --- marlpde/Evolve_scenario.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/marlpde/Evolve_scenario.py b/marlpde/Evolve_scenario.py index 07644fe..d576246 100644 --- a/marlpde/Evolve_scenario.py +++ b/marlpde/Evolve_scenario.py @@ -172,7 +172,9 @@ def integrate_equations(solver_parms, tracker_parms, pde_parms): with h5py.File(stored_results, "w") as stored: stored.create_dataset("solutions", data=field_solutions) stored.create_dataset("times", data=sol.t) - stored.create_dataset("events", data=sol.t_events) + for event_index, _ in enumerate(sol.t_events): + stored.create_dataset("event_" + str(event_index), + data=sol.t_events[event_index]) stored.attrs.update(stored_parms) # We will be plotting only the distributions corresponding to the last time. From e8fe41ad2a6dd55ec204d97dfa237ace2d0e5d1f Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Wed, 25 Sep 2024 16:04:40 +0200 Subject: [PATCH 51/51] README applicable after 'Use_solve_ivp_without_py-pde_wrapper' has been merged into 'main'. Grammar correction. A constant porosity diffusion coefficient is now in all branches. Functional Jacobians turn out not to applicable for this project, because of the discretization. The use of py-pde is now limited to its ScalarField and CartesianGrid. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c0ac52f..3597600 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Integrating diagenetic equations using Python -This repo was created as an attempt to reproduce the plots shown at the kickoff of the AstroTOM ("Turing or Milankovitch") project by Niklas Hohmann, from his Matlab scripts (available at [github.com/MindTheGap-ERC/LMA-Matlab](https://github.com/MindTheGap-ERC/LMA-Matlab)). +This repo was created in an attempt to reproduce the plots shown at the kickoff of the AstroTOM ("Turing or Milankovitch") project by Niklas Hohmann, from his Matlab scripts (available at [github.com/MindTheGap-ERC/LMA-Matlab](https://github.com/MindTheGap-ERC/LMA-Matlab)). AstroTOM is an OpenSSI 2021b project from the Netherlands eScience Center and Utrecht University (UU). Dr. Emilia Jarochowska (UU) is the lead applicant of this project. After replacing central differencing for the gradients in the five diagenetic equations 40-43 from [L'Heureux (2018)](https://www.hindawi.com/journals/geofluids/2018/4968315/) by forward and backward differencing depending on the sign of U and W as a first step and a Fiadeiro-Veronis spatial difference scheme as a second step, it turns out that these equations can be integrated for more than 13.190 years (the full T*) with an implicit or explicit (in time) solver, but not with a simple Eulerian scheme. A Runge-Kutta solver, with an adaptive timestep will, however, suffice. -After correcting the value of b (5-->5e-4) it turned out that a stable integration is also possible without a Fiadeiro-Veronis scheme. The `main` branch makes use of a constant porosity diffusion coefficient. +After correcting the value of b (5-->5e-4) it turned out that a stable integration is also possible without a Fiadeiro-Veronis scheme. We currently make use of a constant porosity diffusion coefficient. -Implicit (in time) solvers with use of Jacobians (in functional forms, so without numerical approximations) are available in the `Use_solve_ivp_without_py-pde_wrapper` branch. +The implicit (in time) solvers that `solve_ivp` offers can be deployed with its numerically approximated Jacobians and a Jacobian sparsity matrix. -Wide use is made of the [py-pde](https://py-pde.readthedocs.io/en/latest/) package, especially in the `main` branch. +Wide use is made of the [py-pde](https://py-pde.readthedocs.io/en/latest/) package, especially `CartesianGrid` and `ScalarField`. ## Installing and using To run this code, you need `git` and `conda` or `pip` to install .