Skip to content

Process

The model is assembled, its behavior is assigned, and the objects needed for the simulation have been defined. The remaining question is no longer what exists, but what happens, and in what order.

Femora answers that question with model.process. A process is an ordered executable timeline of previously defined components. It is not an analysis algorithm, a solver, or a command that runs OpenSees by itself.

Definition: What does this object represent?
Process:    When should its command appear?
Analysis:   How should the solver advance the model?
Export:     How is the complete model translated for OpenSees?

The Final Integration Step

Earlier concept pages treated loading, recorders and actions, constraints, and analysis separately because each has its own responsibility. Process brings the runtime components together without changing those responsibilities.

flowchart LR
    defined["Defined objects<br/>patterns, recorders,<br/>actions, analyses"] --> timeline["Process<br/>ordered timeline"]
    timeline --> export["Tcl export<br/>commands in order"]
    export --> solver["OpenSees<br/>executes the script"]

    classDef input stroke-width:1px;
    classDef process stroke-width:2px;
    classDef result stroke-width:1px;
    class defined input;
    class timeline process;
    class export,solver result;

The distinction between export and execution matters. model.export_to_tcl(...) writes the model and the ordered process to a Tcl script. The analyses run only when OpenSees executes that script.

Process is not the solver

model.process.add_step(...) does not solve an equation and does not advance time. It records where a component's Tcl representation belongs in the exported command sequence. An Analysis component is the step that configures the numerical solution and issues the OpenSees analyze commands.

What Can Appear In A Process

The current process manager accepts the following component types:

Component Effect when its step is reached
Pattern Introduces a load pattern or excitation rule into the active domain
Recorder Creates a runtime recorder that observes subsequent converged response
Action Emits a state-changing command at that exact location
Analysis Configures the analysis, advances the model, and then clears that analysis configuration
SPConstraint Emits a single-point constraint command
MPConstraint Emits a multi-point constraint command

Patterns, recorders, analyses, and constraints are normally created and managed by their corresponding model managers. Actions are lightweight commands created through model.actions for transitions such as holding the current load state, changing time, removing recorders, or changing material stage.

Ordinary constraints already belong to model export

Although ProcessManager accepts SP and MP constraint objects, Femora's Tcl exporter already writes all model-managed constraints during model setup, before time series and the process block. Adding the same managed constraint to the process can therefore emit it again. Use model.constraint for ordinary assembled-model constraints; schedule a constraint only for a deliberate staged workflow whose solver behavior you have verified.

Defining Is Not Scheduling

Creating an object through a manager gives Femora its definition. It does not automatically place that object in the runtime timeline.

# These objects are defined and managed, but this code does not order them.
gravity_pattern = model.pattern.plain(time_series=gravity_series)
tip_displacement = model.recorder.node(
    file_name="beam_tip_disp.out",
    nodes=beam_tip_tags,
    dofs=[1],
    resp_type="disp",
    time=True,
)
gravity_analysis = model.analysis.static(
    name="gravity",
    constraint_handler=gravity_constraints,
    numberer=gravity_numberer,
    system=gravity_system,
    algorithm=gravity_algorithm,
    test=gravity_test,
    integrator=gravity_integrator,
    num_steps=10,
)

The complete signatures and choices belong in the API reference and in their dedicated concept pages. At the process level, these objects are already prepared inputs. Scheduling them is a separate operation:

model.process.add_step(
    gravity_pattern,
    description="Introduce gravity loading",
)
model.process.add_step(
    tip_displacement,
    description="Start recording beam-tip displacement",
)
model.process.add_step(
    gravity_analysis,
    description="Run gravity analysis",
)

This order means: introduce the gravity pattern, activate the recorder, and then advance the model. Reversing those lines changes the simulation rather than merely changing its presentation.

Write descriptions as runtime events

A description becomes a comment heading in the exported Tcl. Prefer "Start recording beam-tip displacement" or "Run gravity analysis" over vague labels such as "Step 3". Clear descriptions make a generated script much easier to inspect and debug.

Build A Multi-Stage Timeline

Continue the soil-structure example from the earlier concepts. Assume the following managed objects have already been defined:

Existing object Responsibility
gravity_pattern Introduces the gravity loads
gravity_analysis Advances the model through the gravity stage
seismic_pattern Introduces the support excitation
dynamic_analysis Advances the model through the transient stage
tip_displacement Records the selected response after activation

We need two transitions between the analyses. First, retain the converged gravity load level. Then reset pseudo-time before the earthquake history begins:

hold_gravity = model.actions.load_const()
reset_time = model.actions.set_time(0.0)
stop_recording = model.actions.remove_recorders()

Creating these actions still does nothing to the solver. Their position gives them meaning.

Step 1: Introduce Gravity And Observe It

model.process.add_step(
    gravity_pattern,
    description="Introduce gravity loading",
)
model.process.add_step(
    tip_displacement,
    description="Start recording beam-tip displacement",
)
model.process.add_step(
    gravity_analysis,
    description="Run gravity analysis",
)

The recorder is placed before gravity_analysis, so its output includes the gravity stage. If only the dynamic response were required, the recorder could instead be placed after the gravity transitions and before dynamic_analysis.

Step 2: Close The Gravity Stage

model.process.add_step(
    hold_gravity,
    description="Hold the converged gravity load",
)
model.process.add_step(
    reset_time,
    description="Reset pseudo-time before excitation",
)

