Skip to main content
Glama
README.md
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="docs/img/numesys-logo-dark.png">
  <img src="docs/img/numesys-logo.png" alt="Numesys" height="40">
</picture>

# Discovery gRPC Toolkit

**[English](#english) · [Türkçe](#türkçe)**

Drive Ansys Discovery from outside: build parametric geometry, load it, solve it
and read the results — all over gRPC.

*Ansys Discovery'yi dışarıdan sürün: parametrik geometri çizin, yükleyin, çözün
ve sonuçları okuyun — hepsi gRPC üzerinden.*

```
browser ──HTTP :8765──► bridge.py ──┬── PyAnsys Geometry        (geometry)
                                    └── ansys.api.discovery.v0  (simulation)
                                             one gRPC channel :50055
                                                      │
                                                      ▼
                                            Ansys Discovery 2025 R2
```

> **Verified on** Discovery **2025 R2** (backend `25.2.0`),
> `ansys-geometry-core` 0.15.5, Python 3.12, Windows 11.
> 2024 R2 (v242) works for geometry; the simulation side was characterised on 25R2.

---

# English

Discovery's **ApiServer** add-in publishes a gRPC server inside an open Discovery
window. This repository gives you three ways to use it:

| Interface | For | What it does |
|---|---|---|
| **Web UI** (`webui/`) | Engineers | Type dimensions in a browser → “Send” → the part appears in the live Discovery window. Apply a load, solve, read the results. |
| **MCP server** (`discovery_mcp/`) | Claude Code, Cursor, Antigravity… | Modelling from natural language: “draw a 200×120×10 plate with Ø12 holes at the corners.” |
| **Python library** (`webui/shapes.py`, `webui/simulation.py`) | Developers | Call it directly from your own automation. |

## Setup

### 1. Prerequisite

Ansys Discovery must be installed **with the ApiServer add-in**:

```
%AWP_ROOT252%\Addins\ApiServer\Presentation.ApiServerAddIn.Manifest.xml
```

If that file is missing, the gRPC API was not installed for that release.

### 2. Clone and create a virtual environment

```bash
git clone https://github.com/numesys/discovery-grpc-toolkit.git
cd discovery-grpc-toolkit
python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
```

Python **3.10+** is required (developed on 3.12).

### 3. Start Discovery with the API enabled

```bash
scripts\attach-discovery.bat
```

It finds the newest installed release (252 → 251 → 242 → 241) from the
`AWP_ROOT2xx` environment variables; pass a version to pin one, e.g.
`attach-discovery.bat 252`. Wait for the window and **leave it open** — drawings
go into it.

> **Important:** a Discovery you open by hand has the gRPC API **disabled** and
> cannot be attached to. The API only comes up in a window launched with the
> add-in manifest, which is exactly what `attach-discovery.bat` does.

### 4. Start the web UI

```bash
scripts\start-webui.bat
```

The browser opens at `http://localhost:8765/`. Press **Connect**, pick a design,
enter dimensions, press **Send to Discovery**.

### Language

The interface ships in **English and Turkish**, defaulting to English. The
**EN / TR** switch at the top right changes it instantly and the choice is
remembered in the browser.

All text lives in the `I18N` dictionary in `webui/index.html`. The Python layer
(`bridge.py`, `shapes.py`, `simulation.py`) speaks English only and returns its
errors with **stable codes** (`not_connected`, `timeout`, `export_failed`, …),
which the page renders in the reader's language and falls back to the English
text for anything it has no translation for. Adding a third language means
adding one block to `I18N`.

Solver result names (`Max. Displacement`, `Factor of Safety`, …) are deliberately
**not** translated: those are Discovery's own output column names, and keeping
them makes the numbers easy to compare against the application window.

## Two ports, two separate links

This is the one genuinely confusing part of the setup, which is why the UI shows
both:

| Port | Link | When it causes trouble |
|---|---|---|
| **8765** (HTTP) | browser → `bridge.py` | Almost never. If the bridge is not running the page simply does not load. |
| **50055** (gRPC) | `bridge.py` → Discovery | Usually here. If Discovery is closed, or was opened without the API add-in, the connection is refused. |

A “cannot connect” error **almost always means the second one**. The *Port state*
row in the UI shows live whether `50055` is listening.

For the MCP server: the agent ↔ server link is **stdio** and has no port at all.
`50055` is only the server ↔ Discovery link.

## Designs in the web UI

Everything is in **millimetres**, with **Z up**. Each part reports its analytic
volume, and the UI compares that with the volume Discovery actually reports — so
a boolean that failed silently does not slip past.

| Design | Parameters |
|---|---|
| **Beam** | Solid rectangle / I-section / box section / solid round; length, height, width, web and flange thickness |
| **Pipe** | Outside diameter, wall thickness, length, optional end flanges |
| **Flange** | Outside diameter, bore, thickness, bolt circle, bolt diameter/count, hub |
| **Coupling** | Two half hubs, shaft bore, flange and hub dimensions, bolt circle, keyway |
| **Plate** | Width, depth, thickness, corner holes |
| **L-Bracket** | Leg lengths, thickness, width, mounting holes |
| **Shaft** | Three steps of diameter/length, keyway |
| **Bolt** | Hex head (across flats, height), shank diameter/length, washer |
| **Vessel** | Outside diameter, wall, length, cap thickness, radial nozzle |
| **Spur Gear** | Module, teeth, pressure angle, face width, bore, keyway |

To add a part, write a function in `webui/shapes.py`, register it in `BUILDERS`,
then add its fields to the `PARTS` catalog in `webui/index.html`. The field names
must match exactly.

## Simulation

The **Simulation** panel applies a fixed support to one end of the first body,
a force to the other, solves, and reads the output columns.

Faces are picked by axis (“the lowest end of the X axis”) rather than by fixed
face ids, because those ids change every time the geometry is rebuilt.

For a beam, the UI puts a closed-form comparison next to the result:

```
δ = PL³/3EI        σ = Mc/I
```

**Verification run** (1000 N tip load, 1000 × 50 × 100 mm solid rectangular beam,
Structural steel S275N):

| Quantity | Discovery | Hand check | Δ |
|---|---|---|---|
| Max. displacement | 0.3830 mm | 0.400 mm | −4.3 % |
| Max. von Mises | 12.93 MPa | 12.0 MPa | +7.7 % |
| Factor of safety | 18.36 | — | — |

The FEA coming out **stiffer** than beam theory is expected: a fully clamped end
face suppresses Poisson contraction and section warping, over-constraining the
root. The stress excess is the concentration at that same corner, not an error.

Raising the load to 2000 N scaled every output by **exactly 2.00000**, which
proves both linearity and that the load genuinely changed. That check matters: a
single solve on its own always looks plausible.

## MCP server (Claude Code, Cursor, Antigravity…)

A project-scoped `.mcp.json` ships in the repository:

```json
{
  "mcpServers": {
    "discovery": {
      "command": ".venv\\Scripts\\python.exe",
      "args": ["discovery_mcp\\server.py"]
    }
  }
}
```

When adding it to another client by hand, give **absolute paths** and double the
backslashes on Windows:

```json
"command": "D:\\discovery-grpc-toolkit\\.venv\\Scripts\\python.exe",
"args": ["D:\\discovery-grpc-toolkit\\discovery_mcp\\server.py"]
```

Always use the **virtual environment's** interpreter; a system Python fails on
import because `ansys-geometry-core` is not there.

Tools: `start_discovery`, `connect_discovery`, `discovery_status`, `new_design`,
`create_box`, `create_cylinder`, `create_sphere`, `extrude_polygon`,
`list_bodies`, `delete_body`, `export_design`, `run_geometry_script`,
`list_snippets`, `get_snippet`.

For agent-side routing, the known bugs and an end-to-end example see
[`AGENTS.md`](AGENTS.md); for sample prompts see
[`docs/PROMPTS.md`](docs/PROMPTS.md).

## Repository layout

| Path | Contents |
|---|---|
| `webui/index.html` | Single-file interface — catalog, dimension form, schematic preview, port panel |
| `webui/bridge.py` | Local HTTP bridge; turns the form into gRPC calls |
| `webui/shapes.py` | Parametric part builders |
| `webui/simulation.py` | Boundary conditions, solving and reading results |
| `discovery_mcp/server.py` | MCP server (FastMCP) |
| `discovery_mcp/snippets.py` | Ready-made templates for `run_geometry_script` |
| `scripts/attach-discovery.bat` | Starts Discovery with the gRPC API enabled |
| `scripts/start-webui.bat` | Starts the web UI |
| `scripts/discovery_report.py` | Window screenshot + single-file HTML report |
| `docs/SIMULATION.md` | Full map of the simulation API and its pitfalls |
| `docs/PROMPTS.md` | Sample natural-language prompts |
| `AGENTS.md` | Operating guide for AI agents |
| `examples/test_live.py` | Standalone smoke test |

## Known behaviours

These are real behaviours of this API; the code is written to work around them.
For the details and the measurements see [`docs/SIMULATION.md`](docs/SIMULATION.md).

- **The unit enum is off by one.** Sending `FORCE_NEWTON` makes the server store
  **millinewtons**: a 1000 N load is applied as 1 N, the solve succeeds, and
  every result comes out 1000× too small. Always use `Quantity.as_string`
  (`"1000 N"`) and **read the value back**.
- **`success=False` may still have created the object.** A call that throws while
  building its response has already created the condition; retrying adds a second
  load and the beam carries 2000 N instead of 1000 N. Conditions are always
  listed after creation and strays deleted.
- **Unset sub-messages cause null references on the server.** Even unused fields
  such as `remote_point` have to be filled explicitly.
- **A cutter tangent to an existing face is silently ignored.** A keyway box
  placed to just touch a bore reports a successful `subtract` and removes
  nothing; cutting the keyway first instead makes the *bore* the one that
  no-ops. Every cutter is therefore given a real overlap with the material or
  void it meets.
- **A failed boolean leaves its tool body behind**, which then inflates every
  volume read. The code deletes the tool when a boolean raises.
- **Deleting bodies from a design that holds conditions can crash Discovery.**
  The conditions stay scoped to face ids that no longer exist. On this build
  `Support.GetAll` is UNIMPLEMENTED and there is no `GetSupportByLabel`, so a
  support created by another session cannot even be found. This is why the UI
  defaults to **starting a new design** — a new design brings its own empty
  simulation.
- **The automatic re-read after a boolean can throw** (especially on 24R2). The
  cut or fuse lands on the server and the following `get_assembly` refresh is
  what fails. The code disables that refresh and verifies the volume separately.
- **`Face.centroid` requires backend 27.1+.** On 25.2 use `bounding_box` and
  `normal()`.
- **Gravity is 0 m/s² by default** and the condition only appears in the tree
  after the first condition is added. Self-weight is silently absent — check it
  before comparing against a hand calculation.
- **A modal dialog in Discovery makes a gRPC call never return.** The bridge has
  a timeout watchdog: it flags the session as stuck and tells you what to do.
- **`IsSolving` is False before the solver picks the job up, not just after it
  finishes.** Polling once and seeing False reports a finished solve that never
  ran, and every result then reads NaN while the call claims success. The code
  waits for `IsSolving` to go **True** first, and only then waits for it to go
  False.
- **A long-lived session can reach a state where `Solve` is accepted but never
  runs.** The model is intact — material, support and load are all still in the
  tree — and rebuilding the geometry does not clear it. Restarting Discovery
  does. The UI reports this instead of showing a table of blanks.
- **Solver columns read NaN before the first solve.** `json.dumps` writes bare
  `NaN`, which is *not* valid JSON and makes the browser throw away the whole
  response. The bridge converts every non-finite float to `null` before sending.
- **`export_to_*` does not work on this setup.** PyAnsys' download service fails
  first, then the streaming fallback looks for a server temp file that was never
  created, and every format dies with `Could not find file '<guid>stp'` — the
  same on a plain box, so it is not a geometry problem. The code uses
  **`design.save(path)`** instead: it honours the extension and writes the file
  directly. Verified outputs: **STEP, Parasolid (.x_t/.x_b), IGES, .dsco**.
  **SCDOCX fails on both paths**, so it is not offered in the UI — save it from
  the Discovery window with *File → Save As* if you need it.
- **A call throwing does not mean the work did not happen.** `save()` can write
  the file and then fail while building its response. The code always checks
  disk, never the return value.

## Troubleshooting

| Symptom | Cause / fix |
|---|---|
| “No API-enabled Discovery” | `scripts\attach-discovery.bat` is not running, or the window has not opened yet. It takes 30–60 s; wait and press **Connect** again. |
| Discovery is open but still will not connect | The window was opened by hand, without the API add-in. Close it and open it with the `.bat`. |
| `attach-discovery.bat` says “No Ansys install found” | `AWP_ROOT252` (or 251/242) is not defined. Pass the version: `attach-discovery.bat 252`. |
| The UI says “Session stuck” | A dialog is waiting in Discovery. Close it; if the window crashed, reopen it and press **Connect**. |
| Volume mismatch warning | A boolean did not land on the server. Send again; if it persists, check the dimensions (bolt holes may fall outside the flange body, for example). |
| `ModuleNotFoundError: ansys` | A system Python is being used. Run with `.venv\Scripts\python.exe`. |
| License error | Each session holds a Discovery license. Close extra windows. |

## Contributing and licence

Use GitHub Issues for problems and suggestions. New part types go into
`webui/shapes.py` + `webui/index.html`; follow the structure of the existing
parts.

Released under the **MIT License** — see [`LICENSE`](LICENSE). You may use,
modify and redistribute it, including commercially, as long as the copyright
notice stays with it. It comes with no warranty.

That covers *this repository's* code only. It is not affiliated with Ansys Inc.,
Ansys and Discovery are trademarks of Ansys Inc., and running any of this still
requires your own valid Ansys Discovery licence.

---

# Türkçe

Discovery'nin **ApiServer** eklentisi, açık bir Discovery penceresinde bir gRPC
sunucusu yayınlar. Bu depo o sunucuyu kullanan üç arayüz sunar:

| Arayüz | Kime göre | Ne yapar |
|---|---|---|
| **Web arayüzü** (`webui/`) | Mühendis | Tarayıcıda ölçü gir → “Gönder” → parça canlı Discovery penceresinde belirir. Yük uygula, çöz, sonuçları oku. |
| **MCP sunucusu** (`discovery_mcp/`) | Claude Code, Cursor, Antigravity… | Doğal dille çizim: “200×120×10 plaka çiz, köşelerine Ø12 delik aç.” |
| **Python kütüphanesi** (`webui/shapes.py`, `webui/simulation.py`) | Geliştirici | Kendi otomasyonunuzda doğrudan çağırın. |

## Kurulum

### 1. Ön koşul

Ansys Discovery kurulu olmalı ve **ApiServer eklentisi** bulunmalı:

```
%AWP_ROOT252%\Addins\ApiServer\Presentation.ApiServerAddIn.Manifest.xml
```

Bu dosya yoksa gRPC API o sürüme kurulmamıştır.

### 2. Depoyu alın ve sanal ortam kurun

```bash
git clone https://github.com/numesys/discovery-grpc-toolkit.git
cd discovery-grpc-toolkit
python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
```

Python **3.10+** gerekir (3.12 ile geliştirildi).

### 3. Discovery'yi API açık başlatın

```bash
scripts\attach-discovery.bat
```

Kurulu en yeni sürümü (252 → 251 → 242 → 241) `AWP_ROOT2xx` ortam
değişkenlerinden kendisi bulur; belirli bir sürüm için `attach-discovery.bat 252`.
Pencere açılana kadar bekleyin ve **açık bırakın** — çizimler bu pencereye gider.

> **Önemli:** Elle açtığınız bir Discovery'de gRPC API **kapalıdır** ve
> bağlanılamaz. API yalnızca eklenti manifestiyle başlatılan pencerede açılır;
> `attach-discovery.bat` tam olarak bunu yapar.

### 4. Web arayüzünü başlatın

```bash
scripts\start-webui.bat
```

Tarayıcı `http://localhost:8765/` adresinde açılır. **Bağlan**'a basın, bir
tasarım seçin, ölçüleri girin, **Discovery'ye Gönder**.

### Dil

Arayüz **İngilizce ve Türkçe**dir; varsayılan İngilizcedir. Sağ üstteki
**EN / TR** düğmesiyle anında değişir ve seçim tarayıcıda saklanır.

Tüm metin `webui/index.html` içindeki `I18N` sözlüğündedir. Python katmanı
(`bridge.py`, `shapes.py`, `simulation.py`) yalnızca İngilizce konuşur ve
hatalarını **sabit kodlarla** (`not_connected`, `timeout`, `export_failed` …)
döndürür — arayüz bunları kendi diline çevirir, çevirisi olmayanı İngilizce
gösterir. Üçüncü bir dil eklemek için `I18N`'e bir blok eklemek yeterlidir.

Çözücü sonuç adları (`Max. Displacement`, `Factor of Safety` …) bilerek
çevrilmez: bunlar Discovery'nin kendi çıktı sütun adlarıdır ve olduğu gibi
kalmaları sayıları program penceresiyle karşılaştırmayı kolaylaştırır.

## İki port, iki ayrı bağlantı

Kurulumdaki tek kafa karıştırıcı nokta budur, o yüzden arayüz de ikisini ayrı
gösterir:

| Port | Hat | Ne zaman sorun çıkarır |
|---|---|---|
| **8765** (HTTP) | tarayıcı → `bridge.py` | Neredeyse hiç. Köprü çalışmıyorsa sayfa hiç açılmaz. |
| **50055** (gRPC) | `bridge.py` → Discovery | Genellikle burası. Discovery kapalıysa ya da API eklentisi olmadan açıldıysa bağlantı reddedilir. |

“Bağlanamadı” hatası **neredeyse her zaman ikinci hattı** işaret eder. Arayüzdeki
*Port durumu* satırı `50055`'in dinlemede olup olmadığını canlı gösterir.

MCP sunucusu için not: ajan ↔ sunucu bağlantısı **stdio**'dur, portu yoktur.
`50055` yalnızca sunucu ↔ Discovery hattıdır.

## Web arayüzündeki tasarımlar

Tümü **milimetre**, **Z yukarı**. Her parça analitik hacmiyle birlikte raporlanır;
arayüz bunu Discovery'nin bildirdiği gerçek hacimle karşılaştırır, böylece sessizce
başarısız olan bir boolean gözden kaçmaz.

| Tasarım | Parametreler |
|---|---|
| **Kiriş** | Dolu dikdörtgen / I-profil / kutu profil / dolu yuvarlak; boy, yükseklik, genişlik, gövde ve başlık kalınlığı |
| **Boru** | Dış çap, et kalınlığı, boy, isteğe bağlı uç flanşları |
| **Flanş** | Dış çap, göbek deliği, kalınlık, cıvata çemberi, cıvata çapı/adedi, boyun |
| **Kaplin** | İki yarım göbek, mil deliği, flanş ve göbek ölçüleri, cıvata çemberi, kama kanalı |
| **Plaka** | Genişlik, derinlik, kalınlık, köşe delikleri |
| **Köşebent** | Bacak boyları, et kalınlığı, genişlik, montaj delikleri |
| **Mil** | Üç kademeli çap/boy, kama kanalı |
| **Cıvata** | Altıgen başlık (AF, yükseklik), gövde çapı/boyu, pul |
| **Tank** | Dış çap, cidar, boy, kapak kalınlığı, radyal nozul |
| **Dişli** | Modül, diş sayısı, basınç açısı, genişlik, göbek, kama kanalı |

Yeni bir parça eklemek için `webui/shapes.py` içine bir fonksiyon yazıp
`BUILDERS`'a kaydedin, sonra `webui/index.html` içindeki `PARTS` kataloğuna
alanları ekleyin. Alan adları birebir eşleşmelidir.

## Simülasyon

Arayüzün **Simülasyon** paneli çizilen ilk gövdeye şunu uygular: bir uca ankastre
mesnet, diğer uca kuvvet, sonra çözer ve çıktı sütunlarını okur.

Yüzeyler eksene göre seçilir (“X ekseninin en küçük ucu”), sabit yüzey
kimlikleriyle değil — geometri her yeniden çizildiğinde bu kimlikler değişir.

Kiriş için arayüz sonucun yanına kapalı-form karşılaştırmasını da koyar:

```
δ = PL³/3EI        σ = Mc/I
```

**Doğrulama koşusu** (1000 N uç yükü, 1000 × 50 × 100 mm dolu dikdörtgen kiriş,
Structural steel S275N):

| Büyüklük | Discovery | El hesabı | Fark |
|---|---|---|---|
| Maks. yer değiştirme | 0.3830 mm | 0.400 mm | −4.3 % |
| Maks. von Mises | 12.93 MPa | 12.0 MPa | +7.7 % |
| Güvenlik katsayısı | 18.36 | — | — |

FEA'nın kiriş teorisinden **daha rijit** çıkması beklenir: tam ankastre bir uç
yüzeyi Poisson daralmasını ve kesit çarpılmasını engelleyerek kökü fazla
kısıtlar. Gerilme fazlası da aynı köşedeki yığılmadır, hata değil.

Yük 2000 N'a çıkarıldığında her çıktı **tam olarak 2.00000** katına çıktı —
doğrusallığı ve yükün gerçekten değiştiğini kanıtlar. Bu kontrol şart: tek başına
bir çözüm her zaman makul görünür.

## MCP sunucusu (Claude Code, Cursor, Antigravity…)

Depoda proje kapsamlı bir `.mcp.json` hazır:

```json
{
  "mcpServers": {
    "discovery": {
      "command": ".venv\\Scripts\\python.exe",
      "args": ["discovery_mcp\\server.py"]
    }
  }
}
```

Başka bir istemciye elle eklerken **tam yol** verin ve Windows yollarında ters
bölü çizgilerini çiftleyin:

```json
"command": "D:\\discovery-grpc-toolkit\\.venv\\Scripts\\python.exe",
"args": ["D:\\discovery-grpc-toolkit\\discovery_mcp\\server.py"]
```

Mutlaka **sanal ortamdaki** yorumlayıcıyı kullanın; sistem Python'u
`ansys-geometry-core` bulunmadığı için import'ta düşer.

Araçlar: `start_discovery`, `connect_discovery`, `discovery_status`,
`new_design`, `create_box`, `create_cylinder`, `create_sphere`,
`extrude_polygon`, `list_bodies`, `delete_body`, `export_design`,
`run_geometry_script`, `list_snippets`, `get_snippet`.

Ajan tarafındaki yönlendirme, bilinen hatalar ve uçtan uca örnek için
[`AGENTS.md`](AGENTS.md); örnek prompt'lar için
[`docs/PROMPTS.md`](docs/PROMPTS.md).

## Depo yapısı

| Yol | İçerik |
|---|---|
| `webui/index.html` | Tek dosyalık arayüz — katalog, ölçü formu, şematik önizleme, port paneli |
| `webui/bridge.py` | Yerel HTTP köprüsü; formu gRPC çağrılarına çevirir |
| `webui/shapes.py` | Parametrik parça üreticileri |
| `webui/simulation.py` | Sınır koşulları, çözüm ve sonuç okuma |
| `discovery_mcp/server.py` | MCP sunucusu (FastMCP) |
| `discovery_mcp/snippets.py` | `run_geometry_script` için hazır şablonlar |
| `scripts/attach-discovery.bat` | Discovery'yi gRPC API açık başlatır |
| `scripts/start-webui.bat` | Web arayüzünü başlatır |
| `scripts/discovery_report.py` | Pencere ekran görüntüsü + tek dosyalık HTML rapor |
| `docs/SIMULATION.md` | Simülasyon API'sinin tam haritası ve tuzakları |
| `docs/PROMPTS.md` | Örnek doğal dil prompt'ları |
| `AGENTS.md` | AI ajanları için işletim kılavuzu |
| `examples/test_live.py` | Bağımsız duman testi |

## Bilinen davranışlar

Bunlar bu API'nin gerçek davranışları; kod bunların etrafından dolaşacak şekilde
yazılmıştır. Ayrıntılar ve ölçüm kayıtları için [`docs/SIMULATION.md`](docs/SIMULATION.md).

- **Birim enum'u bir kayık.** `FORCE_NEWTON` göndermek sunucuda **milinewton**
  saklatır: 1000 N'luk yük 1 N olarak uygulanır, çözüm başarılı görünür, her
  sonuç 1000 kat küçük çıkar. Çözüm: her zaman `Quantity.as_string` kullanın
  (`"1000 N"`) ve değeri **geri okuyun**.
- **`success=False` yine de nesne yaratmış olabilir.** Yanıtı oluştururken atan
  bir çağrı koşulu zaten yaratmıştır; tekrar denemek ikinci bir yük ekler ve
  kiriş 1000 N yerine 2000 N taşır. Koşullar yaratıldıktan sonra daima
  listelenir ve fazlalıklar silinir.
- **Boş bırakılan alt-mesajlar sunucuda null referansa yol açar.** Kullanılmayan
  `remote_point` gibi alanlar bile açıkça doldurulmalıdır.
- **Mevcut bir yüzeye tam teğet olan kesici sessizce yok sayılır.** Deliğe
  değecek şekilde konumlanan bir kama kutusu “başarılı” `subtract` bildirir ve
  hiçbir şey kaldırmaz; kamayı önce kesmek bu kez **deliğin** boşa gitmesine yol
  açar. Bu yüzden her kesiciye, karşılaştığı malzeme veya boşlukla gerçek bir
  bindirme verilir.
- **Başarısız bir boolean aletini geride bırakır** ve bu her hacim okumasını
  şişirir. Boolean hata verdiğinde kod aleti siler.
- **Koşulu olan bir tasarımda gövdeleri silmek Discovery'yi çökertebilir.**
  Koşullar artık var olmayan yüzey kimliklerine asılı kalır. Bu build'de
  `Support.GetAll` UNIMPLEMENTED ve `GetSupportByLabel` yok, yani başka bir
  oturumun açtığı mesnet bulunamaz bile. Bu yüzden arayüzün varsayılanı
  **yeni tasarım açmak**tır — yeni tasarım kendi boş simülasyonuyla gelir.
- **Boolean sonrası otomatik yeniden okuma hata verebilir** (özellikle 24R2).
  Kesme/birleştirme sunucuda gerçekleşir, ardından gelen `get_assembly`
  yenilemesi atar. Kod bu yenilemeyi kapatır ve hacmi ayrıca doğrular.
- **`Face.centroid` backend 27.1+ ister.** 25.2'de `bounding_box` ve `normal()`
  kullanılır.
- **Yerçekimi varsayılan olarak 0 m/s²'dir** ve koşul ağaca ilk koşul
  eklendikten sonra görünür. Öz ağırlık sessizce hesaba katılmaz — el hesabıyla
  karşılaştırma yapmadan önce bunu kontrol edin.
- **Discovery modal uyarı kutusu açarsa** gRPC çağrısı hiç dönmez. Köprüde
  zaman aşımı bekçisi vardır: oturumu “takıldı” işaretler ve arayüzde ne
  yapılacağını söyler.
- **`IsSolving`, çözüm bittiğinde olduğu gibi çözücü işi almadan önce de
  False'tur.** Tek sefer yoklayıp False görmek, hiç koşmamış bir çözümü
  “bitti” diye raporlar; sonuçlar NaN gelir ama çağrı başarılı görünür. Kod
  önce `IsSolving`'in **True** olmasını, ancak ondan sonra False'a dönmesini
  bekler.
- **Uzun süre açık kalan bir oturum, `Solve`'u kabul edip hiç çalıştırmadığı
  bir duruma girebilir.** Model sağlamdır — malzeme, mesnet ve yük ağaçta
  durur — ve geometriyi yeniden çizmek bunu düzeltmez. Discovery'yi yeniden
  başlatmak düzeltir. Arayüz boş bir tablo göstermek yerine bunu bildirir.
- **İlk çözümden önce çözücü sütunları NaN okur.** `json.dumps` çıplak `NaN`
  yazar; bu **geçersiz JSON**'dur ve tarayıcı yanıtın tamamını atar. Köprü
  göndermeden önce sonlu olmayan her ondalığı `null`'a çevirir.
- **`export_to_*` bu kurulumda çalışmıyor.** PyAnsys'in indirme servisi önce
  başarısız oluyor, ardından akış yedeği sunucuda hiç oluşturulmamış bir geçici
  dosyayı arıyor ve her format `Could not find file '<guid>stp'` ile ölüyor
  (düz bir kutuda da aynı — geometriyle ilgisi yok). Bunun yerine kod
  **`design.save(yol)`** kullanır: uzantıyı dikkate alır ve dosyayı doğrudan
  yazar. Doğrulanan çıktılar: **STEP, Parasolid (.x_t/.x_b), IGES, .dsco**.
  **SCDOCX her iki yolda da başarısız**, bu yüzden arayüzde sunulmuyor —
  gerekiyorsa Discovery penceresinden *File → Save As* ile kaydedin.
- **Bir çağrının hata fırlatması işin yapılmadığı anlamına gelmez.** `save()`
  dosyayı yazıp yanıtı oluştururken patlayabilir. Kod her zaman diske bakar,
  dönüş değerine değil.

## Sorun giderme

| Belirti | Sebep / çözüm |
|---|---|
| “API açık bir Discovery yok” | `scripts\attach-discovery.bat` çalışmıyor ya da pencere henüz açılmadı. Açılması 30–60 s sürer; bekleyip tekrar **Bağlan**. |
| Discovery açık ama yine de bağlanmıyor | Pencere API eklentisi olmadan (elle) açılmış. Kapatın, `.bat` ile açın. |
| `attach-discovery.bat` “No Ansys install found” diyor | `AWP_ROOT252` (veya 251/242) tanımlı değil. Sürümü elle verin: `attach-discovery.bat 252`. |
| Arayüz “Oturum takıldı” diyor | Discovery'de bekleyen bir uyarı kutusu var. Kapatın; pencere çökmüşse yeniden açıp **Bağlan**. |
| Hacim uyuşmuyor uyarısı | Bir boolean sunucuda tutmamış. Tekrar gönderin; sürerse ölçüleri kontrol edin (ör. cıvata delikleri flanş gövdesini taşıyor olabilir). |
| `ModuleNotFoundError: ansys` | Sistem Python'u kullanılıyor. `.venv\Scripts\python.exe` ile çalıştırın. |
| Lisans hatası | Her oturum bir Discovery lisansı tutar. Fazla pencereleri kapatın. |

## Katkı ve lisans

Sorunlar ve öneriler için GitHub Issues kullanın. Yeni parça tipleri
`webui/shapes.py` + `webui/index.html` ikilisine eklenir; mevcut parçaların
yapısını örnek alın.

**MIT Lisansı** ile yayınlanmıştır — bkz. [`LICENSE`](LICENSE). Telif bildirimi
korunduğu sürece, ticari kullanım dahil olmak üzere kullanabilir, değiştirebilir
ve yeniden dağıtabilirsiniz. Hiçbir garanti verilmez.

Bu yalnızca *bu deponun* kodunu kapsar. Depo Ansys Inc. ile ilişkili değildir,
Ansys ve Discovery Ansys Inc.'in ticari markalarıdır ve buradaki hiçbir şeyi
çalıştırmak için kendi geçerli Ansys Discovery lisansınız gerekir.

---

**Numesys** · [numesys.com.tr](https://www.numesys.com.tr)