Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #943 +/- ##
========================================
Coverage 94.21% 94.22%
========================================
Files 79 79
Lines 6518 6563 +45
========================================
+ Hits 6141 6184 +43
- Misses 377 379 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| "foliage_c_n_ratio", | ||
| "foliage_c_p_ratio", | ||
| ] | ||
|
|
There was a problem hiding this comment.
What about lignin content for the different tissues, as well as carbon mass per propagule, where are these located? Are these still seen as constants?
There was a problem hiding this comment.
These are currently still set in the constants, in the plant consts model.
I guess at some point we would break that out as well, and ExtraTraitsPFT can be used for that.
| self.data["deadwood_c_n_ratio"] = xr.full_like( | ||
| self.data["elevation"], self.model_constants.deadwood_c_n_ratio | ||
| ) | ||
| self.data["deadwood_c_n_ratio"] = xr.full_like(self.data["elevation"], 56.5) |
There was a problem hiding this comment.
Can you help me understand what this does:
self.data["deadwood_c_n_ratio"] = xr.full_like(self.data["elevation"], 56.5)
There was a problem hiding this comment.
This uses default values for the tissue variables, to get passed to @jacobcook1995 . This needs to be dynamic - however I am hoping to do that in another PR. Also need to discuss exactly how to calculate those values. Will add a comment noting this todo!
| reclaim_ratio=np.array( | ||
| [ | ||
| extra_pft_traits.traits[name]["leaf_turnover_c_n_ratio"] |
There was a problem hiding this comment.
What does reclaim_ratio stand for (i.e., how does it behave in the model)?
-Is it to calculate the amount of nutrients that are reclaimed (and thus kept within the tree) before leaves are lost due to turnover? If so, would this mean we need both a (senesced) leaf_c_n_ratio and leaf_turnover_c_n_ratio to calculate their difference?
-I vaguely remember reading about how the nutrient cost to replace turnover must be taken into account, so perhaps that's what this reclaim_ratio does? Could you please remind me again how this works?
There was a problem hiding this comment.
Yes, exactly (nutrients reclaimed). There are two separate ratios - the foliage ratio (healthy) and the turnover (senseced). It's a bit confusing, so this is something that I will need to eventually clarify in the docs.
I definitely owe a big doc refresh for all of stochiometry - will add an issue for this.
There was a problem hiding this comment.
Hi @sallymatson, thanks for the clarification. I agree it's a bit difficult to understand what is being referred to with turnover (senesced) leaves. Are they already considered turnover/litter? Has nutrient resorption already taken place (I assume we are talking about adult/mature leaves here, or are you referring to something more specific with senesced?). Should nutrient resorption be the difference between the nutrient content of senesced (i.e., mature/adult) leaves and leaf turnover/litter nutrient content (in my opinion this is how nutrient resorption should be calculated). I think most of the data on leaf nutrient content for Borneo comes from chemical analysis on leaf litter, so working with an average ratio of fresh leaves-litter nutrient content sounds like the likely way to go.
On second thought, it seems likely that senesced already refers post resorption, as else I don't see why we'd also have the other "healthy" leaves.
There was a problem hiding this comment.
The idea is that the plants model calculates how much turnover there is in each timestep. This gives us the amount of leaves that will senesce, and therefore pass into the litter model. These leaves are never part of the tree so leaves are never "considered" senesced, however since the tree reclaims nutrients, we need to know the difference in the stochiometric ratio for the two different forms.
There was a problem hiding this comment.
These leaves are never part of the tree
They kinda are 😄 .
On second thought, it seems likely that senesced already refers post resorption, as else I don't see why we'd also have the other "healthy" leaves.
That's correct. The leaf mass of the tree has a target stoichiometric ratio for leaf tissue in general. We don't currently have any kind of leaf age or leaf-economics model. The leaves try and track that ratio as closely as possible but may not be able to realise the ideal ratio if nutrients are limiting.
When we calculate the leaf mass turnover in a time step, there is immediately a resorption of nutrients using the reclaim ratio. The reclaimed nutrients are reallocated within the tree and the remaining nutrients are lost to litter.
There was a problem hiding this comment.
Thanks for the clarification @sallymatson, this is very helpful.
These leaves are never part of the tree
They kinda are 😄 .
In theory they should contribute to foliage mass before they get turned into leaf litter, but I can see how working within a timestep leads to this approach. This does seem to make an important assumption about the link between litterfall timing and the timestep length, but I guess since turnover is scaled according to time (i.e., per year) this mostly solves that issue?
That's correct. The leaf mass of the tree has a target stoichiometric ratio for leaf tissue in general. We don't currently have any kind of leaf age or leaf-economics model. The leaves try and track that ratio as closely as possible but may not be able to realise the ideal ratio if nutrients are limiting.
When we calculate the leaf mass turnover in a time step, there is immediately a resorption of nutrients using the reclaim ratio. The reclaimed nutrients are reallocated within the tree and the remaining nutrients are lost to litter.
Also, thanks for clarifying this @davidorme.
Some additional thoughts: It's interesting to think about how nutrient limitation may affect other processes in the model. For example, it seems likely that, apart from lower tissue nutrient content, the allocation in the T model may change, and GPP would also change depending on leaf nutrient content. The same goes for when there is an excess in nutrients, would a tree choose to create more nutrient rich tissues (as currently implemented), or would it create more tissues (e.g., invest in greater leaf area). These processes are likely to be quite complex and influenced by many things (like environment, competition, etc.).
There was a problem hiding this comment.
Yes... that's definitely something we've discussed. We've come to the conclusion that resource competition is currently WAY too complex, but it's critical for the next step of the model (i.e. after our first runs/prototypes.) If you have knowledge in that area it'll be super helpful when we begin to implement it.
| name,a_hd,ca_ratio,h_max,lai,par_ext,resp_f,resp_r,resp_s,rho_s,sla,tau_f,tau_r,yld,zeta,f_g,m,n,tau_rt,resp_rt,gpp_topslice,p_foliage_for_reproductive_tissue | ||
| test1,116.0,390.43,25.33,1.8,0.5,0.1,0.913,0.044,200.0,14.0,4.0,1.04,0.6,0.17,0.02,2,5,1,0.05,0.1,0.05 | ||
| test2,116.0,390.43,15.33,1.8,0.5,0.1,0.913,0.044,200.0,14.0,4.0,1.04,0.6,0.17,0.02,2,5,1,0.05,0.1,0.05 No newline at end of file | ||
| name,a_hd,ca_ratio,h_max,lai,par_ext,resp_f,resp_r,resp_s,rho_s,sla,tau_f,tau_r,yld,zeta,f_g,m,n,tau_rt,resp_rt,gpp_topslice,p_foliage_for_reproductive_tissue,deadwood_c_n_ratio,deadwood_c_p_ratio,leaf_turnover_c_n_ratio,leaf_turnover_c_p_ratio,plant_reproductive_tissue_turnover_c_n_ratio,plant_reproductive_tissue_turnover_c_p_ratio,root_turnover_c_p_ratio,root_turnover_c_n_ratio,foliage_c_n_ratio,foliage_c_p_ratio |
There was a problem hiding this comment.
Should lignin content of tissues and carbon mass per propagule also be here?
There was a problem hiding this comment.
Eventually yes - for now it is out of scope of this PR / where we are at rn.
|
Hi @sallymatson, it looks good to me. I left a few questions about tissue lignin content and carbon mass per propagule, and some questions about what some parts of the code do but other than that no remarks from me. |
There was a problem hiding this comment.
This looks good but I think there is an issue with the class method on the ABC.
ABC objects are not intended to be directly used and all functionality should be through subclasses. The from_pft_default_ratios @classmethod should be an @abstract_method of Tissue and then the individual tissue subclasses should implement their own methods. This isn't exactly like you are creating an instance of Tissue - which is definitely not intended with ABCs - but the class method relies on the definition of specific downstream subclasses. If we wanted to add a new Tissue, we'd have to edit the ABC to support it. I can see why you've done it - because then you have the code to index the ratios from PFT names in a single location - but it isn't a clean structure.
I think there's an argument for making ExtraPFTTraits more like Flora, so it can use the CohortMethods and PandasExporter mixins from pyrealm. Then we could keep the traits in line with the community PFTs using the same mechanism and wouldn't have to do that alignment. But that might be a tweak for a separate PR.
| @classmethod | ||
| def from_pft_default_ratios( | ||
| cls, | ||
| subclass, | ||
| community: Community, | ||
| extra_pft_traits: ExtraTraitsPFT, | ||
| ratio_name: str, | ||
| ) -> "Tissue": |
There was a problem hiding this comment.
I think this should become an abstract method.
There was a problem hiding this comment.
@davidorme updated - can you take a look and see if it's what you intended?
There was a problem hiding this comment.
Yup - that's what I intended 😄.
I vaguely wonder if there's an argument for nesting dicts within ExtraTraits so we could do:
extra_pft_traits.traits[name][element_name]["foliage_c_ratio"]
But that seems like something to circle back to and might clash with making ExtraTraitsPFT use CohortMethods etc later
I think it is absolutely fine to abstract that detail from the users. If we wanted to get a bit cleaner, Flora has an |
Description
I've now completed a draft of the
ExtraTraitsPFTclass. The initial goal of this class is to allow us to define stoichiometric ratios for plant tissues by PFT (before, they were all set to standard defaults in the plant constants.) To do this I have:ExtraTraitsPFT) which stores a dictionary (keyed by PFT name) of dictionaries (keyed by traits). This is used in parallel with theFloramodel, meaning that it stores these values per PFT, but it does not store any information about cohorts, grid cells, etc so it is essentially a reference dictionary for the entirety of the simulation.get_flora_from_configmethod to return both aFlorainstance and anExtraTraitsPFTinstance, and made that correction throughout the model. This part is a bit hacky, as it takes a pre-defined list of "stochiometry traits" to separate out to set up theExtraTraitsPFTand uses the rest for theFlora. It works for now but it's a bit hardcoded, so would love thoughts on if we should make this more flexible, or if it's ok given that we do want to obstruct some of these things from the user (the user should just give all the traits for a PFT in the schema, and let US decide which belong where, as it's a somewhat arbitrary dictinction between what is in pyrealm and what is not.)PlantConstsand removed relevant references in the plants model and stoichiometry model.Fixes # (issue)
Type of change
Key checklist
pre-commitchecks:$ pre-commit run -a$ poetry run pytestFurther checks