Using a kernel to calculate larval growth parameters, running into issues #2089
-
QuestionQuestionGood afternoon, I am working on a parcels simulation that uses interpolated temperature values to calculate the growth of larvae over time. I'm doing this to create a more mechanistic approach to simulating PLDs. I have tried to do this using the code below, but have run into some issues. Can you help me? I have split the code into three "chunks" where I think the issues may lie. Supporting code/error messages# Paste your code within this block
###### Code chunk 1: This code creates a funtion that, using development times for a larval species at 3 temperatures from the literature, interpolates a development time for a larva at a specified temperature. **It is encoded in the global environment,** outside of the kernels (which I think causes issues with the JITParticle and its interaction with C -- more on this later)
# Prepare larval physiological data from Sprung (1984).
T_data = np.array([18, 12, 6]) # Experimental temperatures, 18, 12 and 6* C
t_data40 = np.array([457.68, 666.48, 1554.72]) # Developmental times at respective temperatures. As temperature increases, development time decreases due to the energetics of metabolism.
# Sort data for interpolation
sorted_indices = np.argsort(T_data)
T_data = T_data[sorted_indices]
t_data40 = t_data40[sorted_indices]
# Create the interpolation function
interp_func = interp1d(T_data, t_data40, kind='linear')
# Define the development time function
def get_Dt(T):
"""Return interpolated development time (Dt) for a given temperature T."""
return float(interp_func(T))
# Example:
T=10
get_Dt(T) # Should return a value of 962 hours to full development, at a temperature of 10 degrees C.
###### Code chunk 2: This code designates the various particle variables I intend to use for my calculations
# Creates a "column" within the particle in which to place data
extra_vars = [
# Variable('age', dtype=np.float32, initial=0, to_write=False),
Variable('cohort', dtype=np.int32, to_write='once'), # Cohort designation. Tells us the week in which a particle is released
Variable('on_land', dtype=np.int32, to_write=False), # An important coastal reflection kernel parameter
Variable('T', dtype=np.float32), # Temperature value at the respective timestep. Interpolated from fieldset "thetao"
Variable('Dt', dtype=np.float32), # Estimated development time at the given temperature, which is used to calcualte G below
Variable('G', dtype=np.float32), # Growth parameter. This represents the size increase of a particle per timestep
Variable('S', dtype=np.float32, initial=70.), # Cumulative size of the particle, starting at 70 microns
]
Particle = JITParticle.add_variables(extra_vars)
###### Code chunk 3: These are my kernels. The first interpolates temperature from the fieldset: it seems to work well. The second uses this temperature to calculate the expected development time (Code chunk 1). This is where I run into my first error. The third uses the expected development time to calculate the growth of the larvae in micrometers for that hour. And finally, the fourth adds this growth to the larva's overall size (so that they grow cumulatively).
def SampleT(particle, fieldset, time):
"""Sample the temperature field"""
particle.T = fieldset.T[time, particle.depth, particle.lat, particle.lon]
def InterpolateDt(particle, fieldset, time):
particle.Dt = get_Dt(particle.T)
def CalculateG(particle, fieldset, time):
particle.G = 230 / particle.Dt #230 is the number of microns required to reach full development, at which point larvae become able to settle.
def GrowS(particle, fieldset, time):
particle.S += particle.G
#In my pset.execute, I specified the kernels in order of calculation:
kernels = pset.Kernel(Sample_land) + pset.Kernel(Unbeaching) + \
pset.Kernel(AdvectionRK4) + pset.Kernel(DiffusionUniformKh) + \
pset.Kernel(SampleT) + pset.Kernel(InterpolateDt) + pset.Kernel(CalculateG) + \
pset.Kernel(GrowS) + pset.Kernel(CheckOutOfBounds)I think it's getting there, but whenever I run this code, I get this huge error, the likes of which I do not understand. I believe it has something to do with C getting confused by the use of get_Dt within my kernel. Are you able to offer any support with this? I have considered using a non-JIT particle to see if I can get around the C issue. Alternatively, I could try and define the function within the kernel? Thanks in advance, Tom |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
|
Thanks @TomMBIO, for raising this question. Indeed, your def get_Dt(particle, fieldset, time):
# your Kernel codeHowever, note that in JIT mode, it is not possible to call other functions. Nor can Kernels Note that this limited amount of allowed declarations is actually one of the reasons we're currently working on Parcels v4, but I guess you can't wait another few months until that lands? |
Beta Was this translation helpful? Give feedback.
-
|
Should the first condition in your ---if particle.S == 0:
+++if particle.S == 70: |
Beta Was this translation helpful? Give feedback.
Should the first condition in your
GrowSkernel not beif particle.S == 70? Because you initialise it at 70, so it will never be 0...