'Solving an ODE with bounds on a variable
I am modelling a bacterial population that grows and dies while consuming a substrate. The model is defined by three ordinary differential equations, one for population, two for each substrate.
My issue is that I need to cap the maximum population to a certain integer. I have down this by adding a maximum_density_penalty
to my growth rate, which maps the difference between the current population count and the maximum count to a float between 0 and 1 using the logistic function.
I also need all those values to always be greater than 0. I believe the equations to solve for this, but my issue, I believe, is that the t
time step value given by the solve_ivp
function is too large and overshoots my calculations. I can show full code for the model if necessary.
Below is a minimal reproducible example.
import numpy as np
from math import floor
from scipy.integrate import solve_ivp
# Initial conditions
initial_carbon_content = 1000000000000
initial_inorganic_carbon_content = 0
initial_cell_count = 10 ** 5
# Community paramaters
natural_death_fraction = 0.001 # %/day
# Heterotroph organism paramaters
ks = 882000000
carbon_content_per_cell = 100
growth_rate = 1 # day^-1 - Max growth rate.
# System paramaters
maximum_cell_count = 10 ** 9
duration = 11000 * 365.25
# Set up initial condition vector
y0 = [initial_carbon_content, initial_cell_count]
t_span = (0, duration) # time grid
def model(t, y):
organic_carbon_content = y[0]
cell_count = y[1]
# Growth
x = max(maximum_cell_count - cell_count, 0)
maximum_density_penalty = np.arctan(x)/(np.pi/2)
penalized_growth_rate = growth_rate * maximum_density_penalty
growth = floor(penalized_growth_rate * (organic_carbon_content / (ks + organic_carbon_content)) * cell_count)
# Calculate the amount of cells at next step:
# next_cell_count = (cell_count + growth - natural_deaths) * t
# Natural Death
natural_deaths = floor(natural_death_fraction * cell_count)
# Organic carbon requirement
required_organic_carbon_per_cell = 5
required_organic_carbon = required_organic_carbon_per_cell * cell_count
# Starvation
starvation_deaths = floor(max((required_organic_carbon - organic_carbon_content), 0) / required_organic_carbon_per_cell)
# Deaths
deaths = starvation_deaths + natural_deaths
# Net cell count change
dndt = growth - deaths
## ORGANIC CARBON
# Organic carbon outputs
consumed_organic_carbon_from_population = required_organic_carbon_per_cell * (cell_count - starvation_deaths)
consumed_organic_carbon_from_growth = dndt * carbon_content_per_cell
total_organic_carbon_outputs = consumed_organic_carbon_from_population + consumed_organic_carbon_from_growth
# Net organic carbon change
dsdt = - total_organic_carbon_outputs
assert 0 <= organic_carbon_content + dsdt
assert 0 <= cell_count + dndt <= maximum_cell_count
return [dsdt, dndt]
# solve the ODEs
soln = solve_ivp(fun=model, y0=y0, t_span=t_span)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|