Module Contents

class ifcopenshell.api.sequence.cascade_schedule.Usecase
cascade_task(task, is_first_task=False, task_sequence=None)
get_task_time_attribute(task, attribute)
offset_date(date, days, duration_type, calendar)
ifcopenshell.api.sequence.cascade_schedule.cascade_schedule(file, task=None) None

Cascades start and end dates of tasks based on durations

Given a start task with a start date and duration, the end date, and the start and end of all successor tasks with durations may be automatically computed.

Using this automatic computation is recommended is an alternative to manually specifying dates. It is useful for doing edits and cascading changes.

Dates can only cascade from predecessor to successors, not backwards. Cyclical relationships are invalid and will result in a recursion error being raised.

Note that there may be differences between how different planning software calculate start and end dates. Some may consider Monday 5pm to be equivalent to be Tuesday 8am, for instance.


task (ifcopenshell.entity_instance) – The start task to begin cascading from.



Return type:



# Define a convenience function to add a task chained to a predecessor
def add_task(model, name, predecessor, work_schedule):
    # Add a construction task
    task = ifcopenshell.api.run("sequence.add_task", model,
        work_schedule=work_schedule, name=name, predefined_type="CONSTRUCTION")

    # Give it a time
    task_time = ifcopenshell.api.run("sequence.add_task_time", model, task=task)

    # Arbitrarily set the task's scheduled time duration to be 1 week
    ifcopenshell.api.run("sequence.edit_task_time", model, task_time=task_time,
        attributes={"ScheduleStart": datetime.date(2000, 1, 1), "ScheduleDuration": "P1W"})

    # If a predecessor exists, create a finish to start relationship
    if predecessor:
        ifcopenshell.api.run("sequence.assign_sequence", model,
            relating_process=predecessor, related_process=task)

    return task

# Open an existing IFC4 model you have of a building
model = ifcopenshell.open("/path/to/existing/model.ifc")

# Create a new construction schedule
schedule = ifcopenshell.api.run("sequence.add_work_schedule", model, name="Construction")

# Let's imagine a starting task for site establishment.
task = add_task(model, "Site establishment", None, schedule)
start_task = task

# Get all our storeys sorted by elevation ascending.
storeys = sorted(model.by_type("IfcBuildingStorey"), key=lambda s: get_storey_elevation(s))

# For each storey ...
for storey in storeys:

    # Add a construction task to construct that storey, using our convenience function
    task = add_task(model, f"Construct {storey.Name}", task, schedule)

    # Assign all the products in that storey to the task as construction outputs.
    for product in get_decomposition(storey):
        ifcopenshell.api.run("sequence.assign_product", model, relating_product=product, related_object=task)

# Ask the computer to calculate all the dates for us from the start task.
# For example, if the first task started on the 1st of January and took a
# week, the next task will start on the 8th of January. This saves us
# manually doing date calculations.
ifcopenshell.api.run("sequence.cascade_schedule", model, task=start_task)

# Calculate the critical path and floats.
ifcopenshell.api.run("sequence.recalculate_schedule", model, work_schedule=schedule)