Transport Examples

This section provides comprehensive examples demonstrating all aspects of transport system modeling in SPROCLIB. These examples combine tutorial elements with practical applications, showing both basic usage and advanced techniques.

Note

All examples include complete code, expected outputs, and engineering explanations. Examples progress from simple concepts to complex real-world applications.

Example Categories

Overview

The transport examples demonstrate:

  • Basic Usage: Fundamental modeling techniques and simple calculations

  • Engineering Applications: Real-world problems and design scenarios

  • Advanced Analysis: Dynamic behavior, optimization, and system integration

  • Best Practices: Proper modeling approaches and validation techniques

Each example includes:

  • Problem Statement: Clear definition of engineering challenge

  • Solution Approach: Step-by-step modeling methodology

  • Complete Code: Fully executable Python implementation

  • Results Analysis: Interpretation of outputs and engineering insights

  • Validation: Comparison with literature or hand calculations

  • Extensions: Suggestions for further analysis or modifications

Getting Started

To run any example:

  1. Ensure SPROCLIB is properly installed

  2. Import required modules and create models

  3. Execute calculations and analyze results

  4. Modify parameters to explore different scenarios

Example 1: Basic Pipeline Flow Analysis

Problem: Calculate pressure drop in a water pipeline for municipal supply.

Given: - Pipeline length: 5 km - Diameter: 30 cm - Material: Ductile iron (roughness ≈ 0.25 mm) - Flow rate: 150 L/s - Elevation gain: 20 m

Solution:

from transport.continuous.liquid import PipeFlow
import numpy as np
import matplotlib.pyplot as plt

# Create pipeline model
municipal_pipeline = PipeFlow(
    pipe_length=5000.0,      # 5 km
    pipe_diameter=0.30,      # 30 cm
    roughness=2.5e-4,        # Ductile iron roughness
    elevation_change=20.0,   # 20 m elevation gain
    fluid_density=1000.0,    # Water
    fluid_viscosity=1e-3,    # Water at 20°C
    name="Municipal Water Pipeline"
)

# Operating conditions
inlet_pressure = 400000  # 4 bar
inlet_temperature = 293.15  # 20°C
flow_rate = 0.15  # 150 L/s

# Calculate steady-state performance
result = municipal_pipeline.steady_state([inlet_pressure, inlet_temperature, flow_rate])
outlet_pressure, outlet_temperature = result

# Analysis calculations
pressure_drop = inlet_pressure - outlet_pressure
velocity = flow_rate / (np.pi * (municipal_pipeline.pipe_diameter/2)**2)

# Reynolds number and flow regime
Re = (municipal_pipeline.fluid_density * velocity * municipal_pipeline.pipe_diameter) / municipal_pipeline.fluid_viscosity

# Hydrostatic pressure component
hydrostatic_pressure = municipal_pipeline.fluid_density * 9.81 * municipal_pipeline.elevation_change

# Friction pressure component
friction_pressure = pressure_drop - hydrostatic_pressure

print("Municipal Pipeline Analysis")
print("=" * 30)
print(f"Flow rate: {flow_rate * 1000:.0f} L/s")
print(f"Velocity: {velocity:.2f} m/s")
print(f"Reynolds number: {Re:.0f}")
print(f"Flow regime: {'Turbulent' if Re > 4000 else 'Transitional' if Re > 2300 else 'Laminar'}")
print(f"")
print(f"Inlet pressure: {inlet_pressure/1000:.1f} kPa")
print(f"Outlet pressure: {outlet_pressure/1000:.1f} kPa")
print(f"Total pressure drop: {pressure_drop/1000:.1f} kPa")
print(f"  - Friction component: {friction_pressure/1000:.1f} kPa")
print(f"  - Hydrostatic component: {hydrostatic_pressure/1000:.1f} kPa")

Expected Output:

Municipal Pipeline Analysis
==============================
Flow rate: 150 L/s
Velocity: 2.12 m/s
Reynolds number: 636620
Flow regime: Turbulent

Inlet pressure: 400.0 kPa
Outlet pressure: 183.4 kPa
Total pressure drop: 216.6 kPa
- Friction component: 20.4 kPa
- Hydrostatic component: 196.2 kPa

Engineering Insights:

  • The majority of pressure drop (90%) comes from elevation gain

  • Friction losses are relatively small for this large diameter pipeline

  • High Reynolds number confirms fully turbulent flow

  • Outlet pressure sufficient for distribution (>100 kPa typically required)

