Created
December 2, 2015 00:23
-
-
Save SiccarPoint/1bd979e42bb48d6ad0ab to your computer and use it in GitHub Desktop.
This shows the different ways one could have a component "time" parameter work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# #1: As a "run until" style: | |
# approach seems fiddly and annoying to me, but has advantage of always being general: | |
time_elapsed = 0. | |
dt = 5. # or whatever | |
while elapsed_time < total_time: | |
new_time = elapsed_time + dt | |
if new_time > total_time: | |
new_time = total_time - elapsed_time | |
my_component.run_component(new_time, *args, **kwds) | |
elapsed_time = new_time | |
# if actual "clock time" matters to the component (e.g., time of day for solar rad), this is clearly trivial | |
# to implement | |
# #2: As a timestep style. | |
# very easy to implement, iff total_time%dt == 0; <0.5 the lines of the other way | |
loops = int(total_time//dt) | |
assert total_time%dt == 0. # don't actually need to do this check if you know ahead of time you know this is true | |
for i in xrange(loops): | |
my_component.run_component(dt, *args, **kwds) | |
# if you can't be totally sure the total_time is a multiple of your dt (...but you can always *make* it so...!), | |
# you can do this: | |
loops = int(total_time//dt) | |
final_time_interval = total_time%dt | |
for i in xrange(loops): | |
my_component.run_component(dt, *args, **kwds) | |
my.component.run_component(final_time_interval, *args, **kwds) | |
# If your component requires an internal clock time, you'll have to track it separately. It can either be tracked | |
# internally to the component (I might prefer this? - after all, discritized differential equation components have | |
# to do this in "run until" cases already anyway), or passed in as an argument, or that kind of component just | |
# has a different signture that takes total time. | |
# Individual storm tracking is really easy this way, as the storms are easy to envision as just a duration and | |
# intensity pair: | |
from landlab.components.uniform_precip.generate_uniform_precip import PrecipitationDistribution | |
precip = PrecipitationDistribution(input_file) | |
for (dt, intensity) in precip.yield_storm_interstorm_duration_intensity(): | |
my_component.run_component(dt, intensity=intensity) | |
# The equivalent set up for a run_until signature would look much uglier, and be a lot less intuitive. | |
""" | |
So, the way I see it, the dt method is almost always cleaner to work with, and arguably more pythonic | |
(look at that lovely generator in the final example!) but has the disadvantages that: | |
1. You have to be thinking about what you want to do. With run_until styles, the way it runs is totally | |
uniform every time (but that boilerplate text is twice as long, will run a bit slower, is arguably | |
more opaque, and requires logic testing in every iteration of the loop). | |
2. Any component that needs to know actual clock time doesn't get it "for free" any more. It either has | |
(a) to be tracked and passed in separately by the driver, (b) have a fundamentally nonstandard | |
signature, or (c) track clock time on its own internally. This actually might be a false choice anyway, | |
as internal tracking must already be occurring to handle the conversion of elapsed_time into | |
time_of_day, and we would be doing the equivalent for mass flux methods based on e.g., von Neumann | |
stability conditions (expressed as intervals, not clock times) if we chose the other option. | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NB: the "run_component" method is just a dummy. I wasn't intending to suggest standardisation of this! I take your point on BMI, but I still like retaining component-specific method names, e.g., erode, route_flow, etc because I think it's clearer what each component is doing. There could also be components with more than one run method (e.g., the storm generating component). These would rule out using "..._for", grammatically as well. We could always have standard named wrappers for the functions in addition as a compromise.
Random thoughts: