{
  "command": "measure history",
  "category": "measure",
  "search_keywords": [
    "history",
    "track",
    "monitor"
  ],
  "description": "Add a measurement history. A history is a floating point variable that can be sampled and stored during a model run, allowing tracking of measurement quantities over time. The history records values such as porosity, coordination number, stress, strain rate, position, or radius from a specified measurement object as the simulation progresses.",
  "syntax": "measure history <id id> <keyword> ...",
  "keywords": [
    {
      "name": "porosity",
      "syntax": "porosity id <i>",
      "description": "Track porosity (void fraction) inside the measurement object over time.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "coordination",
      "syntax": "coordination id <i>",
      "description": "Track coordination number (average number of contacts per body) inside the measurement object over time.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress",
      "syntax": "stress id <i> quantity <keyword>",
      "description": "Track measurement stress. Use the quantity keyword to specify which stress quantity to record (e.g., von-mises, mean, etc.).",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-xx",
      "syntax": "stress-xx id <i>",
      "description": "Track xx-component of the stress tensor inside the measurement object.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-yy",
      "syntax": "stress-yy id <i>",
      "description": "Track yy-component of the stress tensor inside the measurement object.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-zz",
      "syntax": "stress-zz id <i>",
      "description": "Track zz-component of the stress tensor inside the measurement object (3D only).",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-xy",
      "syntax": "stress-xy id <i>",
      "description": "Track xy-component of the stress tensor inside the measurement object.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-xz",
      "syntax": "stress-xz id <i>",
      "description": "Track xz-component of the stress tensor inside the measurement object (3D only).",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-yz",
      "syntax": "stress-yz id <i>",
      "description": "Track yz-component of the stress tensor inside the measurement object (3D only).",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "stress-yx",
      "syntax": "stress-yx id <i>",
      "description": "Track yx-component of the stress tensor inside the measurement object.",
      "required": false
    },
    {
      "name": "stress-zx",
      "syntax": "stress-zx id <i>",
      "description": "Track zx-component of the stress tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "stress-zy",
      "syntax": "stress-zy id <i>",
      "description": "Track zy-component of the stress tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "strainrate",
      "syntax": "strainrate id <i> quantity <keyword>",
      "description": "Track measurement strain rate. Use the quantity keyword to specify which strain rate quantity to record.",
      "required": false,
      "parameters": [
        {
          "name": "i",
          "type": "integer",
          "required": true,
          "description": "Measurement ID"
        }
      ]
    },
    {
      "name": "strainrate-xx",
      "syntax": "strainrate-xx id <i>",
      "description": "Track xx-component of the strain rate tensor inside the measurement object.",
      "required": false
    },
    {
      "name": "strainrate-yy",
      "syntax": "strainrate-yy id <i>",
      "description": "Track yy-component of the strain rate tensor inside the measurement object.",
      "required": false
    },
    {
      "name": "strainrate-zz",
      "syntax": "strainrate-zz id <i>",
      "description": "Track zz-component of the strain rate tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "strainrate-xy",
      "syntax": "strainrate-xy id <i>",
      "description": "Track xy-component of the strain rate tensor inside the measurement object.",
      "required": false
    },
    {
      "name": "strainrate-xz",
      "syntax": "strainrate-xz id <i>",
      "description": "Track xz-component of the strain rate tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "strainrate-yz",
      "syntax": "strainrate-yz id <i>",
      "description": "Track yz-component of the strain rate tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "strainrate-yx",
      "syntax": "strainrate-yx id <i>",
      "description": "Track yx-component of the strain rate tensor inside the measurement object.",
      "required": false
    },
    {
      "name": "strainrate-zx",
      "syntax": "strainrate-zx id <i>",
      "description": "Track zx-component of the strain rate tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "strainrate-zy",
      "syntax": "strainrate-zy id <i>",
      "description": "Track zy-component of the strain rate tensor inside the measurement object (3D only).",
      "required": false
    },
    {
      "name": "position-x",
      "syntax": "position-x id <i>",
      "description": "Track x-coordinate of the measurement object center over time.",
      "required": false
    },
    {
      "name": "position-y",
      "syntax": "position-y id <i>",
      "description": "Track y-coordinate of the measurement object center over time.",
      "required": false
    },
    {
      "name": "position-z",
      "syntax": "position-z id <i>",
      "description": "Track z-coordinate of the measurement object center over time (3D only).",
      "required": false
    },
    {
      "name": "radius",
      "syntax": "radius id <i>",
      "description": "Track radius of the measurement object over time.",
      "required": false
    }
  ],
  "notes": [
    "History records floating point values sampled during model run",
    "Allows tracking measurement quantities over time (e.g., porosity evolution)",
    "Optional history ID - if omitted, next available ID used automatically",
    "Measurement ID (second 'id') is REQUIRED to specify which measurement to track",
    "Multiple histories can track different quantities from same measurement",
    "Multiple histories can track same quantity from different measurements",
    "Histories are sampled automatically during model cycle/solve",
    "Use common history commands to manipulate histories (export, plot, etc.)",
    "Stress and strain rate have both component-specific keywords (stress-xx) and general keywords (stress)",
    "3D-only components: zz, xz, yz, zx, zy (not available in 2D models)",
    "History data can be exported, plotted, or queried with standard PFC history commands"
  ],
  "examples": [
    {
      "command": "measure history porosity id 1",
      "description": "Track porosity of measurement 1 over time (auto-assign history ID)",
      "use_case": "Monitor void fraction evolution during compaction"
    },
    {
      "command": "measure history id 10 coordination id 1",
      "description": "Create history with ID 10 to track coordination number of measurement 1",
      "use_case": "Explicit history ID for organization"
    },
    {
      "command": "measure history stress-zz id 1",
      "description": "Track vertical stress (zz-component) in measurement 1",
      "use_case": "Monitor vertical stress during loading"
    },
    {
      "command": "measure history strainrate-xx id 2",
      "description": "Track xx-component of strain rate in measurement 2",
      "use_case": "Monitor deformation rate during shearing"
    },
    {
      "command": "measure create id 1 radius 5.0\nmeasure history porosity id 1\nmeasure history coordination id 1\nmeasure history stress-zz id 1\nmodel cycle 10000",
      "description": "Create measurement, setup multiple histories, run simulation",
      "use_case": "Complete workflow to track porosity, coordination, and stress during simulation"
    },
    {
      "command": "measure history position-x id 1\nmeasure history position-y id 1",
      "description": "Track x and y coordinates of measurement center",
      "use_case": "Monitor if measurement region is moving (e.g., tracking a moving particle cluster)"
    },
    {
      "command": "measure history id 1 porosity id 1\nmeasure history id 2 porosity id 2\nmodel solve",
      "description": "Track porosity in two different measurement regions",
      "use_case": "Compare porosity evolution at different locations"
    }
  ],
  "python_sdk_alternative": {
    "available": true,
    "notes": [
      "Python SDK can access history data after recording",
      "History system is PFC-wide, not specific to measurements",
      "Command interface simplest for setting up measurement histories",
      "Python useful for programmatic history data processing"
    ],
    "command_vs_python": {
      "command": "measure history porosity id 1",
      "python": "# Python SDK can access history data\n# Consult PFC documentation for history access methods"
    }
  },
  "related_commands": [
    "measure create",
    "measure list",
    "model cycle",
    "model solve",
    "history export",
    "history list",
    "history delete"
  ],
  "common_use_cases": [
    {
      "use_case": "Track porosity evolution during compaction",
      "workflow": [
        "1. Create measurement: measure create id 1 radius 5.0",
        "2. Setup history: measure history porosity id 1",
        "3. Apply loading: apply gravity, boundary conditions",
        "4. Run simulation: model solve or model cycle 20000",
        "5. Porosity automatically recorded during cycling",
        "6. Export history: history export or analyze in PFC"
      ],
      "notes": "Monitor void space changes during densification"
    },
    {
      "use_case": "Monitor stress evolution in triaxial test",
      "workflow": [
        "1. Create measurement in specimen: measure create id 1 position (0,0,0) radius 3.0",
        "2. Track vertical stress: measure history stress-zz id 1",
        "3. Track horizontal stress: measure history stress-xx id 1",
        "4. Track shear stress: measure history stress-xz id 1",
        "5. Run triaxial loading: model cycle with boundary control",
        "6. Analyze stress paths from histories"
      ],
      "notes": "Complete stress state monitoring during loading"
    },
    {
      "use_case": "Compare properties at different locations",
      "workflow": [
        "1. Create region 1: measure create id 1 position (0,0,0) radius 2.0",
        "2. Create region 2: measure create id 2 position (10,0,0) radius 2.0",
        "3. Track porosity 1: measure history porosity id 1",
        "4. Track porosity 2: measure history porosity id 2",
        "5. Run simulation: model cycle",
        "6. Compare spatial variation in porosity evolution"
      ],
      "notes": "Spatial heterogeneity analysis"
    },
    {
      "use_case": "Track coordination number during fracture",
      "workflow": [
        "1. Setup measurement: measure create id 1 radius 4.0",
        "2. Track coordination: measure history coordination id 1",
        "3. Apply loading to cause fracture",
        "4. Run simulation: model cycle",
        "5. Coordination drops when bonds break and contacts lost",
        "6. Analyze drop in coordination to identify fracture onset"
      ],
      "notes": "Coordination number drops indicate material damage"
    }
  ],
  "typical_workflow": [
    "1. Create measurement region: measure create id <i> ...",
    "2. Setup history: measure history <quantity> id <i>",
    "3. Run simulation: model cycle or model solve",
    "4. History automatically sampled during cycling",
    "5. Export history: history export or analyze",
    "6. Plot or analyze time evolution"
  ],
  "history_id_management": {
    "auto_assignment": {
      "syntax": "measure history porosity id 1",
      "effect": "Next available history ID used automatically",
      "use_when": "Don't care about specific history ID"
    },
    "explicit_assignment": {
      "syntax": "measure history id 10 porosity id 1",
      "effect": "History created with ID 10",
      "use_when": "Need specific ID for organization or reference"
    },
    "recommendation": "Use auto-assignment unless specific IDs needed for scripting"
  },
  "measurement_vs_history_id": {
    "description": "Understanding two ID parameters",
    "first_id": {
      "parameter": "id (immediately after 'history')",
      "purpose": "History ID (optional)",
      "default": "Auto-assigned if omitted",
      "example": "measure history id 5 porosity id 1 (history ID = 5)"
    },
    "second_id": {
      "parameter": "id (after quantity keyword)",
      "purpose": "Measurement ID (required)",
      "default": "No default - must be specified",
      "example": "measure history porosity id 1 (measurement ID = 1)"
    },
    "confusion_warning": "Two 'id' keywords with different meanings - first for history, second for measurement"
  },
  "available_quantities": {
    "scalar_quantities": [
      {
        "name": "porosity",
        "description": "Void fraction (0 to 1)",
        "typical_range": "0.2 - 0.5 for granular materials"
      },
      {
        "name": "coordination",
        "description": "Average contacts per body",
        "typical_range": "2 - 6 for stable packings"
      },
      {
        "name": "radius",
        "description": "Measurement region radius",
        "typical_use": "Verify measurement size if programmatically modified"
      }
    ],
    "position_components": [
      {
        "name": "position-x, position-y, position-z",
        "description": "Measurement center coordinates",
        "typical_use": "Track moving measurement regions"
      }
    ],
    "stress_tensor": [
      {
        "name": "stress-xx, stress-yy, stress-zz",
        "description": "Normal stress components",
        "typical_use": "Principal stresses, vertical/horizontal stress"
      },
      {
        "name": "stress-xy, stress-xz, stress-yz (and yx, zx, zy)",
        "description": "Shear stress components",
        "typical_use": "Shear stress, deviatoric stress"
      }
    ],
    "strainrate_tensor": [
      {
        "name": "strainrate-xx, strainrate-yy, strainrate-zz",
        "description": "Normal strain rate components",
        "typical_use": "Volumetric strain rate, compaction/dilation rate"
      },
      {
        "name": "strainrate-xy, strainrate-xz, strainrate-yz (and yx, zx, zy)",
        "description": "Shear strain rate components",
        "typical_use": "Shear deformation rate"
      }
    ]
  },
  "tensor_components_2d_vs_3d": {
    "2d_available": [
      "xx",
      "yy",
      "xy",
      "yx"
    ],
    "3d_only": [
      "zz",
      "xz",
      "yz",
      "zx",
      "zy"
    ],
    "note": "3D-only components will cause errors in 2D models"
  },
  "history_sampling": {
    "description": "When and how histories are sampled",
    "sampling_timing": "Automatically during model cycle or model solve",
    "sampling_frequency": "Typically every cycle, but can be controlled with history settings",
    "triggering": "No manual triggering needed - happens during cycling",
    "data_storage": "Stored in memory, can be exported to file"
  },
  "multiple_histories_from_same_measurement": {
    "description": "Can track multiple quantities from same measurement",
    "example": [
      "measure create id 1 radius 5.0",
      "measure history porosity id 1",
      "measure history coordination id 1",
      "measure history stress-zz id 1",
      "measure history stress-xx id 1"
    ],
    "benefit": "Comprehensive monitoring of single region",
    "note": "Each quantity gets separate history ID"
  },
  "multiple_histories_from_different_measurements": {
    "description": "Can track same quantity from different measurements",
    "example": [
      "measure create id 1 position (0,0,0) radius 3.0",
      "measure create id 2 position (10,0,0) radius 3.0",
      "measure history porosity id 1",
      "measure history porosity id 2"
    ],
    "benefit": "Spatial comparison of same property",
    "note": "Each measurement gets separate history"
  },
  "warnings": [
    {
      "type": "measurement_must_exist",
      "message": "Measurement with specified ID must exist before creating history",
      "severity": "HIGH",
      "mitigation": "Use measure create before measure history"
    },
    {
      "type": "two_id_parameters",
      "message": "Two 'id' keywords with different meanings - first is history ID (optional), second is measurement ID (required)",
      "severity": "MEDIUM",
      "mitigation": "Understand syntax: 'measure history [id <hist_id>] <quantity> id <meas_id>'"
    },
    {
      "type": "3d_components_in_2d",
      "message": "3D-only components (zz, xz, yz, etc.) will cause errors in 2D models",
      "severity": "MEDIUM",
      "mitigation": "Only use xx, yy, xy, yx components in 2D models"
    },
    {
      "type": "history_data_memory",
      "message": "History data stored in memory - large simulations may use significant memory",
      "severity": "LOW",
      "mitigation": "Export and clear histories periodically for very long simulations"
    }
  ],
  "troubleshooting": [
    {
      "issue": "measure history fails or gives error",
      "solutions": [
        "Verify measurement exists: measure list",
        "Check measurement ID correct: use 'id <i>' after quantity",
        "Ensure using correct 2D/3D components",
        "Verify syntax: measure history <quantity> id <measurement_id>"
      ]
    },
    {
      "issue": "History not recording data",
      "solutions": [
        "Verify history was created: history list",
        "Check if model cycle/solve called after history creation",
        "Ensure measurement exists and contains bodies",
        "Call model clean to update measurement before cycling"
      ]
    },
    {
      "issue": "Cannot find history data",
      "solutions": [
        "Use history list to see all histories and their IDs",
        "Check history ID (auto-assigned or explicit)",
        "Use history export to export data to file",
        "Verify history was created before simulation started"
      ]
    },
    {
      "issue": "History shows unexpected values",
      "solutions": [
        "Verify correct measurement ID specified",
        "Check measurement position and radius: measure list",
        "Ensure measurement region contains bodies",
        "Call model clean before starting cycling",
        "Verify correct quantity being tracked"
      ]
    },
    {
      "issue": "3D component error in 2D model",
      "solutions": [
        "Cannot use zz, xz, yz, zx, zy in 2D",
        "Use only xx, yy, xy, yx in 2D models",
        "Switch to 3D model if 3D components needed"
      ]
    }
  ],
  "performance_considerations": {
    "history_overhead": "Minimal - sampling is fast",
    "memory_usage": "Proportional to number of samples × number of histories",
    "sampling_frequency": "Default every cycle - can be adjusted",
    "recommendation": "History tracking adds minimal overhead to simulation"
  },
  "history_commands_integration": {
    "description": "measure history integrates with PFC history system",
    "common_commands": [
      {
        "command": "history list",
        "description": "List all histories including measurement histories"
      },
      {
        "command": "history export <id> <filename>",
        "description": "Export history data to file"
      },
      {
        "command": "history delete <id>",
        "description": "Delete history"
      },
      {
        "command": "history interval <n>",
        "description": "Set sampling interval (every n cycles)"
      }
    ],
    "note": "Review PFC documentation for complete history command set"
  },
  "export_and_analysis": {
    "description": "Typical workflow for exporting and analyzing history data",
    "steps": [
      {
        "step": "1. Run simulation",
        "command": "model cycle 10000",
        "note": "Histories sampled automatically"
      },
      {
        "step": "2. List histories",
        "command": "history list",
        "note": "Find history IDs"
      },
      {
        "step": "3. Export history",
        "command": "history export 1 'porosity.txt'",
        "note": "Export to text file"
      },
      {
        "step": "4. Analyze",
        "note": "Import into Excel, Python, MATLAB, etc. for plotting"
      }
    ]
  },
  "when_to_use_measure_history": {
    "good_use_cases": [
      "Track porosity evolution during compaction",
      "Monitor stress development during loading",
      "Record coordination number changes during fracture",
      "Track strain rate during shearing",
      "Compare properties between different regions over time",
      "Detect fracture onset from sudden property changes"
    ],
    "not_needed_for": [
      "Single-point measurements (use measure list after model clean)",
      "Final state analysis only (use measure list)",
      "Global properties not specific to measurement regions"
    ]
  },
  "stress_strainrate_general_vs_components": {
    "description": "Difference between stress/strainrate and component keywords",
    "general_keywords": {
      "stress": "General stress keyword, requires 'quantity' sub-keyword",
      "strainrate": "General strain rate keyword, requires 'quantity' sub-keyword",
      "use": "For scalar quantities like von-mises, mean, etc.",
      "note": "Syntax and available quantities - consult PFC documentation"
    },
    "component_keywords": {
      "stress-xx, stress-yy, etc.": "Specific tensor components",
      "strainrate-xx, strainrate-yy, etc.": "Specific tensor components",
      "use": "Direct component tracking (most common)",
      "note": "More straightforward than general keywords"
    },
    "recommendation": "Use component keywords (stress-xx) for most cases - simpler and more direct"
  }
}
