Problem
Ice particle distribution properties are recalculated many times each timestep causing a lot of unnecessary non-trivial work for the Grid_Aerosol class. I am sure the same problems occur for the Aerosol class but it is inexpensive given it is not spatially resolved.
The offending properties are: moments 1, 2 & 3, IWC, and extinction. We could add xOD and yOD to this list but they do not come up as often.
As an example per timestep:
Extinction() is called: 1 time when saving, 1 time when calling yOD, 1 time when calling xOD, 2 times calling extinctionWidthIndices, 2 times when calling extinctionDepthIndices.
yOD is called once (saving)
xOD is called twice (saving and determining shear)
extinctionDepthIndices is called once (saving via extinctionDepth)
extinctionWidthIndices is called once (saving via extinctionWidth)
That's 1 + 1 + 1*2 + 2 + 2 = 8 calls to this function. Each of these calls requires loop over the full grid + calls IWC() and EffRadius(). Both of which also loop over the full grid + also call other functions which also loop over the full grid and call other functions that ... You get the point, eventually all these functions call Moment() for the 1st, 2nd or 3rd moment.
This is every timestep...
Solution
Each timestep we can compute once the moments, potentially IWC and extinction and reuse them for all other calculations that timestep.
Implementation
This is the first thing I came up with, I am happy to get feedback on this:
- Make a new class
GridAerosolProperties with members for the properties we want to cache. It also stores a boolean flag is_current to indicate if the stored properties are in sync with the PDF.
- Add
GridAerosolProperties as a member variable to the Grid_Aerosol class. The two functions that mutate the PDF state Grid_Aerosol::Grow and Grid_Aerosol::Coagulate invalidate is_current when called.
- Any getter for a member of
GridAerosolProperties checks the is_current flag and recomputes all properties if is_current is false when called, and then sets is_current to true when done recomputing.
Given we only run Grid_Aerosol::Grow once per timestep (coagulation is disabled currently), all the properties would be computed once and reused throughout the timestep.
Problem
Ice particle distribution properties are recalculated many times each timestep causing a lot of unnecessary non-trivial work for the
Grid_Aerosolclass. I am sure the same problems occur for theAerosolclass but it is inexpensive given it is not spatially resolved.The offending properties are: moments 1, 2 & 3, IWC, and extinction. We could add xOD and yOD to this list but they do not come up as often.
As an example per timestep:
Extinction()is called: 1 time when saving, 1 time when callingyOD, 1 time when callingxOD, 2 times callingextinctionWidthIndices, 2 times when callingextinctionDepthIndices.yODis called once (saving)xODis called twice (saving and determining shear)extinctionDepthIndicesis called once (saving viaextinctionDepth)extinctionWidthIndicesis called once (saving viaextinctionWidth)That's 1 + 1 + 1*2 + 2 + 2 = 8 calls to this function. Each of these calls requires loop over the full grid + calls
IWC()andEffRadius(). Both of which also loop over the full grid + also call other functions which also loop over the full grid and call other functions that ... You get the point, eventually all these functions callMoment()for the 1st, 2nd or 3rd moment.This is every timestep...
Solution
Each timestep we can compute once the moments, potentially IWC and extinction and reuse them for all other calculations that timestep.
Implementation
This is the first thing I came up with, I am happy to get feedback on this:
GridAerosolPropertieswith members for the properties we want to cache. It also stores a boolean flagis_currentto indicate if the stored properties are in sync with the PDF.GridAerosolPropertiesas a member variable to theGrid_Aerosolclass. The two functions that mutate the PDF stateGrid_Aerosol::GrowandGrid_Aerosol::Coagulateinvalidateis_currentwhen called.GridAerosolPropertieschecks theis_currentflag and recomputes all properties ifis_currentis false when called, and then setsis_currentto true when done recomputing.Given we only run
Grid_Aerosol::Growonce per timestep (coagulation is disabled currently), all the properties would be computed once and reused throughout the timestep.