These are two independent state changes. load_const() emits the command that holds the current loading state. set_time(0.0) explicitly sets the time seen by later commands.

An Analysis cleans up its own analysis configuration

The current Analysis.to_tcl() output ends with wipeAnalysis. This clears the numerical analysis configuration after that analysis finishes while preserving the finite-element domain. A separate model.actions.wipe_analysis() step is therefore not normally required between managed Analysis components.

Step 3: Run The Dynamic Stage

model.process.add_step(
    seismic_pattern,
    description="Introduce earthquake excitation",
)
model.process.add_step(
    dynamic_analysis,
    description="Run transient analysis",
)
model.process.add_step(
    stop_recording,
    description="Close runtime recorders",
)

The excitation must exist before the transient analysis advances time. The recorder remains active through both analyses and is removed only after the dynamic stage has finished.

The complete process now reads as an engineering sequence rather than a collection of disconnected commands:

flowchart LR
    gravity["Gravity pattern"] --> recorder["Start recorder"]
    recorder --> static["Gravity analysis"]
    static --> hold["Hold gravity"]
    hold --> time["Reset time"]
    time --> motion["Seismic pattern"]
    motion --> transient["Transient analysis"]
    transient --> close["Remove recorders"]

    classDef definition stroke-width:1px;
    classDef advance stroke-width:2px;
    classDef transition stroke-width:1px,stroke-dasharray:4 2;
    class gravity,recorder,motion definition;
    class static,transient advance;
    class hold,time,close transition;

Ordering Changes Behavior

Process order is executable state, not documentation order. Three rules prevent most workflow errors:

Requirement Correct placement Consequence of incorrect placement
Apply loading Pattern before the analysis that should use it The analysis advances without that loading rule
Capture response Recorder before the analysis to observe Earlier response cannot be recovered afterward
Change stages Action between the stages it separates The action changes the wrong stage, or has no useful effect
A valid component can still be in the wrong place

Type validation only confirms that an object is allowed in the process. It cannot determine your engineering intent. A recorder placed after an analysis, a pattern introduced too late, or remove_recorders() placed too early is syntactically valid but behaviorally wrong.

Terminal actions end the remaining timeline

model.actions.exit() terminates OpenSees, and model.actions.wipe() clears the complete domain. Any steps placed after either action may be unreachable or invalid. Use them only when that termination or reset is intentional.

Inspect And Edit The Timeline

ProcessManager preserves list order. You can inspect the completed timeline before export without changing it:

for step_index, step in enumerate(model.process.get_steps()):
    print(step_index, step["description"])

During construction, add_step(...) returns the zero-based index of the appended entry. insert_step(index, ...) places a component at a chosen position. Both methods also accept a list of supported components, with each component becoming its own entry. get_step(index) retrieves one entry, remove_step(index) removes one entry, and clear() removes the complete timeline. Use these operations before export; changing the Python process does not alter a Tcl file that has already been written.

The process refers to managed objects

Internally, the process keeps non-owning references to managed patterns, recorders, constraints, and analyses; actions are retained directly. In normal use this is transparent because the model managers own their components. Do not remove or clear a managed component after scheduling it and then expect the process entry to remain valid.

What Tcl Export Does

When model.export_to_tcl(...) runs, Femora does not start at the process. It first writes the solver model: materials, transformations, sections, nodes, elements, damping, regions, constraints, and time series. Only after those prerequisites exist does it ask ProcessManager to emit the timeline.

model definition
    -> damping and regions
    -> model constraints
    -> time series
    -> process steps in list order
    -> exit

For each process entry, Femora writes a heading from its description and then calls that component's to_tcl() method. Conceptually, the example becomes:

# Introduce gravity loading ======================================
pattern Plain ...

# Start recording beam-tip displacement =========================
recorder Node ...

# Run gravity analysis ===========================================
constraints ...
numberer ...
system ...
algorithm ...
test ...
integrator ...
analysis Static
analyze 10
wipeAnalysis

# Hold the converged gravity load ================================
loadConst

The exact commands depend on the scheduled objects. The important guarantee is that the process entries are translated in their stored order.

model.export_to_tcl("model.tcl")

This creates the OpenSees script. Running that script is a separate execution operation.

Debug the process from both sides

Before export, inspect model.process.get_steps() to confirm the Python order and descriptions. After export, inspect the # Process section of the Tcl file to confirm the commands produced by each component. This separates timeline mistakes from component-translation mistakes.

API Reference

The generated API reference provides exact signatures, accepted arguments, return values, and component-specific behavior.

  • Process Manager

    Ordered-step creation, insertion, removal, inspection, and Tcl rendering.

  • Action Manager

    Factories for runtime transitions that can be placed in a process.

  • Analysis Manager

    Static, transient, and variable-transient analysis definitions.

  • Process Component Sources

    Pattern, recorder, action, constraint, and analysis component implementations.

The Concepts Path Is Complete

You can now read a Femora model as one continuous workflow:

organize definitions
    -> create mesh parts and interfaces
    -> assemble and partition the domain
    -> inspect tags, regions, and groups
    -> define constraints and physical behavior
    -> define loading, recording, actions, and analyses
    -> order the executable process
    -> export and run

The Concepts section explains how these pieces fit together. Continue with the Tutorial Gallery to build complete models, browse the Example Gallery for focused modeling patterns, and use the API Reference when you need exact signatures and implementation-level detail.