Automated aggregation of simulation results for design validation workflows

I want to share our implementation of automated simulation result aggregation that significantly improved our design validation workflow speed in ENOVIA R2021x. Previously, our engineers manually collected simulation results from multiple analysis tools (FEA, CFD, thermal) and compiled them into validation reports - this took 2-3 hours per design iteration. We automated the entire process using Python scripts that parse simulation output files, normalize the data into consistent JSON format, and push aggregated results directly into ENOVIA through the REST API. The automation triggers automatically when simulation jobs complete, aggregating stress analysis, flow data, and temperature profiles into a single validation record. We then use ENOVIA notifications to alert the design team when results are ready for review. This reduced our validation cycle time from hours to minutes and eliminated manual data entry errors. The script handles multiple simulation tool formats and includes error handling for incomplete or failed analyses. I’ll share the architecture and key implementation details.

The notification integration is interesting - are you using ENOVIA’s built-in notification framework or something custom? We’ve struggled with reliable notifications for automated workflows. Also curious about error handling - what happens if the REST API call fails midway through pushing aggregated data?

How did you handle the ENOVIA integration piece? Did you create custom business objects for simulation results or use existing document/part structures? And what about versioning - if a design changes and simulations rerun, how do you track the history of validation results?

Let me break down the complete implementation architecture that took us from 2-3 hour manual validation cycles to automated processing in minutes.

Automated Result Parsing: We built a plugin-based parser framework in Python that handles multiple simulation tool formats. Each tool has a dedicated parser class:

class ANSYSParser(SimulationParser):
    def parse(self, result_file):
        # Extract stress, displacement data
        return {"maxStress": value, "safetyFactor": calc}

class COMSOLParser(SimulationParser):
    def parse(self, result_file):
        # Extract thermal, flow data
        return {"maxTemp": value, "flowRate": calc}

Each parser extracts tool-specific data and maps it to our standard schema. The framework automatically discovers and loads parsers at runtime, so adding support for new simulation tools just requires dropping in a new parser module - no changes to the core aggregation logic. We handle parsing errors gracefully by logging failures and continuing with other analyses, marking the aggregated result as partial.

JSON Normalization: All parsed simulation data gets normalized into a consistent JSON structure regardless of source tool:

{
  "designId": "PART-12345",
  "validationTimestamp": "2025-09-20T10:00:00Z",
  "analyses": [
    {"type": "structural", "tool": "ANSYS", "maxStress": 450.2, "safetyFactor": 1.8},
    {"type": "thermal", "tool": "COMSOL", "maxTemp": 85.3, "avgTemp": 62.1}
  ],
  "validationStatus": "PASS"
}

This schema includes metadata about each analysis (tool used, completion timestamp), the extracted results, and an overall validation status computed by comparing results against design requirements. The normalization layer is critical - it allows our ENOVIA integration and reporting to work uniformly regardless of which simulation tools were used.

ENOVIA Notification Integration: We leverage ENOVIA’s subscription framework to trigger notifications when validation results are ready. The aggregation script creates a ValidationResult business object through the REST API and sets a lifecycle state to “Ready for Review”. We configured ENOVIA subscriptions to watch for this state transition:

result_data = {
    "type": "ValidationResult",
    "attributes": {
        "title": f"Validation - {design_id}",
        "simulationData": json_normalized_results
    },
    "relationships": [{"type": "ValidatesDesign", "to": design_id}]
}
response = enovia_api.create_object(result_data)
enovia_api.promote_object(response['id'], "Ready for Review")

The promotion triggers ENOVIA’s notification system, which emails the design team with a direct link to the validation results. This eliminated the need for custom notification logic - we just leverage ENOVIA’s built-in capabilities.

For error handling, we implement retry logic with exponential backoff for API calls. If the REST API fails during object creation, the script retries up to 3 times before giving up and logging the failure. We also persist the aggregated JSON locally before attempting the API call, so we can manually recover and push results if the automation fails completely.

Regarding versioning, we create a new ValidationResult object for each simulation run and link it to the specific part version being validated. ENOVIA’s relationship management tracks the complete validation history automatically - engineers can view all previous validation results for a design through the part’s relationship tree.

The impact has been dramatic: validation cycle time dropped from 2-3 hours to 8-12 minutes (mostly simulation execution time, aggregation itself takes under 1 minute). More importantly, we eliminated manual transcription errors that previously caused 15-20% of validations to require rework due to incorrect data entry. The automation runs 24/7, so overnight simulation jobs are automatically processed and ready for review when engineers arrive in the morning. We’re now processing 40-50 design validations weekly versus 15-20 before automation.

We use file system watchers on the simulation output directories - when result files appear, it triggers the aggregation script. For partial failures, we aggregate whatever succeeded and flag the validation record as incomplete with details about which analyses failed. Design engineers can then decide whether to proceed with partial data or rerun failed simulations.

What triggers the automation? Do you poll for completed simulation jobs or is there an event-driven mechanism? And how do you handle scenarios where one simulation fails but others succeed - do you still aggregate partial results or wait for all to complete?

This sounds exactly like what we need. How do you handle different simulation tool output formats? We use ANSYS, COMSOL, and Star-CCM+, each with completely different result file structures. Is your parsing logic tool-specific or did you find a way to generalize it?

We use adapter pattern - each simulation tool has a dedicated parser module that extracts results into our standard JSON schema. The schema defines common fields like max stress, safety factor, temperature ranges regardless of source tool. New tools just need a new adapter implementing the same interface.