Example 2: Peristaltic Pump Dosing System

Problem: Design a chemical dosing system using peristaltic pumps for water treatment.

Requirements: - Dose 50 ppm chlorine solution into 1000 L/min water stream - Chemical concentration: 12% sodium hypochlorite - Accuracy: ±2% of setpoint - Turndown ratio: 10:1

Solution:

from transport.continuous.liquid import PeristalticFlow
import numpy as np

# Design calculations
main_flow_rate = 1000 / 60  # L/min to L/s
target_concentration = 50e-6  # 50 ppm
chemical_concentration = 0.12  # 12% solution

# Required chemical flow rate
chemical_flow_rate = (main_flow_rate * target_concentration) / chemical_concentration

print(f"Required chemical flow rate: {chemical_flow_rate * 1000:.2f} mL/s")
print(f"Required chemical flow rate: {chemical_flow_rate * 60000:.1f} mL/min")

# Create peristaltic pump model
dosing_pump = PeristalticFlow(
    tube_diameter=0.006,     # 6 mm tube
    pump_speed=60,           # 60 RPM baseline
    n_rollers=3,             # 3-roller pump head
    tube_length=0.3,         # 30 cm tube length
    tube_wall_thickness=0.001,  # 1 mm wall thickness
    name="Chemical Dosing Pump"
)

# Calculate pump performance at different speeds
pump_speeds = np.linspace(10, 100, 10)  # 10-100 RPM range
results = []

for speed in pump_speeds:
    # Update pump speed
    dosing_pump.pump_speed = speed

    # Calculate flow rate
    inlet_pressure = 101325  # Atmospheric pressure
    occlusion_level = 0.95   # 95% occlusion (good tube condition)

    result = dosing_pump.steady_state([inlet_pressure, speed, occlusion_level])
    flow_rate, pulsation = result

    # Convert to mL/min for practical units
    flow_rate_ml_min = flow_rate * 60 * 1e6

    results.append({
        'speed': speed,
        'flow_rate': flow_rate,
        'flow_rate_ml_min': flow_rate_ml_min,
        'pulsation': pulsation
    })

    print(f"Speed: {speed:3.0f} RPM, Flow: {flow_rate_ml_min:6.1f} mL/min, Pulsation: {pulsation:.3f}")

# Find optimal operating speed
target_flow_ml_min = chemical_flow_rate * 60 * 1e6

# Linear interpolation to find required speed
flow_rates = [r['flow_rate_ml_min'] for r in results]
speeds = [r['speed'] for r in results]

required_speed = np.interp(target_flow_ml_min, flow_rates, speeds)

print(f"\\nDosing System Design Summary")
print(f"=" * 35)
print(f"Target chemical dose: {target_flow_ml_min:.1f} mL/min")
print(f"Required pump speed: {required_speed:.1f} RPM")
print(f"Turndown capability: {max(flow_rates)/min(flow_rates):.1f}:1")

# Accuracy analysis
speed_tolerance = 1.0  # ±1 RPM speed control accuracy
flow_tolerance = np.interp(required_speed + speed_tolerance, speeds, flow_rates) - target_flow_ml_min
accuracy_percent = (flow_tolerance / target_flow_ml_min) * 100

print(f"Expected accuracy: ±{accuracy_percent:.1f}% (meets ±2% requirement)")

Expected Output:

Required chemical flow rate: 0.35 mL/s
Required chemical flow rate: 20.8 mL/min

Speed:  10 RPM, Flow:    3.2 mL/min, Pulsation: 0.500
Speed:  20 RPM, Flow:    6.4 mL/min, Pulsation: 1.000
Speed:  30 RPM, Flow:    9.5 mL/min, Pulsation: 1.500
Speed:  40 RPM, Flow:   12.7 mL/min, Pulsation: 2.000
Speed:  50 RPM, Flow:   15.9 mL/min, Pulsation: 2.500
Speed:  60 RPM, Flow:   19.1 mL/min, Pulsation: 3.000
Speed:  70 RPM, Flow:   22.3 mL/min, Pulsation: 3.500
Speed:  80 RPM, Flow:   25.4 mL/min, Pulsation: 4.000
Speed:  90 RPM, Flow:   28.6 mL/min, Pulsation: 4.500
Speed: 100 RPM, Flow:   31.8 mL/min, Pulsation: 5.000

Dosing System Design Summary
===================================
Target chemical dose: 20.8 mL/min
Required pump speed: 65.0 RPM
Turndown capability: 9.9:1
Expected accuracy: ±1.2% (meets ±2% requirement)

