2. Knowledge graph fundamentals for CAE

CAE data is inherently relational. A mesh belongs to a part, a part is assigned a material, a material carries temperature-dependent properties, a load case references a boundary condition, and a solver run produces a result field that must be traceable back to the exact input deck. Traditional file-based storage captures these relationships only implicitly, through directory conventions and naming rules. A knowledge graph makes them explicit, typed, and queryable. This section establishes the core vocabulary — entities, relations, ontologies, triples, and graph query languages — and shows how each concept maps onto real CAE artifacts.

Entities: the nodes of a CAE graph

An entity is a uniquely identifiable object in the graph. In a CAE context, entities are the things engineers already name: a Part, a Material, a Mesh, a LoadCase, a SolverRun, a ResultField, a BoundaryCondition, or a GeometryFeature. Each entity has a stable identifier (an IRI or a UUID), a type, and a set of attributes. For example, a material entity might carry name, density, youngsModulus, and poissonRatio as literal attributes, while a solver run entity carries solverVersion, wallClockTime, and convergenceStatus.

The critical design decision is granularity. If a mesh is modeled as a single entity, you cannot ask which element set was used for a particular contact definition. If every element is an entity, the graph becomes unwieldy. A practical rule for CAE is to model entities at the level of engineering decisions: parts, materials, load cases, boundary conditions, solver runs, and result fields — not individual nodes or elements, unless mesh-level traceability is a genuine requirement.

Relations: typed, directed edges

A relation connects two entities and carries a direction and a type. Direction matters: Part --hasMaterial--> Material is not the same as Material --usedBy--> Part, even though they describe the same fact. In CAE graphs, common relation types include:

  • hasMaterial, hasMesh, hasLoadCase — composition relations from an assembly or part to its components.
  • assignedTo — a boundary condition assigned to a specific surface or node set.
  • derivedFrom — a result field derived from a solver run, or a solver run derived from an input deck.
  • references — a load case referencing a material or a coordinate system.
  • validatedBy — a simulation result validated against a physical test.

Relations can also carry attributes. A derivedFrom edge between a result field and a solver run might store timestamp and confidence. This is where graphs outperform relational tables: the relationship itself becomes a first-class object with its own metadata.

Ontologies: the schema that gives meaning

An ontology is the formal specification of the entity types, relation types, and constraints that govern a graph. It answers questions such as: Can a LoadCase exist without a BoundaryCondition? Is hasMaterial functional (at most one material per part) or multi-valued? What are the allowed units for youngsModulus?

For CAE, a lightweight ontology is usually sufficient. You do not need full OWL reasoning; a schema expressed in SHACL or even a documented set of RDF classes and properties is enough to enforce consistency. A minimal CAE ontology might define:

Class: Part
  - hasMaterial (exactly 1 Material)
  - hasMesh (exactly 1 Mesh)
  - hasLoadCase (0..n LoadCase)

Class: Material
  - density (exactly 1, unit: kg/m^3)
  - youngsModulus (exactly 1, unit: Pa)
  - poissonRatio (exactly 1, range: -1.0 to 0.5)

Class: SolverRun
  - derivedFrom (exactly 1 InputDeck)
  - produces (1..n ResultField)
  - convergenceStatus (exactly 1, enum: converged | diverged | incomplete)

The ontology is what prevents a graph from degenerating into a pile of loosely connected triples. It also enables validation: before a new solver run is ingested, the graph can reject it if it lacks a derivedFrom link or if the material's poissonRatio falls outside the physical range.

Triples: the atomic unit of knowledge

A triple is a statement of the form subject – predicate – object. Every graph is a set of triples. For example:

ex:BracketPart  ex:hasMaterial      ex:Al6061
ex:Al6061       ex:youngsModulus    6.9e10
ex:BracketPart  ex:hasLoadCase      ex:LoadCase_01
ex:LoadCase_01  ex:assignedTo       ex:FixedSupport
ex:SolverRun_42 ex:derivedFrom      ex:InputDeck_v3
ex:SolverRun_42 ex:convergenceStatus "converged"

Each triple is independently assertable and independently queryable. This atomicity is what makes graphs composable: you can merge two graphs from different teams without a schema migration, as long as they share the same ontology. It also makes provenance natural — every triple can be annotated with who asserted it and when.

Graph query languages: asking engineering questions

SPARQL is the standard query language for RDF graphs. Its power for CAE lies in pattern matching over paths. Consider a question an engineer might actually ask: "Which solver runs used Al6061 and converged, and what was the maximum von Mises stress in each?" In SPARQL:

SELECT ?run ?maxStress WHERE {
  ?part      ex:hasMaterial      ex:Al6061 .
  ?part      ex:hasLoadCase      ?lc .
  ?run       ex:derivedFrom      ?lc .
  ?run       ex:convergenceStatus "converged" .
  ?run       ex:produces         ?field .
  ?field     ex:maxVonMises      ?maxStress .
}

The query traverses four hops — part to material, part to load case, load case to run, run to result field — without any explicit join syntax. This is the practical advantage over SQL: the graph structure is the join path. For property graphs (Neo4j, Memgraph), Cypher expresses the same idea with ASCII-art patterns:

MATCH (p:Part)-[:hasMaterial]->(:Material {name:"Al6061"}),
      (p)-[:hasLoadCase]->(lc:LoadCase)<-[:derivedFrom]-(r:SolverRun),
      (r)-[:produces]->(f:ResultField)
WHERE r.convergenceStatus = "converged"
RETURN r.id, f.maxVonMises

Both languages support aggregation, filtering, and optional patterns. The choice between RDF/SPARQL and property-graph/Cypher is largely organizational: RDF excels when data comes from many sources with a shared ontology, while property graphs are often simpler for single-team, single-toolchain deployments.

Practical guidance: Start with a small ontology — 8 to 12 entity types and 10 to 15 relation types cover most CAE traceability needs. Ingest one project's data first, run the queries you actually need, and only then expand the schema. Premature ontology design is the most common failure mode in engineering knowledge graphs.

How the pieces fit together

The diagram below shows the relationship between the four concepts and how a typical CAE query traverses them. The ontology defines the allowed types; entities instantiate those types; triples connect entities; and the query language navigates the resulting graph.

Ontology (schema) Defines: Part, Material, LoadCase, SolverRun, ResultField Relations: hasMaterial, hasLoadCase, derivedFrom, produces, assignedTo Entities (instances) BracketPart Al6061 LoadCase_01 SolverRun_42 ResultField hasMaterial hasLoadCase derivedFrom produces Triples (assertions) ex:BracketPart ex:hasMaterial ex:Al6061 ex:SolverRun_42 ex:convergenceStatus "converged" Query (SPARQL / Cypher) SELECT ?run ?maxStress WHERE { ?part ex:hasMaterial ex:Al6061 . ... } → traverses entity graph via typed relations instantiates asserts queries

The layering is deliberate. The ontology constrains what can exist. Entities populate the graph. Triples record facts. Queries extract engineering answers. When a new solver version introduces a new result type, you extend the ontology, add entities, and assert triples — existing queries continue to work because they match on the relations they already know. This incremental extensibility is the core reason knowledge graphs fit CAE workflows, where toolchains, material databases, and simulation methods evolve continuously.

Common pitfall: Do not confuse the ontology with the data. A class definition for Material is not a material. If your graph contains only schema triples and no instance triples, queries will return empty results. Validate ingestion by counting instances per class after each load.