Skip to content

Commit 0428bb0

Browse files
TheNightFox-1claude
andcommitted
Add SolarX LCA analysis and SysML v2-to-openLCA integration PoC
Adds the LCA Analysis SolarX folder with a working SimpleLCAIntegration proof-of-concept: SysML v2 motor part (5 kg steel hot rolled coil) is semantically linked to ELCD flows via an OWL ontology bridge and SPARQL matching, then connected to openLCA via IPC for GWP calculation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 92baf08 commit 0428bb0

File tree

9 files changed

+655
-0
lines changed

9 files changed

+655
-0
lines changed

CLAUDE.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Documentation Site
6+
7+
The documentation is built with MkDocs Material and deployed automatically to GitHub Pages on every push to `main`.
8+
9+
Install dependencies:
10+
```bash
11+
pip install -r requirements.txt
12+
```
13+
14+
Serve locally with live reload:
15+
```bash
16+
mkdocs serve
17+
```
18+
19+
Build static site:
20+
```bash
21+
mkdocs build
22+
```
23+
24+
All documentation source files are in `docs/` as Markdown. The site navigation is configured in `mkdocs.yml`.
25+
26+
## Repository Architecture
27+
28+
This is a **knowledge repository and MBSE model workspace**, not a traditional software project. It contains:
29+
30+
- **`docs/`** — Documentation source (MkDocs). Editing these files updates the published site at [thenightfox-1.github.io/SustainableTogether](https://thenightfox-1.github.io/SustainableTogether/).
31+
- **`System Model/SolarX/`** — MBSE/SysML model of the SolarX PV system (current/AS-IS state). The system architecture is: `PVArray → SolarInverter → BatteryStorage` and `SolarInverter → GridConnection`, all orchestrated by `SystemController`.
32+
- **`System Model/SolarX/LCA Analysis SolarX/`** — Planned location for Life Cycle Assessment (LCA) integration with the SolarX model (currently empty, in active development).
33+
- **`Our Presentations/`** and **`SustainabilityWebinarSeries/`** — Static assets (PDFs, slides); not built or processed.
34+
35+
## Project Context
36+
37+
The project models a transformation from **SolarX** (conventional PV company, current state) to **SustainaSun** (sustainable future state). The MBSE models use SysML. Compatible tooling includes Cameo, Capella, and SysML v2 environments.
38+
39+
The near-term roadmap prioritises: completing the SolarX RFLP (Requirements, Functional, Logical, Physical) model layers; integrating LCA to automate environmental impact assessment; and beginning the SustainaSun model.
40+
41+
## Contribution Workflow
42+
43+
Commit message convention: `Add: ...`, `Fix: ...`, `Update: ...`
44+
45+
Issue templates in `.github/ISSUE_TEMPLATE/`: `bug_report.md`, `feature_request.md`, `content_contribution.md`.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Purpose
6+
7+
This folder contains the Life Cycle Assessment (LCA) of **SolarX** — the AS-IS state of a conventional photovoltaic solar energy system. The LCA establishes the environmental baseline that the SustainaSun transformation will be measured against.
8+
9+
## SolarX System Boundary
10+
11+
The LCA covers five components of the SolarX PV system:
12+
13+
| Component | Role in System |
14+
|---|---|
15+
| **PVArray** | Converts sunlight to DC electricity; dominant source of material impacts (silicon, silver, aluminium) |
16+
| **SolarInverter** | Converts DC to AC; contains copper, electronics |
17+
| **BatteryStorage** | Stores excess energy; lithium/lead chemistry, significant end-of-life impacts |
18+
| **SystemController** | Manages energy flow; PCB and embedded electronics |
19+
| **GridConnection** | Interface to public grid; cabling and switchgear |
20+
21+
22+
## LCA Methodology
23+
24+
Follow **ISO 14040 / ISO 14044** — four phases:
25+
26+
1. **Goal & Scope** — functional unit, system boundary, life cycle stages covered (cradle-to-grave)
27+
2. **Life Cycle Inventory (LCI)** — material and energy flows per component per life cycle stage
28+
3. **Life Cycle Impact Assessment (LCIA)** — translate inventory into impact categories
29+
4. **Interpretation** — identify hotspots, sensitivity analysis, conclusions
30+
31+
### Life Cycle Stages to Cover
32+
33+
- Raw material extraction & processing
34+
- Component manufacturing
35+
- Transport & logistics
36+
- Installation & commissioning
37+
- Operation & maintenance (25-year assumed lifetime)
38+
- End-of-life (disposal, recycling, landfill)
39+
40+
### Recommended Impact Categories (minimum)
41+
42+
- Global Warming Potential (GWP) — kg CO₂-eq
43+
- Energy Payback Time (EPBT) — years
44+
- Cumulative Energy Demand (CED) — MJ
45+
- Acidification Potential (AP)
46+
- Human Toxicity Potential (HTP)
47+
48+
## Tooling & Data Sources
49+
50+
**Open-source LCA tools:**
51+
- [Brightway2](https://brightway.dev/) — Python-based; preferred for scripted/automated analysis and SysML integration
52+
- [OpenLCA](https://www.openlca.org/) — GUI-based; good for initial exploration
53+
54+
**Background inventory databases:**
55+
- [ecoinvent](https://ecoinvent.org/) — industry standard (requires licence)
56+
- [GLAD / openLCA Nexus](https://nexus.openlca.org/) — free datasets
57+
58+
**Python packages for Brightway2 workflows:**
59+
```
60+
brightway2
61+
bw2data
62+
bw2calc
63+
bw2io
64+
pandas
65+
matplotlib
66+
```
67+
68+
## Folder Structure (Intended)
69+
70+
```
71+
LCA Analysis SolarX/
72+
├── CLAUDE.md # This file
73+
├── README.md # Overview
74+
├── data/ # Raw inventory data (CSV, JSON) per component
75+
├── notebooks/ # Jupyter notebooks for analysis and visualisation
76+
├── results/ # LCIA result tables and charts
77+
└── reports/ # Written LCA report (Markdown or PDF)
78+
```
79+
80+
## Integration with MBSE Model
81+
82+
The roadmap calls for automating LCA from the SysML model. When adding inventory data, structure it so it can be mapped to SysML block properties — one data file or dataset per SolarX component, keyed by component name (`PVArray`, `SolarInverter`, `BatteryStorage`, `SystemController`, `GridConnection`).
83+
84+
## Key References
85+
86+
- ISO 14040:2006 — LCA Principles and Framework
87+
- ISO 14044:2006 — LCA Requirements and Guidelines
88+
- IEA PVPS Task 12 — LCA of PV systems (authoritative PV-specific guidance)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
This file contains focuses on the LCa analysis of SolarX, which represents the current state regarding its sustainability.
2+
3+
This is the structure of the PV system:
4+
- PVArray
5+
- SolarInverter
6+
- BatteryStorage
7+
- SystemController
8+
- GridConnection
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Purpose
6+
7+
This folder is a **proof-of-concept SysML v2 ↔ LCA integration pipeline**. It demonstrates how a SysML v2 part definition can be semantically linked to an LCA flow database (ELCD/ecoinvent) without hardcoding UUIDs, using RDF/OWL ontology bridging and SPARQL matching.
8+
9+
The motor example here is a stepping stone toward automating LCA from the full SolarX SysML model (PVArray, SolarInverter, BatteryStorage, SystemController, GridConnection).
10+
11+
## Pipeline Architecture
12+
13+
The integration has four layers, each represented by a file:
14+
15+
```
16+
motor.sysml ← SysML v2 model (source of truth)
17+
↓ (manual / future: automated serialization)
18+
motor_instance.ttl ← SysML part as RDF individuals
19+
↓ (loaded together into a triplestore)
20+
motor_lca_ontology.ttl ← OWL bridge: SysML concepts ↔ LCA concepts
21+
↓ (queried via)
22+
semantic_matching.sparql ← SPARQL: match material names to ELCD flows
23+
```
24+
25+
The SPARQL query requires a fourth graph at runtime: `elcd_flows.ttl` — ELCD flows loaded as RDF. This is **not yet generated**; it is the responsibility of `stage4_integration.py` (not yet written).
26+
27+
## Key Design Decisions
28+
29+
- **No hardcoded UUIDs.** Matching is done at runtime by string containment on flow names (`CONTAINS(LCASE(?matchedFlowName), LCASE(?materialName))`), so the query is database-agnostic.
30+
- **Ontology bridge rules** in `motor_lca_ontology.ttl` declare: `sysml:PartDefinition owl:equivalentClass lca:Process` and `sysml:materialName owl:equivalentProperty lca:flowName`. These are the semantic anchors for reasoning.
31+
- **Namespaces to preserve:**
32+
- `sysml: <http://sysmlv2.org/ontology#>`
33+
- `lca: <http://lca.org/ontology#>`
34+
- `ex: <http://sysmlv2club.org/example#>`
35+
36+
## What Still Needs to Be Built
37+
38+
1. **`stage4_integration.py`** — Python script (rdflib) that:
39+
- Loads `motor_lca_ontology.ttl`, `motor_instance.ttl`, and `elcd_flows.ttl` into a conjunctive graph
40+
- Executes `semantic_matching.sparql`
41+
- Outputs matched flow name, category, and ELCD UUID
42+
43+
2. **`elcd_flows.ttl`** — ELCD/ecoinvent flows serialized as RDF using the `lca:` ontology classes (`lca:Flow` with `lca:flowName`, `lca:flowCategory`, `lca:elcdUUID`)
44+
45+
3. **Automated SysML → RDF serialization** — currently `motor_instance.ttl` is written by hand; future work should parse `.sysml` files and generate instance TTL automatically
46+
47+
## Scaling to SolarX
48+
49+
To extend this pattern to the full SolarX system, create one `<component>_instance.ttl` per SolarX component, reusing the same ontology and SPARQL query. Component names to use: `PVArray`, `SolarInverter`, `BatteryStorage`, `SystemController`, `GridConnection`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package MotorExample {
2+
3+
public import ScalarValues::Real;
4+
public import ScalarValues::String;
5+
6+
attribute def MaterialRef {
7+
attribute name : String;
8+
attribute database : String;
9+
attribute uuid : String; // unique ID in the LCA database
10+
}
11+
12+
part def Motor {
13+
attribute mass : ScalarValues::Real = 5.0; // kg
14+
attribute material : MaterialRef {
15+
name = "steel hot rolled coil";
16+
database = "ELCD";
17+
uuid = ""; // resolved at runtime via SPARQL semantic match
18+
}
19+
}
20+
21+
part motor : Motor;
22+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
2+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5+
@prefix sysml: <http://sysmlv2.org/ontology#> .
6+
@prefix ex: <http://sysmlv2club.org/example#> .
7+
8+
# ─────────────────────────────────────────
9+
# Motor instance — SysML v2 model as RDF
10+
# Source: Motor part with 5 kg steel attribute
11+
# ─────────────────────────────────────────
12+
13+
# The Motor part definition
14+
ex:Motor a sysml:PartDefinition ;
15+
rdfs:label "Motor" ;
16+
rdfs:comment "Simple motor part from SysML v2 model" ;
17+
sysml:hasAttribute ex:MotorMaterialAttr ;
18+
sysml:hasAttribute ex:MotorMassAttr .
19+
20+
# Its material attribute — what the part is made of
21+
ex:MotorMaterialAttr a sysml:MaterialAttribute ;
22+
rdfs:label "Motor material" ;
23+
sysml:materialName "steel hot rolled coil" .
24+
25+
# Its mass attribute — how much of the material
26+
ex:MotorMassAttr a sysml:MassAttribute ;
27+
rdfs:label "Motor mass" ;
28+
sysml:massValue "5.0"^^xsd:decimal .
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
2+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5+
@prefix sysml: <http://sysmlv2.org/ontology#> .
6+
@prefix lca: <http://lca.org/ontology#> .
7+
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
8+
9+
# ─────────────────────────────────────────
10+
# SYSML V2 SIDE
11+
# ─────────────────────────────────────────
12+
13+
sysml:PartDefinition a owl:Class ;
14+
rdfs:label "Part Definition" ;
15+
rdfs:comment "A type of physical component in SysML v2" .
16+
17+
sysml:Attribute a owl:Class ;
18+
rdfs:label "Attribute" ;
19+
rdfs:comment "A named property of a part" .
20+
21+
sysml:MaterialAttribute a owl:Class ;
22+
rdfs:subClassOf sysml:Attribute ;
23+
rdfs:label "Material Attribute" ;
24+
rdfs:comment "An attribute that references a physical material" .
25+
26+
sysml:MassAttribute a owl:Class ;
27+
rdfs:subClassOf sysml:Attribute ;
28+
rdfs:label "Mass Attribute" ;
29+
rdfs:comment "An attribute representing the mass of a material" .
30+
31+
# Properties
32+
sysml:hasAttribute a owl:ObjectProperty ;
33+
rdfs:domain sysml:PartDefinition ;
34+
rdfs:range sysml:Attribute .
35+
36+
sysml:materialName a owl:DatatypeProperty ;
37+
rdfs:domain sysml:MaterialAttribute ;
38+
rdfs:range xsd:string ;
39+
rdfs:label "material name" .
40+
41+
sysml:massValue a owl:DatatypeProperty ;
42+
rdfs:domain sysml:MassAttribute ;
43+
rdfs:range xsd:decimal ;
44+
rdfs:label "mass value in kg" .
45+
46+
# ─────────────────────────────────────────
47+
# LCA / ELCD SIDE
48+
# ─────────────────────────────────────────
49+
50+
lca:Process a owl:Class ;
51+
rdfs:label "LCA Process" ;
52+
rdfs:comment "A unit process that consumes and produces flows" .
53+
54+
lca:Flow a owl:Class ;
55+
rdfs:label "Material Flow" ;
56+
rdfs:comment "A material, product or waste flow in ELCD" .
57+
58+
lca:Exchange a owl:Class ;
59+
rdfs:label "Exchange" ;
60+
rdfs:comment "A flow entering or leaving a process with a quantity" .
61+
62+
# Properties
63+
lca:hasExchange a owl:ObjectProperty ;
64+
rdfs:domain lca:Process ;
65+
rdfs:range lca:Exchange .
66+
67+
lca:exchangeFlow a owl:ObjectProperty ;
68+
rdfs:domain lca:Exchange ;
69+
rdfs:range lca:Flow .
70+
71+
lca:quantity a owl:DatatypeProperty ;
72+
rdfs:domain lca:Exchange ;
73+
rdfs:range xsd:decimal .
74+
75+
lca:flowName a owl:DatatypeProperty ;
76+
rdfs:domain lca:Flow ;
77+
rdfs:range xsd:string .
78+
79+
lca:flowCategory a owl:DatatypeProperty ;
80+
rdfs:domain lca:Flow ;
81+
rdfs:range xsd:string ;
82+
rdfs:comment "ELCD category path, e.g. Materials / Metals" .
83+
84+
lca:elcdUUID a owl:DatatypeProperty ;
85+
rdfs:domain lca:Flow ;
86+
rdfs:range xsd:string ;
87+
rdfs:comment "Resolved UUID in ELCD — populated after semantic matching" .
88+
89+
# ─────────────────────────────────────────
90+
# THE BRIDGE — Semantic Mapping Rules
91+
# ─────────────────────────────────────────
92+
93+
# Rule 1: A PartDefinition IS semantically equivalent to an LCA Process
94+
sysml:PartDefinition owl:equivalentClass lca:Process .
95+
96+
# Rule 2: A MaterialAttribute + MassAttribute together ARE an Exchange
97+
sysml:MaterialAttribute rdfs:seeAlso lca:Exchange ;
98+
skos:mappingRelation lca:Exchange .
99+
100+
# Rule 3: materialName maps to flowName (for SPARQL matching)
101+
sysml:materialName owl:equivalentProperty lca:flowName .
102+
103+
# Rule 4: massValue maps to quantity
104+
sysml:massValue owl:equivalentProperty lca:quantity .

0 commit comments

Comments
 (0)