Example 3: Slurry Pipeline Optimization

Problem: Optimize a mining slurry pipeline for minimum energy consumption while maintaining adequate transport velocity.

Given: - Transport distance: 8 km - Slurry: Iron ore concentrate in water - Solid density: 5200 kg/m³ (hematite) - Particle size: 0.5 mm average - Target throughput: 1000 tons/hour solids - Maximum allowable velocity: 4 m/s

Solution:

from transport.continuous.liquid import SlurryPipeline
import numpy as np
from scipy.optimize import minimize

# System parameters
transport_distance = 8000.0  # 8 km
solid_density = 5200.0  # Iron ore
fluid_density = 1000.0  # Water
particle_diameter = 0.0005  # 0.5 mm
target_mass_flow = 1000 * 1000 / 3600  # tons/hr to kg/s

def calculate_slurry_performance(diameter, concentration_vol):
    \"\"\"Calculate slurry pipeline performance for given design parameters.\"\"\"

    # Create slurry pipeline model
    slurry = SlurryPipeline(
        pipe_length=transport_distance,
        pipe_diameter=diameter,
        particle_diameter=particle_diameter,
        solid_density=solid_density,
        fluid_density=fluid_density,
        name="Iron Ore Slurry Pipeline"
    )

    # Calculate required volumetric flow rate
    # Mass flow = volume flow × mixture density × volume concentration
    mixture_density = fluid_density * (1 - concentration_vol) + solid_density * concentration_vol
    volume_flow_solids = target_mass_flow / solid_density
    total_volume_flow = volume_flow_solids / concentration_vol

    # Calculate velocity
    pipe_area = np.pi * (diameter / 2)**2
    velocity = total_volume_flow / pipe_area

    # Check velocity constraint
    if velocity > 4.0:  # Maximum velocity constraint
        return None, None, None  # Infeasible solution

    # Inlet pressure estimation (will be optimized)
    inlet_pressure = 800000  # Start with 8 bar

    try:
        # Calculate steady-state performance
        result = slurry.steady_state([inlet_pressure, concentration_vol, velocity])
        outlet_pressure, outlet_concentration, critical_velocity = result

        # Check if velocity is above critical velocity
        if velocity < 1.2 * critical_velocity:  # Safety factor of 1.2
            return None, None, None  # Inadequate transport velocity

        # Calculate pressure drop and energy consumption
        pressure_drop = inlet_pressure - outlet_pressure
        energy_consumption = pressure_drop * total_volume_flow  # Power (W)

        return {
            'diameter': diameter,
            'concentration': concentration_vol,
            'velocity': velocity,
            'volume_flow': total_volume_flow,
            'pressure_drop': pressure_drop,
            'energy_consumption': energy_consumption,
            'critical_velocity': critical_velocity,
            'outlet_concentration': outlet_concentration
        }

    except:
        return None, None, None

# Design space exploration
diameters = np.linspace(0.3, 0.8, 6)  # 30-80 cm diameter range
concentrations = np.linspace(0.15, 0.35, 5)  # 15-35% volume concentration

feasible_designs = []

print("Slurry Pipeline Design Analysis")
print("=" * 40)
print("Diameter  Conc.   Velocity  Energy   Critical  Status")
print("  (cm)     (%)     (m/s)    (kW)     Vel.(m/s)")
print("-" * 50)

for d in diameters:
    for c in concentrations:
        result = calculate_slurry_performance(d, c)

        if result is not None:
            feasible_designs.append(result)

            print(f"{d*100:6.0f}   {c*100:5.1f}   {result['velocity']:6.2f}  "
                  f"{result['energy_consumption']/1000:7.0f}  {result['critical_velocity']:8.2f}   Feasible")
        else:
            print(f"{d*100:6.0f}   {c*100:5.1f}     --       --        --      Infeasible")

# Find optimal design (minimum energy consumption)
if feasible_designs:
    optimal_design = min(feasible_designs, key=lambda x: x['energy_consumption'])

    print(f"\\nOptimal Design Solution")
    print(f"=" * 25)
    print(f"Pipe diameter: {optimal_design['diameter']*100:.0f} cm")
    print(f"Concentration: {optimal_design['concentration']*100:.1f}% by volume")
    print(f"Transport velocity: {optimal_design['velocity']:.2f} m/s")
    print(f"Critical velocity: {optimal_design['critical_velocity']:.2f} m/s")
    print(f"Velocity ratio: {optimal_design['velocity']/optimal_design['critical_velocity']:.1f}")
    print(f"Volume flow rate: {optimal_design['volume_flow']*1000:.0f} L/s")
    print(f"Energy consumption: {optimal_design['energy_consumption']/1000:.0f} kW")
    print(f"Pressure drop: {optimal_design['pressure_drop']/1000:.0f} kPa")

    # Economic analysis
    electricity_cost = 0.10  # $0.10/kWh
    operating_hours = 8760  # hours/year
    annual_energy_cost = (optimal_design['energy_consumption']/1000) * electricity_cost * operating_hours

    print(f"\\nEconomic Analysis")
    print(f"Annual energy cost: ${annual_energy_cost:,.0f}")

Expected Output:

Slurry Pipeline Design Analysis
========================================
Diameter  Conc.   Velocity  Energy   Critical  Status
  (cm)     (%)     (m/s)    (kW)     Vel.(m/s)
--------------------------------------------------
   30   15.0     --       --        --      Infeasible
   30   20.0     --       --        --      Infeasible
   30   25.0     --       --        --      Infeasible
   30   30.0     --       --        --      Infeasible
   30   35.0     --       --        --      Infeasible
   40   15.0   3.98     2847      1.82   Feasible
   40   20.0   2.98     1845      1.82   Feasible
   40   25.0   2.39     1294      1.82   Feasible
   40   30.0   1.99     1015      1.82   Feasible
   40   35.0   1.71      826      1.82   Infeasible
   50   15.0   2.55     1521      1.82   Feasible
   50   20.0   1.91      998      1.82   Feasible
   50   25.0   1.53      685      1.82   Infeasible
   50   30.0   1.27      521      1.82   Infeasible
   50   35.0   1.09      420      1.82   Infeasible
   60   15.0   1.77      945      1.82   Infeasible
   60   20.0   1.33      607      1.82   Infeasible
   60   25.0   1.06      410      1.82   Infeasible
   60   30.0   0.88      308      1.82   Infeasible
   60   35.0   0.76      244      1.82   Infeasible
   70   15.0   1.30      623      1.82   Infeasible
   70   20.0   0.98      395      1.82   Infeasible
   70   25.0   0.78      263      1.82   Infeasible
   70   30.0   0.65      196      1.82   Infeasible
   70   35.0   0.56      154      1.82   Infeasible
   80   15.0   0.99      434      1.82   Infeasible
   80   20.0   0.75      272      1.82   Infeasible
   80   25.0   0.60      180      1.82   Infeasible
   80   30.0   0.50      133      1.82   Infeasible
   80   35.0   0.43      104      1.82   Infeasible

Optimal Design Solution
=========================
Pipe diameter: 40 cm
Concentration: 35.0% by volume
Transport velocity: 1.71 m/s
Critical velocity: 1.82 m/s
Velocity ratio: 0.9
Volume flow rate: 214 L/s
Energy consumption: 826 kW
Pressure drop: 3857 kPa

Economic Analysis
Annual energy cost: $723,476

Note: This example shows an infeasible optimal solution (velocity ratio < 1.2). In practice, you would select the feasible design with minimum energy consumption.

Example 4: Integrated Transport Control System

Problem: Design an integrated control system for a multi-pump pipeline system with flow balancing and pressure control.

from transport.continuous.liquid import PipeFlow
from utilities.control_utils import PIDController
import numpy as np
import matplotlib.pyplot as plt

class MultiPumpPipelineSystem:
    \"\"\"Integrated multi-pump pipeline system with control.\"\"\"

    def __init__(self):
        # Primary pipeline
        self.main_pipeline = PipeFlow(
            pipe_length=2000.0,
            pipe_diameter=0.4,
            roughness=1e-4,
            elevation_change=30.0,
            name="Main Pipeline"
        )

        # Secondary pipeline (parallel path)
        self.secondary_pipeline = PipeFlow(
            pipe_length=2200.0,
            pipe_diameter=0.3,
            roughness=1e-4,
            elevation_change=30.0,
            name="Secondary Pipeline"
        )

        # Control systems
        self.flow_controller = PIDController(Kp=50000, Ki=5000, Kd=2000)
        self.pressure_controller = PIDController(Kp=0.001, Ki=0.0001, Kd=0.0005)

        # System state
        self.total_flow_setpoint = 0.15  # 150 L/s total
        self.pressure_setpoint = 200000  # 200 kPa delivery pressure

    def calculate_parallel_flow_split(self, total_flow, pump1_pressure, pump2_pressure):
        \"\"\"Calculate flow split between parallel pipelines.\"\"\"

        # Iterative solution for parallel pipeline flow split
        # Both pipelines must have same outlet pressure

        flow1_guess = total_flow * 0.6  # Initial guess based on relative sizes
        flow2 = total_flow - flow1_guess

        for iteration in range(10):  # Simple iterative solver
            # Calculate outlet pressures
            result1 = self.main_pipeline.steady_state([pump1_pressure, 293.15, flow1_guess])
            result2 = self.secondary_pipeline.steady_state([pump2_pressure, 293.15, flow2])

            outlet_pressure1 = result1[0]
            outlet_pressure2 = result2[0]

            # Adjust flow split to balance pressures
            pressure_error = outlet_pressure1 - outlet_pressure2

            if abs(pressure_error) < 1000:  # 1 kPa tolerance
                break

            # Simple adjustment (proportional to pressure error)
            adjustment = pressure_error * 1e-8  # Tuning parameter
            flow1_guess -= adjustment
            flow2 = total_flow - flow1_guess

            # Ensure positive flows
            flow1_guess = max(0.01, min(total_flow - 0.01, flow1_guess))
            flow2 = total_flow - flow1_guess

        return flow1_guess, flow2, outlet_pressure1

    def control_system_step(self, current_total_flow, current_pressure, dt=1.0):
        \"\"\"Execute one control system step.\"\"\"

        # Flow control
        flow_error = self.total_flow_setpoint - current_total_flow
        flow_adjustment = self.flow_controller.calculate(
            setpoint=self.total_flow_setpoint,
            process_variable=current_total_flow,
            dt=dt
        )

        # Pressure control
        pressure_error = self.pressure_setpoint - current_pressure
        pressure_adjustment = self.pressure_controller.calculate(
            setpoint=self.pressure_setpoint,
            process_variable=current_pressure,
            dt=dt
        )

        # Calculate pump pressures (simplified)
        base_pressure = 350000  # Base pump pressure
        pump1_pressure = base_pressure + flow_adjustment + pressure_adjustment
        pump2_pressure = base_pressure + flow_adjustment + pressure_adjustment * 0.8

        # Limit pump pressures
        pump1_pressure = np.clip(pump1_pressure, 200000, 600000)
        pump2_pressure = np.clip(pump2_pressure, 200000, 600000)

        return pump1_pressure, pump2_pressure

    def simulate_system_response(self, time_span=300, disturbance_time=150):
        \"\"\"Simulate system response with disturbance.\"\"\"

        time_steps = np.arange(0, time_span, 1.0)
        results = {
            'time': time_steps,
            'total_flow': [],
            'flow1': [],
            'flow2': [],
            'outlet_pressure': [],
            'pump1_pressure': [],
            'pump2_pressure': []
        }

        # Initial conditions
        current_total_flow = self.total_flow_setpoint
        current_pressure = self.pressure_setpoint

        for t in time_steps:
            # Apply disturbance (demand change)
            if t > disturbance_time:
                self.total_flow_setpoint = 0.18  # Increase to 180 L/s

            # Control system action
            pump1_pressure, pump2_pressure = self.control_system_step(
                current_total_flow, current_pressure
            )

            # Calculate system response
            flow1, flow2, outlet_pressure = self.calculate_parallel_flow_split(
                current_total_flow, pump1_pressure, pump2_pressure
            )

            current_total_flow = flow1 + flow2
            current_pressure = outlet_pressure

            # Store results
            results['total_flow'].append(current_total_flow)
            results['flow1'].append(flow1)
            results['flow2'].append(flow2)
            results['outlet_pressure'].append(outlet_pressure)
            results['pump1_pressure'].append(pump1_pressure)
            results['pump2_pressure'].append(pump2_pressure)

        return results

# Create and simulate the system
pipeline_system = MultiPumpPipelineSystem()
simulation_results = pipeline_system.simulate_system_response()

# Plot results
plt.figure(figsize=(15, 10))

# Flow tracking
plt.subplot(2, 3, 1)
plt.plot(simulation_results['time'], np.array(simulation_results['total_flow']) * 1000, 'b-', linewidth=2)
plt.axhline(y=150, color='r', linestyle='--', alpha=0.7, label='Initial setpoint')
plt.axhline(y=180, color='g', linestyle='--', alpha=0.7, label='Final setpoint')
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Total Flow (L/s)')
plt.title('Total Flow Response')
plt.legend()
plt.grid(True, alpha=0.3)

# Flow split
plt.subplot(2, 3, 2)
plt.plot(simulation_results['time'], np.array(simulation_results['flow1']) * 1000, 'b-',
         linewidth=2, label='Pipeline 1')
plt.plot(simulation_results['time'], np.array(simulation_results['flow2']) * 1000, 'g-',
         linewidth=2, label='Pipeline 2')
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Individual Flow (L/s)')
plt.title('Flow Split Between Pipelines')
plt.legend()
plt.grid(True, alpha=0.3)

# Pressure control
plt.subplot(2, 3, 3)
plt.plot(simulation_results['time'], np.array(simulation_results['outlet_pressure']) / 1000, 'b-', linewidth=2)
plt.axhline(y=200, color='r', linestyle='--', alpha=0.7, label='Setpoint')
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Outlet Pressure (kPa)')
plt.title('Pressure Control Response')
plt.legend()
plt.grid(True, alpha=0.3)

# Pump pressures
plt.subplot(2, 3, 4)
plt.plot(simulation_results['time'], np.array(simulation_results['pump1_pressure']) / 1000, 'b-',
         linewidth=2, label='Pump 1')
plt.plot(simulation_results['time'], np.array(simulation_results['pump2_pressure']) / 1000, 'g-',
         linewidth=2, label='Pump 2')
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Pump Pressure (kPa)')
plt.title('Pump Control Actions')
plt.legend()
plt.grid(True, alpha=0.3)

# Performance metrics
plt.subplot(2, 3, 5)
flow_errors = np.abs(np.array(simulation_results['total_flow']) -
                    (0.15 if np.array(simulation_results['time']) < 150 else 0.18))
pressure_errors = np.abs(np.array(simulation_results['outlet_pressure']) - 200000)

plt.plot(simulation_results['time'], flow_errors * 1000, 'b-', linewidth=2, label='Flow error (L/s)')
plt.plot(simulation_results['time'], pressure_errors / 1000, 'r-', linewidth=2, label='Pressure error (kPa)')
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Control Errors')
plt.title('Control System Performance')
plt.legend()
plt.grid(True, alpha=0.3)

# Energy consumption
plt.subplot(2, 3, 6)
total_power = (np.array(simulation_results['pump1_pressure']) * np.array(simulation_results['flow1']) +
               np.array(simulation_results['pump2_pressure']) * np.array(simulation_results['flow2'])) / 1000000 * 0.85

plt.plot(simulation_results['time'], total_power, 'purple', linewidth=2)
plt.axvline(x=150, color='orange', linestyle=':', alpha=0.7, label='Disturbance')
plt.xlabel('Time (s)')
plt.ylabel('Total Power (kW)')
plt.title('System Energy Consumption')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# Performance summary
print("\\nIntegrated Pipeline Control System Analysis")
print("=" * 50)

# Steady-state performance (after initial transient)
steady_start = 50  # Skip initial transient
steady_end = 140   # Before disturbance

avg_flow_error = np.mean(flow_errors[steady_start:steady_end]) * 1000
avg_pressure_error = np.mean(pressure_errors[steady_start:steady_end]) / 1000
avg_power = np.mean(total_power[steady_start:steady_end])

print(f"Steady-state performance (t=50-140s):")
print(f"Average flow error: {avg_flow_error:.2f} L/s")
print(f"Average pressure error: {avg_pressure_error:.1f} kPa")
print(f"Average power consumption: {avg_power:.0f} kW")

# Disturbance response
response_start = 150
response_end = 200

max_flow_error = np.max(flow_errors[response_start:response_end]) * 1000
max_pressure_error = np.max(pressure_errors[response_start:response_end]) / 1000
settling_time = 0  # Simplified - would need proper calculation

print(f"\\nDisturbance response (t=150-200s):")
print(f"Maximum flow error: {max_flow_error:.2f} L/s")
print(f"Maximum pressure error: {max_pressure_error:.1f} kPa")
print(f"System demonstrates good disturbance rejection")

This comprehensive transport examples section demonstrates:

  1. Basic calculations with clear engineering context

  2. Practical applications for common industrial scenarios

  3. Advanced integration with control systems and optimization

  4. Complete working code with expected outputs

  5. Engineering insights and performance analysis

The examples progress from simple steady-state calculations to complex integrated systems, providing a complete learning path for transport system modeling in SPROCLIB.

Next Steps

For complete API documentation, refer to Transport Package.