# 구조해석 — 전체구조 취약부 자동탐지 계획 (조사 결과 + 실행 계획)

작성 2026-10-09 · CEO 지시(자동탐지 방향 전환) 수행 1단계 = **조사·측정만**. 저장소 코드는 한 줄도 바꾸지 않았다.
대상 = 캐나다 E500 PRO-R 궤도식 작업기 하부 프레임 "500PRO-R 수정안 20260917" **기계 1대(146부품)**
코드 기준 = HEAD `038e082` · 해석 서버 `fea_server.py`(포트 8097) · 화면 `fab.html` + `fab_fea.js`

> **이 문서의 숫자는 전부 이번 세션에 실제로 돌려서 나온 값이다.** 추정한 곳에는 `[추정]`, 확인하지 못한 곳에는 `[미확인]` 을 붙였다.
> 측정에 쓴 도구(저장소 밖, 작업용 임시폴더):
> `diag_conv.py`(통제 실험 — 솔버 입출력 직독) / `diag_quality.py`(tetgen 품질조건 비교) /
> `diag_full_mesh.py`(140부품 전수 메시) / `diag_loose.py`(느슨한 품질조건) / `diag_valid.py`(유효메시 해석 시도)

---

## 0. 한 장 요약 — 이번 조사로 바뀐 결론

| 종전 결론 (수렴시험 보고서) | 이번 측정으로 확정된 결론 |
|---|---|
| 메시가 성겨서(벽당 0.29겹) 수렴하지 않았다 | **성긴 것이 아니라 "유한요소 메시가 아니다."** 전체 요소의 **58.8%** 가 수치적으로 쓸 수 없는 납작한 사면체(슬리버)다 |
| 절점 예산을 올려도 24%만 늘었다 → `-p` 천장 | 천장은 예산이 아니라 **부품당 상한(`PER_CAP`)** 이었다. 상한을 풀면 **152,817절점**(2.4배)까지 간다. 그래도 **벽당 겹수는 0.29 → 0.31** 로 그대로 |
| 변위가 2.08 → 2.57 → 2.10 으로 흔들렸다 | 원인은 메시 밀도도, 용접쌍 변동도, MPC 가중치도 **아니다. 요소 품질이다.** 최대변위 절점은 매번 **요소 2~3개에만 걸친 슬리버 끝**이고, 위치가 메시마다 **2m씩 이동**한다 |
| 부재 20~30개로 좁히면 수렴시킬 수 있다 | 품질조건을 걸면 품질은 **교과서 수준으로 해결된다**(슬리버 58.8% → 0.1%). 그러나 기계 1대 전체는 **절점 102만 / 자유도 307만** 이 되어 **이 PC(32GB)의 CalculiX 로는 못 푼다** |

**→ 핵심 판단: "전체구조를 유효한 솔리드 메시로 한 번에 푸는 길"은 이 PC·이 솔버로는 막혀 있다.
그 한계를 숫자로 확정했으므로, 자동탐지는 "전체(탐지) → 국부(검증)" 2단 구조로 가야 한다.
이것은 CEO 가 금지한 '20~30개 부품으로 대체' 가 아니다 — 전체 146부품은 매번 다 푼다. 국부 재해석은
자동탐지의 *결과*이고, 사용자는 위치를 입력하지 않는다.**

---

## A. 확인된 사실 (전부 실측)

### A-1. 통제 실험 — 변위 흔들림의 원인 분리 (CEO 지시 3·요구산출물 1)

같은 모델(화면이 보낸 `last_request.json` 그대로 — 형상·고정점 6개·하중점 3개·3톤·SS275 동일)로
메시 상한만 4단계 바꿔 돌리고, **솔버가 실제로 받은 입력(`job.inp`)과 낸 출력(`job.frd`)을 직접 읽어** 재었다.

| | 1단계 | 2단계 | 3단계 | 4단계(상한해제) |
|---|---|---|---|---|
| `PER_CAP` / 절점예산 | 4,000 / 150,000 | 8,000 / 300,000 | 16,000 / 600,000 | 해제 / 해제 |
| **절점** | 51,580 | 57,468 | 63,962 | **152,817** |
| 요소(C3D10) | 21,571 | 23,715 | 25,015 | 61,824 |
| **벽당 겹수** | 0.29 | 0.29 | 0.30 | **0.31** |
| 용접 묶인절점 / MPC식 | 2,346 / 7,038 | 2,580 / 7,740 | 3,191 / 9,573 | 6,332 / 18,996 |
| **제외부품 집합 동일?** | — | **동일(True)** | **동일(True)** | **동일(True)** |
| **껍질부품 집합 동일?** | — | **동일(True)** | **동일(True)** | **동일(True)** |
| **MPC 최대가중치 max\|w\|** | 1.0 | 1.0 | 1.0 | 1.0 |
| **MPC 가중치 이상(\|w\|>1.5)** | **0개** | **0개** | **0개** | **0개** |
| **MPC 가중치합 Σw≠1** | **0개** | **0개** | **0개** | **0개** |
| **컴플라이언스 ΣF·u (N·mm)** | **28,719** | **15,377** | **28,835** | **26,480** |
| 최대변위 (mm) | 3.944 | **10.473** | 2.095 | 1.869 |
| 변위 p99 / p50 (mm) | 1.91 / 0.208 | **6.61 / 0.056** | 1.885 / 0.227 | 1.631 / 0.179 |
| 최대변위 절점이 MPC 종속인가 | **아니다** | **아니다** | **아니다** | **아니다** |
| 최대변위 절점이 속한 요소 수 | **2개** | 8개 | **3개** | **3개** |
| 최대변위 위치 (x,y,z) | 4504, 3761, 154 | 3431, 3109, 259 | 5504, 1994, 125 | 5504, 1994, 125 |
| 구조 최대응력(마스크 후, MPa) | 50.6 | **378.0** | 50.9 | 129.6 |
| 전역 첨두(MPa) | 605.3 | 707.6 | 626.1 | 625.2 |
| 전역 첨두 절점이 속한 요소 수 | **1개** | **1개** | **1개** | 2개 |

**읽는 법 — 원인은 하나씩 배제된다:**

- **(b) 용접쌍 변동이 원인이 아니다.** 용접 묶인절점은 2,346 → 2,580 → 3,191 → 6,332 로 **단조증가**인데
  변위는 3.94 → 10.47 → 2.10 → 1.87 로 **오르락내리락한다.** 단조로운 입력이 비단조 출력을 만들 수 없다.
  또 **최대변위 절점은 네 번 모두 MPC 종속절점이 아니다** — 용접 자리에서 나온 값이 아니다.
- **(d) MPC 가중치 오류가 원인이 아니다.** `*EQUATION` 을 전수 파싱해 재었다: 최대가중치 1.0,
  `|w|>1.5` 인 식 0개, 가중치합이 1이 아닌 식 0개. 종속절점이 상대 삼각형 밖으로 투영돼 외삽되는
  현상(= 가중치 폭주)은 **일어나지 않았다.** `tri6_weights` 는 정상 동작한다.
- **모델 구성이 바뀐 것도 아니다.** 제외부품 13개의 **번호 집합**과 껍질 23개의 **번호 집합**이
  네 단계 모두 **완전히 동일**하다(개수만 같은 게 아니라 같은 부품들이다).
- **(c) 요소 품질이 원인이다.** 아래 A-2.

### A-2. ★ 현재 메시는 유한요소 메시로 성립하지 않는다

`job.inp` 의 요소를 전수 계산했다. 지표 세 개:
· **종횡비(ar)** = 최장변/최단변 (좋음 < 3)
· **스케일드 야코비안(sj)** = 요소가 얼마나 납작한가, 0=완전 납작 (상용 해석기 경고선 ≈ 0.1, 거부선 ≈ 0.01)
· **eta** = 정사면체 대비 모양 점수, 1=정사면체

| | 1단계 | 2단계 | 3단계 | 4단계 |
|---|---|---|---|---|
| **sj 중앙값** | 0.0293 | 0.0244 | 0.0170 | **0.0113** |
| **sj < 0.02 인 요소** | **9,272 (43%)** | 11,014 (46%) | 13,309 (53%) | **35,167 (57%)** |
| sj 최소 | 2.8e-9 | 2.8e-9 | 2.8e-9 | **1.4e-11** |
| **종횡비 중앙값** | **8.2** | 8.9 | 10.3 | **13.3** |
| 종횡비 p99 | 1,384 | 1,144 | 1,917 | 1,960 |
| **종횡비 최대** | 2,755 | 2,753 | 3,890 | **55,027** |
| eta 중앙값 | 0.139 | 0.122 | 0.095 | **0.060** |
| 부피가 음수인 요소 | 0 | 0 | 0 | 0 |

**세 줄 정리:**
1. **요소의 43~57% 가 상용 해석기라면 거부당할 품질(sj<0.02)이다.** 종횡비 중앙값이 8~13 이고 최대 55,000 이다.
2. **메시를 "조일수록" 품질이 나빠진다**(sj 중앙 0.029 → 0.011). 그래서 단계를 올려도 수렴하지 않는다 —
   수렴하는 수열이 아니라 **점점 더 나빠지는 수열**이다.
3. 원인은 코드에 명시돼 있다: 전체해석 메시는 `build_tet_mesh_repaired` 가 **`-p`(표면보존) 전용**으로
   만들고 **품질조건(`-q`)을 아예 걸지 않는다.** 품질을 통제하는 장치가 코드에 없다.

### A-3. 컴플라이언스(ΣF·u)로 재면 "이산화가 깨졌다"가 바로 보인다

변위 최대값은 절점 하나의 값이라 슬리버 한 개에 흔들린다. 그래서 **컴플라이언스 = Σ(하중·변위)**
를 같이 재었다(= 변형에너지의 2배). 선형 탄성에서 **구속조건이 같고 메시를 조이면 이 값은
아래에서 단조증가해야 한다**(최소 포텐셜에너지 원리). 전역 적분량이라 슬리버 하나에 안 흔들린다.

측정: **28,719 → 15,377 (−46%) → 28,835 (+88%) → 26,480 (−8%).**

**→ 단조증가해야 하는 값이 ±46~88% 로 요동한다. 이것이 "현재 결과는 수렴 전이 아니라 무의미하다"는
가장 강한 증거다.** (단서: 단조성은 *구속조건이 고정*일 때만 성립한다. 용접 MPC 가 단계마다 달라지므로
이 표만으로 단조성 위반을 100% 품질 탓으로 돌릴 수는 없다. 그래서 A-1·A-2 의 다른 증거와 함께 읽어야 한다.)

### A-4. 2단계(최대변위 10.47mm)의 정체 — 떠다니는 덩어리

2단계만 p50 변위가 0.056mm(다른 단계의 1/4 = 본체가 더 단단하다)인데 p99 가 6.61mm(3.5배)다.
**즉 절점 1개가 튄 것이 아니라 약 1%(약 575절점) 가 한꺼번에 6mm 이상 움직였다** —
구속이 거의 없는 덩어리가 흔들린 모습이다. 품질이 나쁜 요소로 매달린 부재는 신뢰할 강성이 없다.

### A-5. 전역 첨두응력 605~708MPa 는 "요소 1개짜리 섬"에서 나온다

전역 최대 von Mises 가 나온 절점은 1~3단계 모두 **요소 단 1개에만 속한다**(요소수=1).
품질도 같다(eta 0.0713 / sj 0.0051) → **세 단계 모두 같은 자리**다.
**과거 보고서에 실린 "946MPa = 항복의 344%" 류의 숫자는 구조 응력이 아니라 이 한 요소의 외삽값이다.**

### A-6. ★ CalculiX 가 이미 오차추정자를 출력하고 있고, 코드가 그것을 버리고 있다

`job.frd` 실측:
```
 -4  ERROR       1    1
 -5  STR(%)      1    1    0    0
 -1         1 2.69286E+01
```
· 블록 이름 `ERROR`, 성분 `STR(%)` = **절점별 응력 추정오차(%)**, 절점당 값 1개.
· `write_inp` 는 `*NODE FILE / U, S, RF` 만 요청하는데도 **ccx 가 알아서 같이 써 준다**(4단계 전부 확인).
· `parse_frd`(fea_server.py 1072~)는 블록 이름이 `DISP`/`STRESS`/`FORC` 가 아니면 `mode=None` 으로
  **건너뛴다** → 이 값이 한 번도 쓰인 적이 없다. **추가 계산비용 0, 솔버 변경 0.**

실측 분포(1~4단계): 중앙값 **27.8~30.7%**, p90 34.4~36.5%, 최대 46.3~51.4%.
**von Mises 와의 상관계수 0.018 ~ 0.057 = 사실상 무상관.**

**두 가지 뜻:**
1. **지표로 쓸 수 있다.** 전역 최대응력으로 정규화된 값이라면 응력과 강한 상관이 나와야 하는데
   무상관이다 → 응력 크기를 되풀이하는 값이 아니라 **독립된 정보**를 담고 있다.
   (ccx 2.23 내부 정규화 정의는 원문으로 확인하지 못했다 — **[미확인]**. 상관계수는 실측이다.)
2. **지금 결과는 응력오차 중앙값이 30%다.** 솔버 자신이 "이 응력장은 30% 틀렸다"고 말하고 있다.
   그리고 메시를 조여도 거의 안 내려간다(30.7 → 27.8%) — A-2 의 품질 문제와 방향이 맞다.

### A-7. ★ 품질조건을 걸면 품질 문제는 완전히 해결된다

같은 부품(수리 완료 형상)에 tetgen 스위치만 바꿔 재었다(표본 20부품).

| tetgen 스위치 | sj 중앙 | **sj<0.02 비율** | 종횡비 중앙 | 종횡비 p99 | 종횡비 최대 | eta 중앙 |
|---|---|---|---|---|---|---|
| **`-p` (현재)** | 0.0093 | **58.8%** | 18.8 | 411 | 875 | 0.071 |
| `-pq2.0` | 0.355 | **0.0%** | 1.8 | 3.6 | — | 0.756 |
| `-pq1.4` | 0.372 | **0.0%** | 1.8 | 2.6 | — | 0.777 |
| `-pq1.4/10` | 0.378 | **0.0%** | 1.7 | 2.6 | — | 0.784 |
| `-pq1.1` | 0.420 | **0.0%** | 1.6 | 2.1 | — | 0.825 |

**sj 중앙값이 0.0093 → 0.36 (39배), 거부급 요소가 58.8% → 0.0%.** 품질은 "숫자를 바꿔 맞추는 문제"가
아니라 **스위치 한 개로 해결되는 문제**였다. 140부품 전수로도 확인: `-pq2.0` 에서 sj<0.02 가 **0.10%**.

### A-8. 그런데 유효한 메시는 이 PC 로 풀 수 없다 (측정으로 확정)

140부품 전수, `-pq2.0`, 벽두께 보존 확인:

| 표면 처리 | 삼각형 | **절점** | **자유도(DOF)** | sj<0.02 | 벽두께 보존 |
|---|---|---|---|---|---|
| 원본(줄이지 않음) | 61,776 | **2,669,403** | 8,008,209 | 0.10% | **1.000 (완전보존)** |
| 줄이기 hs=60mm, 두께게이트 없음 | 16,046 | 1,054,564 | 3,163,692 | 0.58% | 최소 **0.231 — 20부품 벽 무너짐** |
| 줄이기 hs=40mm, 두께게이트 없음 | 16,154 | 784,867 | 2,354,601 | 0.56% | 최소 **0.231 — 18부품 벽 무너짐** |
| **줄이기 hs=40mm + 두께게이트 0.90** | — | **1,024,077** | **3,072,231** | 0.18% | **보존(게이트 통과분만 줄임, 20부품은 거부)** |
| 줄이기 hs=28mm + 두께게이트 0.90 | — | 1,091,550 | 3,274,650 | 0.26% | 보존 |

**실제 해석 시도 결과(`diag_valid.py`, `-pq2.0`, 전체):**
```
PaStiX 6.4.0 / N: 7763964 / nnz: 603259974  → CalculiX 해석 실패 (프로세스 사망)
```
· 자유도 **7,763,964**, 행렬 비영요소 **6억 32백만**(행렬만 6.7GB).
· 이 PC = **RAM 31.8GB / 16코어**. 3차원 직접해법의 분해(factor)는 행렬의 수십~수백 배가 되므로
  **32GB 로는 불가능**하다. 실제로 분해 시작 지점에서 죽었다.
· **반복해법도 시험했다**: 현재 메시(152,817절점) 의 `job.inp` 에서 `*STATIC` →
  `*STATIC, SOLVER=ITERATIVE CHOLESKY` 만 바꿔 돌렸다 → **15분 이상 메모리 501MB 만 쓰면서
  결과파일을 한 줄도 못 쓰고 수렴하지 않았다**(직접해법은 같은 모델을 13초에 푼다).
  메모리는 문제가 아니고 **수렴이 문제**다. 슬리버가 만든 악조건 때문으로 보이며,
  **품질 좋은 메시에서 반복해법이 수렴하는지는 시험하지 못했다 — [미확인]**.

**★ 마지막 탈출구도 막혀 있다 — 품질조건을 느슨하게 해도 절점이 줄지 않는다**

"품질을 좀 포기하면 절점이 줄어들까"를 140부품 전수로 시험했다(두께게이트 0.90 + hs=40mm 줄이기 공통 적용).
`-q` 첫 숫자가 클수록 느슨한 조건이다.

| tetgen 스위치 | **절점** | DOF | sj 중앙 | sj 하위5% | sj<0.02 | 벽당 겹수 |
|---|---|---|---|---|---|---|
| `-pq2.0` | **1,024,077** | 3,072,231 | 0.340 | 0.147 | 0.18% | 0.71 |
| `-pq3.0/10` | **1,106,914** | 3,320,742 | 0.349 | 0.137 | 0.16% | 0.73 |
| `-pq4.0/10` | **1,085,599** | 3,256,797 | 0.349 | 0.134 | 0.17% | 0.73 |
| `-pq6.0/12` | **1,201,137** | 3,603,411 | 0.360 | 0.155 | 0.15% | 0.74 |

**→ 느슨하게 해도 절점이 줄지 않는다(오히려 조금 늘기도 한다). 절점 수를 정하는 것은 품질조건이 아니라
"벽두께"다.** 벽보다 큰 사면체는 벽을 표현할 수 없으므로 tetgen 은 조건을 어떻게 주든 벽 근처에
10mm 간격으로 점을 넣어야 한다. **따라서 유효한 전체 솔리드 메시의 하한은 절점 약 102만 / DOF 약 307만이고,
이것은 설정으로 조절할 수 있는 값이 아니다.**

**솔버 한계의 산술 (근거: 코드 주석의 실측 + 이번 실측)**
· 알려진 성공점: 절점 152,817(DOF 0.46M) → 13초 / 절점 394,000(DOF 1.18M) → 82.5초
· 실패점: DOF 7.76M → 메모리 초과
· **→ 실용 상한 ≈ 절점 40~50만 / DOF 1.2~1.5M [추정]**
· **최소 유효 전체메시 = 절점 102만 / DOF 3.07M**
· **격차 2.0~2.6배. 게다가 수렴시험은 2배씩 3단계가 필요하므로 가장 성긴 1단계가 이미 한계를 넘는다.**

### A-9. 왜 이것이 구현 문제가 아니라 형상의 본질인지

· 수리 후 140부품 총 부피 **3.904e8 mm³**, 총 표면적 **3.433e7 mm²(34.3 m²)**
· 벽두께: 중앙 **10.67mm**, 하위10% **5.07mm**, 최소 **0.51mm**
· CAD 표면 삼각형 평균 변길이 **35.8mm** — 이미 벽두께보다 3.4배 거칠다
· 유효한 사면체는 **벽보다 큰 요소를 가질 수 없다** → 요소크기 h ≤ 약 10.7mm
· 필요 사면체 ≈ 6V/h³ = 6×3.904e8/1,215 ≈ **193만개 → C3D10 절점 약 270만**
· **실측값 2,669,403 절점과 일치한다.**

**→ 270만 절점은 비효율이 아니라 "얇은 판 구조를 솔리드 사면체로 채우는 일"의 고유 비용이다.
숫자를 조정해 줄일 수 있는 성질이 아니다.**

### A-10. 하중·구속·반력 쪽은 이미 정상이다 (재확인)

· 평형: 전 절점 절점력 합 / 하중 = **0.025%** (F-1 로 확인된 값, 이번에도 유지)
· 적용하중 = 요청하중 29,400N, 소멸 0N, 겹침절점 0
· 지지점 반력 차이 3.8 / 33.8 / 13.4 / 14.0% — **이것은 평형오차가 아니다**(용접 MPC 가 받는 몫).
  단 단계마다 크게 달라지는 것 자체가 A-2 의 품질 문제와 같은 뿌리다.
· 고정점 6개가 모두 주덩어리(133부품) 안에 있다 — 받침면 선택은 맞다.

---

## B. 미구현 (코드에 없다 — "있는 척" 하지 않는다)

| 번호 | 항목 | 현재 상태 (근거) |
|---|---|---|
| **B-1** | **취약부 자동탐지** | 없다. `fea_server.py` 1876~1898 의 `hotspots` 는 **마스크 적용 후 von Mises 상위 3점을 bbox 8% 이상 떨어뜨려 고른 것** = CEO 가 금지한 "최대 응력값 하나로 위험 확정" 그 자체다. 여러 지표를 합친 탐지 로직은 없다 |
| **B-2** | 응력 구배 / 오차추정 / 주응력 / 변형에너지밀도 지표 | 전부 없다. ERR% 는 솔버가 주는데 **버린다**(A-6) |
| **B-3** | 메시 연결 기반 후보 영역 클러스터링 | 없다. 후보는 "점 3개"이고 영역 개념이 없다 |
| **B-4** | 적응형 국부 재해석 | 없다. 요소 크기를 영역별로 다르게 줄 통로가 코드에 없다(`build_tet_mesh_repaired` 는 `-p` 고정) |
| **B-5** | 자동 수렴성 검증 | 없다. `fab_fea.js` 2064~ `MESH_CONV` 는 **2026-10-09 시험 결과를 박아 넣은 상수**이고, `convMatches()` 가 절점수·부품수가 그 시험과 똑같을 때만 표시한다. 계산하는 코드가 아니다 |
| **B-6** | 용접 이음부 전달력 | **0건으로 비어 있다.** `fea_server.py` 1437 `w['force_idx'] = sel_f` 의 선별이 `dA <= wtol(3mm)` — `dA` 는 **두 부재 면중심끼리의 거리**다. 성긴 메시에서 면 하나가 수백 mm라 전부 탈락한다. 코드 1963~ 주석이 이 사실을 이미 적어 두고 `weld_note` 로 "0건"을 알리고 있다 |
| **B-7** | 요소 품질 지표 | 코드에 전혀 없다. 종횡비·야코비안·슬리버 수를 재는 곳이 없어서 A-2 의 상태가 지금까지 보이지 않았다 |
| **B-8** | 컴플라이언스/변형에너지 수렴 지표 | 없다. 수렴 판정이 `max_disp` (절점 1개 값) 기준이라 슬리버에 흔들린다 |
| **B-9** | 고정점·하중점의 CEO 확인 | 자동 외팔보/프리셋 추정값이며 **CEO 확인을 받지 않았다**. 피로 순위(`fab_fea.js` 773~ FAT80)는 **존재한다**(미구현 아님). 단 von Mises 기준이라 용접 피로 평가로는 부적절 — **[AI설명·원문미확인]** |

---

## C. 불가능 / 현재 한계 (기술적 변경 제안 포함)

### C-1. 기계 1대 전체를 "유효한 솔리드 사면체 메시"로 푸는 것 — 이 PC·이 솔버로는 불가능
근거 = A-8 + A-9. 최소 유효메시 DOF 3.07M vs 솔버 실용상한 DOF 약 1.2~1.5M.
**수렴시험(2배씩 3단계)은 8배가 필요하므로 더욱 불가능.**

### C-2. "벽당 1겹"은 전체 모델에서 도달 불가
벽당 1겹 = h ≤ 10.67mm → 절점 약 270만 / DOF 800만. A-8 에서 실제로 죽은 지점이다.
`-pq1.1` 로 벽당 1.47겹이 나오지만 절점이 더 늘어난다. **전체 모델에서는 포기해야 하는 목표다.**

### C-3. 필요한 기술적 변경 — 쉘(판) 요소 (이번 세션 범위 밖)
· 얇은 판의 굽힘은 **쉘 요소**(CalculiX `S6`/`S8R`)가 두께 방향 요소 없이 정확히 표현하도록 만들어진 요소다.
· 규모 산술: 막면적 ≈ 부피/벽두께 = 3.904e8/10.67 ≈ **3.66e7 mm² (36.6 m²)**.
  쉘 변길이 40mm → 약 23,000요소 → **절점 약 7만 / DOF 약 21만** — **지금도 몇 초에 풀린다.**
  솔리드로 벽당 1겹을 맞추려면 270만 절점이니 **약 38배 차이**이고, 굽힘 정확도는 쉘이 더 좋다.
· **블로커 = 중립면(mid-surface) 추출.** 닫힌 솔리드 146개에서 판 중앙면과 두께를 자동으로 뽑아야 한다.
  단순 평판은 가능하지만 ㄷ형강·브래킷·교차부는 어렵다. **몇 주 규모의 기하 과제이고 이번 세션 범위 밖이다.**
· 중간 대안 **[미확인]**: 품질 좋은 메시에서 `SOLVER=ITERATIVE CHOLESKY` 가 수렴하는지. 메모리는
  충분(행렬 2.7GB)하므로 수렴만 되면 C-1 이 풀린다. **가장 값싼 다음 실험**이다.

### C-4. 지금 화면의 응력·안전율 숫자로는 어떤 판정도 할 수 없다
구조 최대응력이 단계마다 **50.6 / 378.0 / 50.9 / 129.6 MPa** 로 7.5배 흔들리고,
솔버 자신의 응력오차 추정이 **중앙 30%** 다. **안전/위험 확정 금지를 유지해야 한다**(CEO 지시 7).
`fab_fea.js` 1943·2026~ 의 "판정 불가" 차단 장치는 이미 들어 있다 — **그것을 끄지 말 것.**

### C-5. 측정의 한계 (정직하게)
· `-pq` 경로로 **전체 모델을 끝까지 푼 적은 없다**(메모리로 실패). 품질 좋은 메시에서 컴플라이언스가
  실제로 단조증가하는지는 **아직 증명하지 못했다** — 국부 모델에서 먼저 보여야 한다.
· ERR% 의 ccx 내부 정규화 정의는 원문 미확인. "응력과 무상관"은 실측, "국부 지표로 유효"는 **[추정]**.
· 표본 20부품으로 전체 절점수를 부피비 외삽한 초기 추정(45만)은 **5.7배 틀렸다**(실제 267만).
  절점수는 부피가 아니라 **얇은 부품**이 지배한다. 전수 측정으로 교체했다.

---

## D. 실행 계획 — 2단 구조 (전체=탐지 / 국부=검증)

> **왜 이 방향인가:** 전체를 유효하게 푸는 길이 측정으로 막혔으므로(C-1), 전체에서는 *어디가 의심스러운지*
> 만 고르고, *얼마나 위험한지*는 그 자리만 제대로 풀어 답한다. 전체 146부품은 매번 전부 해석하며,
> 사용자는 위치를 입력하지 않는다. 국부 재해석은 자동탐지의 결과다.

### D-0. 먼저 할 값싼 실험 2개 (방향이 바뀔 수 있으므로 코드 수정 전에)

| # | 실험 | 통과 기준 | 실패 시 |
|---|---|---|---|
| **E1** | 국부 모델(자동탐지 후보 1곳, 부품 8~15개)을 `-pq2.0` 으로 2~3단계 조여 풀고 **컴플라이언스가 단조증가**하는지 | 단조증가 + 변화율 5% 이내 수렴 | 품질 외 다른 원인이 남아 있다 → 재조사 |
| **E2** | 품질 좋은 메시에서 `SOLVER=ITERATIVE CHOLESKY` 수렴 여부 | 직접해법과 변위 1% 이내 일치 | 전체 유효해석은 포기, D 계획 그대로 진행 |

### D-1. 메시 품질을 코드에 들여온다 (가장 먼저, 가장 값싸다)

1. **품질 지표 계산·보고**: `fea_server.py` 에 요소 품질 함수를 추가해 결과에 싣는다
   (종횡비 중앙/p99/최대, sj 중앙/최소, sj<0.02 비율, 음수부피 수).
   **화면에 "요소 품질" 한 줄을 띄우고, sj<0.02 가 5% 를 넘으면 자동으로 "판정 불가"에 사유를 더한다.**
   → 지금까지 보이지 않던 상태가 매 해석마다 보인다. 이것만으로도 거짓 판정이 막힌다.
2. **ERR%(응력오차) 파싱**: `parse_frd` 에 `ERROR` 블록을 추가(절점당 1값). **솔버 변경 0, 비용 0.**
   결과에 절점별 ERR% 를 실어 보내고 요약(중앙/p90/최대)을 화면에 띄운다.
3. **컴플라이언스 계산**: `ΣF·u` 를 결과에 추가(하중과 변위만 쓰므로 즉시 가능). 수렴 지표를 여기로 옮긴다.
4. `PER_CAP` 이 실제 상한이라는 사실을 코드 주석과 화면 표시에 반영한다
   (`build_tet_mesh_repaired` 458행 `cap = min(budget_nodes or PER_CAP, PER_CAP)` — 예산을 올려도
   `PER_CAP` 때문에 안 늘어난다는 사실이 지금 어디에도 적혀 있지 않다).

**커밋 단위:** 품질지표 / ERR% / 컴플라이언스 각각 성공할 때마다 즉시 커밋.

### D-2. 전체해석(1단) = 탐지 전용으로 성격을 바꾼다

전체 메시는 그대로 `-p` 를 쓴다(바꿀 수 없다 — C-1). 대신 **전체해석의 출력에서 "응력 판정"을 떼고
"후보 지목"만 남긴다.** 품질이 나쁜 메시에서도 상대적으로 견디는 양을 쓴다:

| 탐지 지표 | 왜 이것인가 | 구현 상태 |
|---|---|---|
| **용접 이음부 전달력** | 접촉면 트랙션의 **면적분**. 적분량은 점 최대값보다 메시·품질에 훨씬 둔감하다. 힘이 많이 지나가는 이음부가 곧 하중경로다 | **B-6 버그 수정 필요**(면중심 거리 → 점↔삼각형 거리 `point_tri_dist` 는 이미 코드에 있다) |
| **단면 대비 전달력** | 전달력 ÷ 그 이음부/부재의 단면적 = 평균 응력 수준. 응력 첨두가 아니라 역학적 과부하를 본다 | 신규 |
| **지지점 반력 분포** | 이미 정상(A-10). 어느 받침이 과하게 받는지 | 있음, 표시만 |
| **ERR%** | "여기 결과는 못 믿는다"의 지표. 응력과 무상관(A-6)이라 독립 정보 | D-1-2 로 확보 |
| **요소 품질(국부)** | 후보 자리가 슬리버 소굴이면 후보가 아니라 **메시 결함**이다. 둘을 반드시 구분한다 | D-1-1 로 확보 |
| von Mises (참고만) | 지금처럼 **순위에만** 쓰고, 값은 인용 금지 | 있음 |

**후보 영역 만들기(클러스터링):** 좌표 k-means 가 아니라 **메시 연결(요소 인접)로 연결성분을 잡는다** —
후보는 "물리적으로 이어진 영역"이어야 한다. 각 후보에 반드시 붙일 근거:
① 어느 지표가 몇 번째인지 ② 가장 가까운 고정점/하중점/MPC/껍질 경계까지의 거리
③ 그 영역의 요소 품질 ④ 그 영역의 ERR% ⑤ **"특이점 의심 / 구조 후보 / 메시 결함" 3분류**

> **금지:** 최대 응력 하나로 순위를 정하지 않는다. 고정·하중·MPC·껍질 근처의 높은 응력을
> 파손 위험으로 올리지 않는다(거리를 숫자로 적어 사용자가 직접 보게 한다).

### D-3. 국부 재해석(2단) = 여기서만 응력을 말한다

**구조적으로 이미 가능하다 — 이것이 이번 조사의 가장 좋은 소식이다.**
현재 메시는 **부품 1개 = tetgen 1회**이고(`run_fea` 1329~1348), 부품별 디스크 캐시가 있다
(`build_tet_mesh_repaired` 의 `m<hash>.npz`). 따라서:

1. 후보 영역에 닿는 부품만 골라 **그 부품만 `-pq2.0` 으로 다시 메시**한다. 나머지는 캐시를 그대로 쓴다.
2. 부품 8~15개 규모면 **절점 10~30만 / DOF 30~90만 → 솔버 한계 안**이다(A-8 산술).
3. 경계조건: 전체해석의 변위를 잘라낸 경계에 **강제변위로 얹는다**(`write_inp` 에 `prescribed` 통로가
   이미 있다). CalculiX `*SUBMODEL` 은 쓰지 않는다 — 별도 보간 오차가 생기고, 같은 모델 안에서
   부품만 다시 메시하는 쪽이 깨끗하다.
4. **그 영역에서 2~3단계(요소크기 1/2씩) 조여 컴플라이언스·고정 탐침점 응력의 변화율을 자동 계산** →
   후보마다 "수렴 / 미수렴" 표시. **미수렴이면 그 후보는 판정 불가로 남긴다.**

**한계 2개를 반드시 표시:**
· 세분화 단위가 "영역"이 아니라 **"부품"** 이다. 1,225mm 판 가운데가 후보면 그 판 전체가 조여진다(비용).
  진짜 영역 단위가 필요하면 tetgen `-m`(크기함수 파일 `.mtr`) 경로가 있다 — **지원 확인됨**(`-m  Applies
  a mesh sizing function`), 구현은 미검증.
· 잘라낸 경계에 전체해석(품질 나쁜 메시)의 변위를 얹으므로 **경계 근처 결과는 못 믿는다.**
  후보는 잘라낸 경계에서 충분히 안쪽에 있어야 한다(반경 자동 결정 시 이 조건을 넣는다).

### D-4. 용접쌍 고정 (요구산출물 2의 "용접쌍은 1단계에서 확정해 고정")

**"용접쌍 고정"이 뜻할 수 있는 것은 하나뿐이다 — 쌍 목록과 접촉 영역을 고정하는 것이고,
절점 목록은 고정할 수 없다.** MPC 는 *메시 절점*을 묶는 것이라 메시가 바뀌면 묶는 절점은 반드시 바뀐다.
그래서:

· **접촉 판정을 메시 전 "입력 표면"(CAD 삼각형)에서 수행**해 `(부품i, 부품j, 접촉영역 bbox)` 목록을 확정한다.
  (오프라인 실측에서 이 방식이 참 쌍 243개를 정확히 재현했다 — FINDINGS F14/F20)
· 그 목록을 메시 단계에 넘겨 **같은 쌍·같은 영역 안에서만** 절점을 묶는다.
· **이것은 "수렴 지표가 뜻을 가지기 위한 전제조건"이다** — 개선 항목이 아니다. 묶음이 단계마다 달라지면
  컴플라이언스 단조성 자체가 성립하지 않으므로(A-3 단서), **D-3 의 수렴시험보다 먼저 들어가야 한다.**

### D-5. 화면 (`fab_fea.js`)

· 후보 **순위 목록** + 3D 마커 + 각 후보의 **근거 줄**(어느 지표 / 특이점과의 거리 / 품질 / ERR% / 수렴여부)
· 후보마다 **"수렴 / 미수렴 / 판정불가"** 배지. 미수렴·판정불가에는 안전율·응력값을 **아예 띄우지 않는다.**
· "요소 품질" 한 줄과 "응력오차(ERR%) 중앙값" 한 줄 상설 표시.
· `MESH_CONV` 하드코딩 상수를 **서버가 계산한 값**으로 교체(B-5).
· 제약 준수: `alert` 금지 / 15MB 빌드 html 금지 / selftest PASS 유지.

### D-6. 작업 순서와 이유

| 순서 | 작업 | 이유 |
|---|---|---|
| 1 | **E1·E2 실험** | 방향이 바뀔 수 있다. 코드 수정 전에 한다 |
| 2 | **D-1 품질지표 + ERR% + 컴플라이언스** | 가장 값싸고, 거짓 판정을 즉시 막는다. 이후 모든 판단의 계측기 |
| 3 | **D-4 용접쌍 CAD 기준 확정** | 수렴 지표가 뜻을 가지기 위한 전제 |
| 4 | **B-6 용접 전달력 버그 수정** | D-2 의 주력 탐지 지표가 지금 0건이다 |
| 5 | **D-2 자동탐지 + 클러스터링 + 근거** | 여기서 CEO 목표(자동탐지)가 처음 성립한다 |
| 6 | **D-3 국부 재해석 + 수렴 자동판정** | 탐지된 후보를 실제로 검증 |
| 7 | **D-5 화면 + 브라우저 증빙** | 마지막. 계산이 먼저 |

### D-7. 성공 기준 (이 중 하나라도 못 하면 "완료"라고 보고하지 않는다)

1. 매 해석마다 요소 품질·ERR%·컴플라이언스가 숫자로 나온다
2. 사용자 입력 없이 후보 영역이 순위와 **근거**와 함께 나온다
3. 후보마다 "특이점 의심 / 구조 후보 / 메시 결함"이 구분된다
4. 상위 후보에서 국부 재해석 2~3단계가 돌고 **컴플라이언스가 단조증가**한다
5. 수렴하지 않은 후보에는 안전율·응력값이 **표시되지 않는다**
6. 브라우저 화면 캡처로 1~5가 보인다

---

## E. CEO 지시 7개 항목에 대한 현재 답

| 지시 | 답 |
|---|---|
| 1. 응력·변형률·변위·안전율 계산 방식 | CalculiX C3D10 선형 정적. 변위·응력은 `.frd` 절점값, von Mises 는 서버 계산, 안전율 = fy/구조최대응력. **변형률은 계산하지 않는다**(출력 요청 안 함). **이 숫자들은 현재 신뢰할 수 없다 — A-2/A-3** |
| 2. 자동 탐지 가능한가 | **불가능(미구현). B-1.** 부족한 것 = 응력구배·오차추정(ERR%, 솔버가 주는데 버림)·변형에너지밀도·이음부 전달력(버그로 0건)·메시 연결 기반 클러스터링·요소 품질 지표 |
| 3. 2.08→2.57→2.10 원인 | **확정: 요소 품질(슬리버).** 메시 밀도·용접쌍·MPC 가중치·모델 구성은 전부 배제됨. A-1/A-2 |
| 4. 요소·품질·메시·하중·접촉·구속·알고리즘 점검 | 완료. 요소 C3D10(정상) / **품질 치명적** / 메시 `-p` 전용(품질조건 없음) / 하중·평형 정상(0.025%) / 접촉 MPC `*EQUATION` 가중치 정상 / 구속 정상 / 솔버 PaStiX 직접해법, 반복해법 미수렴 |
| 5. 적응형 해석 가능한가 | **부품 단위로는 가능**(부품별 tetgen + 부품별 캐시 구조). **영역 단위는 tetgen `-m` 필요, 미검증.** 전체 모델을 유효하게 조이는 것은 **불가능(C-1)** |
| 6. 후보 영역 근거 표시 | **미구현.** D-2 설계 완료 |
| 7. 수렴 전 확정 판정 금지 | **지킨다.** 현재 미수렴·응력오차 30% 이므로 판정 불가 유지. 화면 차단 장치는 이미 있다 |

**빨간색이 가장 먼저 깨지는 곳이라고 단정하지 않는다** — 현재 빨간 자리는 A-5 에서 보듯 요소 1개짜리 섬이다.

---

*기록: Claude Code(deep-reasoner) · 실측만 기재 · 저장소 코드 변경 0 · 해석 실행 6회(성공 5, 메모리초과 1)*

---

# 부록 F — 2차 조사 (요구산출물 2단계 착수 중 측정)

작성 2026-10-09 후반 · 커밋 `f0f086a` 이후 추가 측정. 저장소 코드는 여전히 변경 0.

## F-1. tetgen `-a`(세분화) 는 정상 작동한다 — 내 1차 계산이 틀렸다

부품 #82 `RB702_0272_2`(삼각형 1,044 / 부피 52,327mm³ / 벽 8.17mm) 단독 실측:

| 스위치 | 사면체 | 절점 | 평균 요소크기 | 벽당 겹수 | sj 중앙 |
|---|---|---|---|---|---|
| `-pq2.0` | 45,232 | 77,118 | 1.91mm | 4.28 | 0.262 |
| `-pq2.0a10.4` | 55,106 | 93,581 | 1.79mm | 4.57 | 0.284 |
| `-pq2.0a2.0` | 96,738 | 156,243 | 1.48mm | 5.52 | 0.349 |
| `-pq2.0a0.5` | **248,648** | **374,484** | 1.08mm | 7.56 | 0.406 |
| `-pa10.4` | 55,106 | 93,581 | — | — | 0.284 |
| `-pq2.0a100.0` | 46,253 | 78,979 | 1.89mm | 4.31 | 0.266 |

· **`-a` 는 잘 먹는다.** 체적상한을 1/20 로 줄이면 사면체가 5.5배가 된다.
· 요소수 ∝ (체적상한)^-0.6 정도로 움직인다 → **2배로 조이려면 체적상한을 약 1/3.2 로** 줘야 한다.
· `-pa10.4` 와 `-pq2.0a10.4` 가 **완전히 같다** → tetgen 은 `-a` 를 주면 품질조건을 기본 적용한다(코드 주석의 서술이 맞다).
· `-pq2.0a100.0` ≈ `-pq2.0` → 상한이 이미 만족되면 아무 일도 안 일어난다.

**★ 내가 1차로 "`-a` 가 안 먹는다"고 본 것은 내 계산 실수였다.**
`run_fea` 가 돌려주는 `mesh.elem_size_mm` 는 **부품별 세제곱근 평균의 평균**(`np.mean(esizes)`, 1443행)이라
5.00mm 로 나오는데, 실제 부품 요소크기는 1.9mm 였다. 그 5.00mm 로 체적상한을 뽑으니 상한이
실제 요소보다 **9배 커서** 제약이 처음부터 비활성이었다.
**→ 세분화 사다리의 체적상한은 `elem_size_mm` 로 뽑지 말고, 그 메시에서 실제로 나온
"총부피 ÷ 요소수"(평균 요소 부피)에서 뽑아야 한다.** (`through_wall` 도 `mean(walls)/mean(esizes)` 라 같은 함정이 있다.)

## F-2. 거친 쪽으로는 사다리를 만들 수 없다 — 벽두께 보존이 막는다

국부 영역(14부품)에서 표면목표 34mm 로 줄이기를 시도했으나 **절점수가 303,182 로 원본과 완전히 동일**했다.
원인: 벽두께 보존 게이트(0.90)가 줄이기를 전부 거부했다. 1,044삼각형 판재를 40삼각형으로 줄이면
벽이 무너지므로(ratio < 0.9) 올바르게 거부된 것이다.

**→ 전체 모델(A-8)에서 본 것과 같은 물리적 구속이 국부에서도 그대로 성립한다:
얇은 판의 표면은 벽을 망가뜨리지 않고는 거칠게 만들 수 없다.
따라서 메시 사다리는 "거침→촘촘" 이 아니라 반드시 "품질 하한에서 시작해 `-a` 로 조이는" 방향이어야 한다.**

## F-3. ★★ 가장 중요한 발견 — 품질 메시에서는 용접 짝짓기가 'CAD 정답' 과 정확히 일치한다

> **이 한 가지가 과거 작업 한 묶음을 모두 무효화한다.** FINDINGS 의 F19/F20/F22 가 처방한
> "양방향 slave 선택 / 접촉절점 요구 3→1 / 역할 뒤집기 재시도 / 공중에 뜬 21부품" 은
> **용접 알고리즘의 결함이 아니라 `-p` 성긴 메시의 증상이었다.** 메시를 고치면 함께 사라진다.

같은 14부품을 두 방법으로 판정해 비교했다.

| 판정 방법 | 용접쌍 | 연결성분 | 최대 덩어리 | 고아 |
|---|---|---|---|---|
| **CAD 입력표면** (점↔삼각형, tol 3.0mm) — 메시 전 | **21** | 1 | **14부품** | 0 |
| 메시 절점 기준 (`find_weld_pairs`), `-pq2.0` 메시, wtol 1.5mm | 20 | 1 | **14부품** | 0 |
| 메시 절점 기준, `-pq2.0` 메시, wtol 3.0mm | **21** | 1 | **14부품** | 0 |

(메시 14/14 성공, 절점 171,816)

**→ 용접 짝짓기 알고리즘은 틀리지 않았다.** 품질 메시에서는 메시 기준 판정이 CAD 정답(21쌍)을
**정확히 재현**한다. FINDINGS 에 기록된 "부품이 공중에 뜬다 / 짝짓기가 절반을 놓친다"는
**`-p` 성긴 메시의 증상이었고, 메시를 고치면 함께 사라진다.**

**★ 계획 D-4(용접쌍 CAD 기준 고정)는 "전제조건" 에서 "있으면 좋은 것" 으로 내려간다.**
연결을 *살리기* 위해 필요한 것이 아니라, 단계마다 묶음이 달라지는 것을 막아 수렴 지표를
엄밀히 비교하기 위한 장치일 뿐이다. **오케스트레이터의 주경로에서 빼도 된다 — 작업 1건 감소.**

## F-4. 국부 모델은 유효하고, 풀리고, 응력오차가 1/3.5 로 떨어진다 (계획 E1 부분 성공)

하중점에서 가까운 부품을 자동 선택(기하 규칙 — **균열 위치를 지정하지 않는다**)해 `-pq2.0` 로 해석:

| 항목 | 전체 146부품 (`-p`, 현행) | **국부 (`-pq2.0`)** |
|---|---|---|
| 절점 / 요소 | 51,580 / 21,571 | **303,182 / 178,107** |
| **sj < 0.02 (쓸 수 없는 요소)** | **43%** | **0.000%** |
| 종횡비 중앙 | 8.2 | **1.84** |
| **벽당 겹수** | **0.29** | **2.26** |
| **ERR%(솔버 응력오차) 중앙 / p90** | **30.7 / 36.4** | **8.68 / 28.65** |
| 평형오차 | 0.025% | **0.0002%** |
| 변위 max / p99 (비) | 3.944 / 1.909 (**2.07배**) | 0.0297 / 0.0234 (**1.27배**) |
| 최대변위 절점이 속한 요소 수 | **2개** | 4개 |
| 구조최대 vs 전역첨두 | 50.6 vs 605.3 MPa (**12배 차**) | **194.1 vs 194.1 MPa (일치)** |
| ccx 시간 | 11~13초 | **73초** |

**다섯 줄로 읽는 법:**
1. 품질이 완전히 해결된다(쓸 수 없는 요소 43% → 0.000%).
2. **벽당 2.26겹** — 목표였던 1겹을 국부에서는 넘어선다.
3. **솔버 자신의 응력오차가 30.7% → 8.68% 로 떨어진다.** ERR% 가 메시 품질에 반응한다는 직접 증거이고,
   따라서 **"여기 결과는 못 믿는다"의 지표로 쓸 수 있다**(계획 D-2).
4. 변위 max/p99 비가 2.07 → 1.27 — **슬리버가 만든 가짜 첨두가 사라졌다**(변위장이 매끄럽다).
5. **구조최대와 전역첨두가 같아졌다** — 첨두가 경계조건·MPC·껍질 자리에 있지 않다는 뜻이고,
   전체 모델에서 보이던 "요소 1개짜리 섬의 605MPa" 같은 인공 첨두가 없다.

**단, 3단계 수렴 표는 아직 만들지 못했다.** 이유 = F-1 의 계산 실수로 1차 사다리가 세 단계 모두
같은 메시를 풀었고(절점 303,182 동일), F-2 로 거친 쪽 사다리도 막혔다. 올바른 사다리는
**`-pq2.0` 기준에서 평균 요소부피 × 1/3.2, × 1/10 으로 조이는 것**이며(F-1 근거),
그러면 절점이 약 30만 → 60만 → 120만이 된다. **60만은 풀 수 있을 것으로 보이나, 120만은
전체 모델 실패(DOF 776만)와 같은 메모리 벽에 부딪힐 가능성이 크다 — [미검증].**
**→ 3단계 사다리는 더 작은 영역(부품 3~5개, 절점 8만부터)에서 시작해야 한다.**

## F-5. 요구산출물 2단계(전체 146부품에서 절점 2배씩 3단계)에 대한 판정

### ★ 먼저 — 내가 측정한 것과 측정하지 않은 것을 구분한다 (1차 서술 교정)

부록 F 초판에 "유효한 전체 메시의 **하한** = 절점 102만 (품질조건 무엇을 쓰든)" 이라고 썼다.
**이 표현은 과장이다.** 내가 실제로 바꿔 본 것은 `-q` 의 반경/최단변 비 네 가지뿐이고,
표면 줄이기는 **hs=40mm · 두께게이트 0.90 한 점에서만** 재었다.

| 측정한 것 (실측) | 측정하지 않은 것 |
|---|---|
| `-pq2.0 / 3.0/10 / 4.0/10 / 6.0/12` 네 설정 모두 절점 **102만~120만** → **반경비 완화는 절점을 줄이지 못한다** | 두께게이트 **0.80 / 0.75** — 0.90 만 돌렸다 |
| 두께게이트 **없이** 줄이면 절점 **78.5만**, 단 18~20부품의 벽이 최대 0.231배로 무너진다 | hs **40~28mm 사이** × 게이트 0.90 이외의 조합 |
| 두께게이트 **0.90** 에서 절점 **102만** (줄이기 거부 20부품) | 게이트를 0.80 으로 낮췄을 때의 절점수·벽 손상 목록 |

**→ 바로잡은 결론 (이것만 주장한다):**
1. **반경비(`-q`) 완화로는 절점이 줄지 않는다** — 설정 4개로 실측. 절점수를 정하는 것은 벽두께다.
2. **hs=40 / 게이트 0.90 에서 유효한 전체 메시는 절점 1,024,077 / DOF 3,072,231 이고,
   입증된 솔버 성공점(DOF 0.91M)의 약 2배다.**
3. **전체 모델을 "한 번" 유효하게 푸는 것은 두께게이트를 0.80 정도로 낮추면 닿을 수도 있다 — 미검증.**
   (게이트 없이 78.5만까지 내려가는 것이 실측이므로 그 사이에 해가 있을 가능성이 있다.
   대신 어느 부품의 벽이 얼마나 얇아지는지를 반드시 목록으로 남겨야 한다.)
4. **그러나 "절점 2배씩 3단계" 사다리는 시험한 어떤 설정으로도 닿지 않는다** —
   가장 거친 1단계가 최종의 1/4 이어야 하는데, 유효 메시의 관측 범위 자체가 78.5만~120만에 몰려 있어
   한 자리에서 움직이지 않는다. **이것이 2단 구조(전체=탐지 / 국부=검증)를 택하는 실제 근거다.**

### 솔버 쪽 실측 (바뀌지 않음)

| 항목 | 측정값 |
|---|---|
| CalculiX **실패** 지점 | DOF **7,763,964** / nnz 603,259,974 → 프로세스 사망 (RAM 31.8GB) |
| CalculiX **성공** 지점 | 절점 152,817 (DOF 0.46M) 13초 · 절점 303,182 (DOF 0.91M) 73초 |
| **솔버 실용 상한** | 절점 **30~50만** / DOF **0.9~1.5M** — **[추정]** (0.91M 성공, 7.76M 실패 사이를 좁혀 재지 않았다) |
| 반복해법(`ITERATIVE CHOLESKY`) | 현재 `-p` 메시(152,817절점)에서 **15분 미수렴**, 메모리 501MB. 품질 메시에서는 **미검증** |

## F-5b. ★ 미해결 모순 — 같은 14부품이 6부품으로 줄어든 이유를 모른다 (핸드오버 1번 항목)

같은 14부품·같은 스위치(`-pq2.0`)인데 두 측정이 어긋난다.

| 측정 | 부품 | 절점 | 연결 |
|---|---|---|---|
| `diag_local.py` → `run_fea` 경로 | **6** (제외 8) | **303,182** | — |
| 직접 메시+`find_weld_pairs` 경로 | **14 / 14** | **171,816** | 1덩어리 / 고아 0 / 21쌍 |

**둘 다 같은 모델을 말할 수는 없다.** 가능한 원인(어느 것인지 확정하지 못했다):
① `run_fea` 는 부품 하나가 여러 덩어리로 쪼개지면 전부 넣는데(`split_components`), 내 직접 측정은 `sub[0]` 만 썼다
② `run_fea` 의 '고정 부재와 용접으로 안 이어진 부품 자동 제외' 가 실제로는 이어진 부품을 빼고 있다
③ 자동 외팔보 경계조건이 잡은 고정면이 일부 부품만 닿았다

**왜 중요한가:** F-4 의 머리글 숫자(ERR% 8.68 / 벽당 2.26겹 / 절점 303,182)는 **그 6부품 결과**인데
그 6부품이 무엇인지 모른다. 만약 ②라면 **전체해석에서도 매번 조용히 부품이 빠지고 있다는 뜻**이고,
실제로 전체해석은 지금 13부품을 제외하고 있다.

**핸드오버 첫 작업(1회 실행):** 14부품 국부 모델을 다시 돌려 `failed_parts`(메시 실패)와
`auto_dropped`(연결 제외)를 **따로** 찍어 본다. 버그면 드러나고, 측정 착오면 설명된다.

## F-7. ★★ 코드에 이미 '품질 메시 경로' 가 있다 — 부품 40개 이하에서만 켜진다

`fea_server.py` 1327행 `_bulk = len(comps) > MANY_PARTS` (MANY_PARTS = 40, 90행).

| 부품 수 | 타는 경로 | tetgen | 품질 |
|---|---|---|---|
| **41개 이상** (= 기계 1대 전체) | `build_tet_mesh_repaired` | **`-p` 전용** | **쓸 수 없는 요소 43~57%** |
| **40개 이하** (= 검증·국부) | `build_tet_mesh` | **`-pq1.4a` / `-pq2.0a` 승격** | **쓸 수 없는 요소 0.000%** |

**실측(3부품, 기존 `build_tet_mesh` 경로를 그대로 사용 — 내 패치는 호출되지 않았다):**
절점 188,721 / 요소 116,909 / **sj<0.02 = 0.0000% / 종횡비 중앙 1.87 / 벽당 2.70겹** /
ERR% 중앙 20.06 / 평형오차 0.000351% / ccx 57초.

**→ 계획 D-3(적응형 국부 재해석)의 구현 비용이 크게 내려간다.**
새 메시 경로를 만들 필요가 없다. **후보 영역을 40부품 이하로 잘라 기존 경로에 넘기면
품질 메시가 이미 나온다.** 바꿀 것은 "어느 부품을 넘길지 고르는 로직"뿐이다.

**또한 A-2 의 품질 재앙은 전체해석(bulk) 경로에 국한된 것임이 확정됐다** —
`-q` 승격을 건너뛰는 그 한 가지 선택이 원인이다(근거: 코드 451~516행 주석 + 실측).

## F-8. ★ F-5b 모순 해결 — 연결성 버그가 아니라 '부품당 품질개선 제한시간' 이었다

`fea_server.py` **1321행**: `_qto = 8.0 if len(comps) == 1 else max(2.5, 40.0 / len(comps))`
→ **부품당 품질개선 시간이 부품 수에 반비례**하고, 그 시간을 넘긴 부품은 메시가 실패해 제외된다.

| 부품 수 | 부품당 제한시간 | 제외된 부품 | 출처 |
|---|---|---|---|
| 3개 | **13.3초** | **0개** | 실측 (F-7) |
| 14개 | **2.86초** | **8개** | 실측 (F-4 / `diag_local.py`) |
| 14개 (직접시험, 제한 240초) | 240초 | **0개** (14/14 성공) | 실측 (F-3) |

**→ F-5b 의 "6부품 vs 14부품" 모순은 연결성 판정 버그가 아니다. 제한시간이다.**
같은 14부품이 2.86초에서는 8개가 죽고 240초에서는 0개가 죽는다.

**세 가지 결과:**
1. **F-3 의 결론이 더 강해진다** — 용접 짝짓기·연결성 판정에는 버그가 없다.
2. **D-3 에서 국부 영역을 자를 때 부품 수가 품질을 좌우한다.** 40.0/n 공식 때문에
   후보 영역을 넓게 잡으면 품질개선이 조용히 포기된다. **제한시간을 부품 수와 분리해야 한다.**
3. **지금 전체해석이 제외하는 13부품의 사유를 다시 봐야 한다** — bulk 경로는 `_qto` 를 쓰지 않으므로
   13부품은 다른 이유(형상 수리 실패)일 것이나, **확인하지 않았다 — [미확인]**.

## F-9. ★★★ 3단계 메시 사다리 실측 — 2단 완주, 3단 메모리 초과. 그리고 D-4 를 되살려야 한다

국부 영역(하중점 최근접 3부품 — **균열 위치를 지정하지 않는 기하규칙**)에서
품질 하한 `-pq2.0` 에서 시작해 tetgen `-a` 로 조였다.

| | **1단계** | **2단계** | 3단계 |
|---|---|---|---|
| 스위치 | `-pq2.0` | `-pq2.0a18.205` | `-pq2.0a5.689` |
| **절점** | **93,276** | **619,347** (6.64배) | — |
| 요소(C3D10) | 53,951 | 405,247 | — |
| **벽당 겹수** | **1.56** | **4.36** | — |
| **쓸 수 없는 요소(sj<0.02)** | **0.0000%** | **0.0000%** | — |
| 종횡비 중앙 | 2.30 | **1.63** | — |
| **컴플라이언스 (N·mm)** | **78,772.37** | **68,675.77** | — |
| 최대변위 (mm) | 3.1265 | 2.6964 | — |
| 구조최대 응력 (MPa) | 1,305.02 | 732.93 | — |
| **ERR%(솔버 응력오차) 중앙 / p90** | **23.06 / 29.89** | **9.17 / 24.31** | — |
| 평형오차 | 0.000941% | **0.000187%** | — |
| **용접 묶인절점** | **5,924** | **8,495 (+43%)** | — |
| ccx 시간 / 메모리 | 25초 | **423초 / 약 18GB** | **메모리 초과 사망** |

### 판정: **미수렴** (컴플라이언스 −12.82%, 변위 −13.76%)

### ★ 그런데 "단조성 위반" 의 원인은 품질이 아니다 — 용접 구속이 늘어난 것이다

요소 품질은 두 단계 모두 **완벽하다**(쓸 수 없는 요소 0.0000%, 종횡비 2.30 → 1.63).
그런데 **용접 묶인절점이 5,924 → 8,495 로 43% 늘었다.**

· `*EQUATION` 으로 묶인 절점 하나는 자유도 3개를 없애고 그 자리를 **강체처럼** 붙인다.
· 메시를 조이면 허용오차(wtol) 안에 들어오는 표면 절점이 많아져 **묶음이 자동으로 늘어난다.**
· 묶음이 늘면 이음부가 더 단단해지고 → **컴플라이언스가 내려간다.**
· 즉 메시를 조이면 두 가지가 동시에 일어난다: (a) 굽힘을 더 잘 표현해 **부드러워짐**,
  (b) 이음부 구속이 늘어 **단단해짐**. 이번에는 (b)가 이겼다.

**→ 최소 포텐셜에너지 원리의 단조성은 "구속조건이 고정" 일 때만 성립한다.
구속이 단계마다 늘어나므로 이 표의 비단조는 이산화가 깨진 증거가 아니다. 시험 설계의 결함이다.**

### ★★ 따라서 F-3 에서 내린 판단을 되돌린다 — D-4(용접쌍 고정)는 다시 '전제조건' 이다

F-3 에서 "품질 메시에서는 짝짓기가 CAD 정답과 일치하니 D-4 는 있으면 좋은 것" 이라고 적었다.
**짝짓기의 *정확성* 에 대해서는 맞지만, 수렴 시험의 *전제* 로서는 틀렸다.**
어느 부품끼리 붙는지(쌍 목록)는 메시와 무관하게 정확해도, **묶이는 절점 수는 메시 밀도에 따라 늘어난다.**
그것만으로 모델의 강성이 바뀌어 수렴 지표가 무의미해진다.
**CEO 지시의 "용접쌍은 1단계에서 확정해 고정" 은 바로 이 문제를 정확히 가리킨 것이었다.**

**구현 처방 (요구 2의 핵심):**
1. **CAD 접촉면에 일정 간격으로 '용접 씨앗점' 을 미리 박는다**(메시와 무관한 고정 좌표).
2. 각 단계에서 씨앗점마다 **가장 가까운 절점 1개만** 종속으로 삼는다.
   → **묶인 절점 수가 단계마다 똑같아진다** → 구속 고정 → 컴플라이언스 단조성이 뜻을 갖는다.
3. 더 올바른 길: CalculiX의 **면대면 묶음 접촉**(`*TIE` / `*CONTACT PAIR, TYPE=SURFACE TO SURFACE`).
   구속을 절점 표본이 아니라 면 전체에 가중 적용하므로 강성이 절점 수에 따라 자라지 않는다. **미검증**.

### ★ 부수 소득 1 — ERR%(솔버 오차추정자)가 올바르게 거동한다

**23.06% → 9.17%.** 메시를 조이면 솔버가 추정하는 응력오차가 2.5배 줄어든다.
앞서 전체 모델(30.7%) → 국부(23.1%) → 조인 국부(9.17%) 로 일관되게 내려간다.
**→ "여기 결과는 못 믿는다" 를 가리키는 국부 지표로 쓸 수 있다(계획 D-2). ERR% 는 공짜다.**

### ★ 부수 소득 2 — 솔버 상한을 다시 재야 한다 (F-5 재교정)

**절점 619,347 / DOF 1,858,041 을 약 18GB·423초로 실제로 풀었다.** 이것은 내가
F-5 에서 적은 추정 상한(절점 30~50만 / DOF 0.9~1.5M)보다 **높다.**

| | 절점 | DOF | 결과 |
|---|---|---|---|
| 실측 성공 | **619,347** | **1,858,041** | 423초 / 약 18GB |
| 실측 실패 | 약 150~200만 [추정] | — | 메모리 초과 |
| 실측 실패 (전체모델 `-pq2.0`) | 2,587,988 | 7,763,964 | 메모리 초과 |
| **갱신된 실용 상한** | **약 65~75만** | **약 2.0~2.3M** | **[추정]** |

**→ 유효한 전체 메시(절점 1,024,077)와의 격차가 2배가 아니라 약 1.4~1.6배로 줄었다.
그리고 두께게이트 없이 줄이면 78.5만(실측)이다 — 이는 성공점 61.9만의 1.27배에 불과하다.**

**★ 결론 수정: "기계 1대 전체를 유효한 메시로 *한 번* 푸는 것" 은 닿을 가능성이 상당히 높다.**
두께게이트를 0.90 → 0.80 근처로 낮춰 절점을 80~90만으로 맞추면 25~28GB 로 풀릴 수 있다.
**여전히 미검증이지만, 이것이 가장 값진 다음 실험이다**(E1 보다 우선).
단 **"절점 2배씩 3단계 사다리" 는 그래도 불가능하다** — 61.9만을 2배 하면 124만이고 이미 죽는다.

## F-6. 2차 조사로 확정된 "못 한 것"

| 항목 | 상태 |
|---|---|
| 요구 2 — 전체 모델 3단계 메시 (절점 2배씩) | **불가능 확정** (F-5). 코드 수정 안 함 |
| 요구 3 — 취약 후보 자동탐지 | **미구현.** 설계만(계획 D-2) |
| 요구 4 — 적응형 국부 재해석 | **미구현.** 단, 국부 품질해석이 실제로 돌고 유효하다는 것은 확인(F-4) |
| 요구 5 — 후보별 수렴 자동판정 | **미구현.** 3단계 사다리 자체를 아직 못 만들었다(F-4 마지막 단락) |
| 요구 6 — 브라우저 스크린샷 | **미수행** (표시할 새 기능이 없다) |

---

# 부록 G — 0단계 실험 결과: ★★★ 전체 146부품 품질메시가 완주했다

작성 2026-10-09 밤 · CEO 지시 0단계(최우선) 실행 결과. 실험 스크립트는 저장소 밖
(`exp0_bulk_quality.py`). **저장소 코드는 이 실험 중에는 변경 0.**

> **F-9 의 예측이 맞았다.** "두께게이트를 낮춰 절점을 80~90만으로 맞추면 풀릴 수 있다 —
> 미검증" 이라고 적었던 그 실험을 돌렸고, **풀렸다.**

## G-0. 결론 한 줄

**기계 1대 전체(146부품)를 품질조건(`-pq2.0`) 메시로 한 번 푸는 것은 가능하다.
절점 786,278 / DOF 2,358,834 / ccx 196.7초 / 메모리 피크 약 17.4GB / 평형오차 0.00099%.
쓸 수 없는 요소(sj<0.02)는 43~57% → 0.28% 로 떨어졌다.**
**단, 벽당 겹수가 0.59 로 1겹에 못 미친다 — 품질(모양)은 해결됐지만 굽힘 분해능은 아직 아니다.**

## G-1. 메시 사다리 실측 (3회, 전부 완주)

세 함정을 피해 `build_tet_mesh_repaired` 만 '품질 경로' 로 바꿔치기했다
(`build_tet_mesh` 를 그대로 쓰면 ① 1568행 `dense_surface(len(F)>2000)` 가 `-p` 결과를
즉시 돌려주고 ② 1591행 절점>예산이면 `-p` 로 조용히 물러나고 ③ 1321행 `_qto` 가
146부품에서 2.5초가 되어 품질개선이 포기된다 — 실험이 아무것도 못 재게 된다).

절점 수를 조절하는 손잡이는 **표면 줄이기 목표 변길이 `hs`** 하나이고,
**벽두께 보존비 게이트 0.80**(줄인 뒤 벽 ÷ 줄이기 전 벽)이 거부하면 한 단 덜 거칠게
물러나는 사다리(x1.00 → x0.75 → x0.50 → x0.35)를 만들었다.

| `hs` (표면 목표 변길이) | **절점** | 요소(C3D10) | DOF | **불량요소 sj<0.02** | sj 중앙 | 종횡비 중앙 | 벽당 겹수 중앙 | 메시 시간 |
|---|---|---|---|---|---|---|---|---|
| 40mm | 1,244,896 | 654,948 | 3,734,688 | **0.094%** | 0.455 | 2.07 | 0.72 | 22초 |
| 55mm | 893,551 | 458,332 | 2,680,653 | **0.144%** | 0.486 | 1.99 | 0.68 | 17초 |
| **75mm** | **843,185** | 431,156 | 2,529,555 | **0.278%** | 0.483 | 2.02 | 0.66 | 20초 |

**→ 55mm 와 75mm 의 차이가 5.6% 뿐이다. 절점 수의 바닥은 약 84만이고,
`hs` 를 더 키워도 내려가지 않는다 — F-5 의 "절점 수를 정하는 것은 벽두께다" 가 재확인됐다.**
(한 번만 줄이기를 시도하면 게이트가 거부한 부품이 원본 밀도를 그대로 유지해
상위 5부품이 전체 절점의 39% 를 차지했다. 사다리로 물러나게 해서 124만 → 89만으로 내렸다.)

## G-2. 실제 해석(`run_fea` 전체 경로) 완주 — hs=75 / 게이트 0.80

| 항목 | 전체 146부품 (`-p`, 현행) | **전체 146부품 (`-pq2.0`, 이번)** |
|---|---|---|
| 절점 / 요소 | 51,580 / 21,571 | **786,278 / 401,466** |
| DOF | 154,740 | **2,358,834** |
| 해석에 들어간 부품 | 133 (제외 13) | **125 (형상실패 6)** |
| **쓸 수 없는 요소(sj<0.02)** | **43%** | **0.278%** |
| sj 중앙 / 종횡비 중앙 | 0.029 / 8.2 | **0.483 / 2.02** |
| **벽당 겹수** | **0.29** | **0.59** |
| **평형오차** | 0.025% | **0.00099%** |
| 적용하중 / 요청하중 / 소멸 | — | 29,400N / 29,400N / **0N** |
| 지지점 반력 차이 | 3.8~33.8% | **3.52%** |
| 구조최대 응력(마스크 후) | 50.6 MPa | **175.6 MPa** (안전율 1.57) |
| 전역 첨두 | 605.3 MPa | 576.7 MPa |
| 최대변위 | 3.944 mm | **55.50 mm** |
| **ccx 시간 / 메모리 피크** | 11~13초 / 소 | **196.7초 / 약 17.4GB** |
| 전체 완주 시간(메시+해석+후처리) | 약 100초 | **225초** |
| **완주 여부** | 완주 | **완주(ok=True)** |

메모리는 실측으로 추적했다: 4.0GB → 15.4GB → **17.4GB(피크)** → 2.9GB(분해 종료 후).
**이 PC(31.8GB)에서 약 14GB 여유가 남았다.**

## G-3. 그런데 "됐다" 고 말하면 안 되는 것 3개 (CEO 지시 — 계산 안 한 것을 한 것처럼 금지)

1. **벽당 겹수 0.59 — 1겹 미달.** 요소 *모양* 은 교과서 수준(종횡비 2.0)이지만
   요소가 벽보다 크다. 2차 요소(C3D10)라 1겹이면 충분하다는 것이 selftest 의 근거인데,
   0.59겹은 그 기준에도 못 미친다. **굽힘 응력의 정확도는 아직 보장되지 않는다.**
2. **최대변위가 3.94mm → 55.50mm 로 14배가 됐다.** 두 가지 가능성이 섞여 있다 —
   (a) `-p` 메시가 슬리버 때문에 과도하게 단단했고 품질 메시가 진짜 유연도를 보여준 것,
   (b) 표면 줄이기로 얇아진 부재가 실제보다 약해진 것. **어느 쪽인지 확정하지 못했다 — [미확인].**
   따라서 **55.50mm 를 '실제 처짐' 으로 인용해서는 안 된다.**
3. **수렴 시험은 여전히 안 됐다.** 이 결과는 1점이다. 절점을 2배(157만)로 올리면
   메모리 벽(F-9 에서 사망)에 부딪히므로, **전체 모델의 수렴 사다리는 그대로 불가능하다.**
   G-2 의 응력·안전율로 **안전/위험을 확정하면 안 된다**(CEO 지시 유지).

## G-4. 형상 실패 6부품 (전체해석이 조용히 빼던 부품의 정체 — F-8 의 [미확인] 해결)

bulk 경로의 제외는 제한시간이 아니라 **형상 결함**이었다. 실측 사유:

| 부품 | 사유 |
|---|---|
| 138번(Group74) | 정점이 3개뿐 — 형상이 없음 |
| 29번(Group44) | 두께 0인 면 형상 (300 x 0 x 300 mm) |
| 133·134·135·136번(WINCH_BASE_PLATE_25T_1) | 두께 0인 면 형상 (28 x 30 x 0 mm) |

**→ 6부품 모두 "속을 채울 수 없는 평면 조각" 이다. 해석 알고리즘의 결함이 아니라
CAD 데이터의 결함이고, 그 부품만 모델을 고쳐야 한다.** (종전 13부품 제외와 숫자가 다른 이유는
`-p` 경로의 수리 사다리와 품질 경로의 수리 결과가 다르기 때문 — 품질 경로에서 7부품이 되살아났다.)

## G-5. 다음 단계에 주는 결론

**전체해석을 "성긴 탐지 전용" 으로 둘 필요가 없어졌다. 선택지가 2개로 늘었다:**

| 선택지 | 절점 | 시간 | 품질 | 쓸모 |
|---|---|---|---|---|
| A. 현행 `-p` 전체 | 5.2만 | 약 100초 | **쓸 수 없는 요소 43%** | 흐름 보기용만 |
| **B. 품질 `-pq2.0` 전체(이번)** | **78.6만** | **225초** | **불량 0.28% / 종횡비 2.0** | **후보 탐지에 쓸 수 있다** |
| C. 국부 품질 재해석 | 9~62만 | 25~423초 | 불량 0.000% / 벽당 1.6~4.4겹 | **응력 값을 말할 수 있는 유일한 층** |

**→ 3단계(후보 자동탐지)의 입력은 B 로 간다**(A 의 슬리버 43% 위에서 지표를 계산하면
지표 자체가 무의미하다). **4단계(국부 검증)는 C 가 그대로 담당한다.**
벽당 1겹 미달이므로 **B 에서는 응력 값을 인용하지 않고 "어디가 의심스러운가" 만 고른다** —
이것은 애초 계획 D-2 의 성격과 같고, 달라진 것은 그 판단의 바탕이 쓸 수 없는 메시에서
쓸 수 있는 메시로 바뀌었다는 점이다.

## G-6. 이 실험의 한계 (정직하게)

· 1차 조사의 측정 스크립트(`diag_full_mesh.py` 등)는 **임시폴더와 함께 사라졌다**.
  그래서 "두께게이트 0.90 → 절점 102만"(A-8) 과 이번 "게이트 0.80 → 절점 84~124만" 은
  **줄이기 구현이 다른 별개 측정**이다. 두 숫자를 직접 비교하면 안 된다.
  이번 숫자는 전부 이번 구현의 자체 측정이고, 같은 구현 안에서는 비교할 수 있다.
· 메모리 17.4GB 는 1초 간격 폴링의 관측 피크다. 폴링 사이의 더 높은 순간값은 못 봤다.
· `hs` 를 75mm 보다 더 키운 경우, 게이트를 0.80 보다 더 낮춘 경우는 재지 않았다.

## G-7. ★★★ 교정 — 55.5mm 는 줄이기 손상이었다. 정답 설정은 hs=55mm 다

G-3 에 "최대변위 55.50mm 의 원인 미확정" 이라고 적었다. **판별 실험을 돌려 확정했다.**
같은 게이트(0.80), 같은 경로, `hs` 만 75 → 55mm 로 바꿔 한 번 더 완주시켰다.

| | hs=75mm (G-2) | **hs=55mm (이것이 정답)** | 참고: 현행 `-p` 전체 |
|---|---|---|---|
| **절점 / DOF** | 786,278 / 2,358,834 | **893,076 / 2,679,228** | 51,580 / 154,740 |
| **벽당 겹수** | 0.59 (1겹 미달) | **1.09 (1겹 넘김)** | 0.29 |
| **최대변위** | **55.50 mm** | **4.19 mm** | 3.944 mm |
| 구조최대 응력 | 175.6 MPa | 327.5 MPa | 50.6 MPa |
| 전역 첨두 | 576.7 MPa | 1,672.9 MPa | 605.3 MPa |
| 평형오차 | 0.00099% | 0.00147% | 0.025% |
| 지지점 반력 차이 | 3.52% | 7.09% | 3.8~33.8% |
| 해석에 들어간 부품 | 125 | **136** | 133 |
| 형상실패 / 자동제외 | 6 / **15** | 6 / **4** | 13 / — |
| 껍질 대체 부품 | 18 | 23 | 23 |
| ccx 시간 | 196.7초 | **220.1초** | 11~13초 |
| 완주 | ok=True | **ok=True** | ok=True |

**읽는 법 — 네 가지가 동시에 맞아떨어진다:**
1. **55.50mm → 4.19mm.** 현행 `-p` 전체의 3.944mm 와 같은 크기다. **hs=75 의 55.5mm 는
   물리가 아니라 표면 줄이기가 부재를 얇게 깎아 만든 가짜 유연함이었다**(게이트 0.80 이
   부품당 20% 벽 손실까지 허용했고, hs=75 에서 38부품이 0.80~0.89 구간에 걸렸다).
2. **벽당 겹수 1.09 — 처음으로 1겹을 넘겼다.** selftest 가 PASS 하는 각파이프가 0.97겹이므로
   **이 밀도는 검증된 정확도 영역 안이다.**
3. **자동제외가 15개 → 4개로 줄었다.** 거칠게 깎으면 부재가 서로 안 닿는 것으로 판정돼
   조용히 빠진다. hs=55 에서는 거의 사라졌다 → 연결이 제대로 살아 있다는 뜻이다.
4. **용접부 검토 건수는 4건(hs=75) → 5건(hs=55)이다.**
   **※ 이 줄은 초판에서 "0건 → 5건으로 살아났다" 라고 잘못 적었다.** 그 "0건" 은
   계획 B-6 이 서술한 현행 `-p` 경로의 상태이고, 이 두 실험 중 어느 쪽에서도 측정한
   값이 아니다. 게다가 hs=75 실험은 B-6 수정 **이전** 코드로 돌았고 hs=55 는 이후라
   메시까지 달라서 **두 숫자를 '수정 효과' 로 읽어서도 안 된다.**

**→ 전체 146부품 품질해석의 운전 설정은 `-pq2.0` + 표면목표 hs=55mm + 벽두께 게이트 0.80,
절점 약 89만, 약 260초(메시+해석+후처리)다.**

### 그래도 확정하면 안 되는 것 (변함없음)
· **수렴은 여전히 증명되지 않았다.** 절점을 2배(179만)로 올리는 길이 메모리로 막혀 있다.
  구조최대 327.5MPa 는 항복(275MPa)의 119% 지만 **이 숫자로 '위험' 을 확정하면 안 된다**
  — 전역 첨두가 1,672.9MPa 로 구조최대의 5.1배라 아직 특이점이 지배한다.
· hs=75 와 hs=55 는 메시가 서로 다르므로 **두 열을 '수렴 2단계' 로 읽어서는 안 된다**
  (구속·껍질 집합이 함께 달라졌다 — F-9 가 지적한 시험설계 결함과 같은 함정).
· 146부품 중 실제로 풀린 것은 **136개**다: 형상실패 6(두께 0 평면 조각 = CAD 결함) +
  연결 자동제외 4(65·88·89·111번). **"146 전부 풀었다" 고 말하지 않는다.**

---

# 부록 H — 구현 결과와 못 한 것 (2026-10-09 밤 세션)

## H-1. 한 일

| 단계 | 상태 | 근거 |
|---|---|---|
| 0. 전체 품질메시 완주 실험 | **완료** | 부록 G·G-7. 절점 89.3만 완주, 벽당 1.09겹 |
| 1. 용접 씨앗점 고정 | **미구현** | 아래 H-3 |
| 2. 공짜 지표 파싱·계산 | **완료** | ERR%·요소품질·컴플라이언스·용접전달력 버그·제한시간 분리 |
| 3. 취약 후보 자동 탐지 | **완료** | `detect_candidates()` + 화면 목록·마커·근거 |
| 4. 적응형 국부 재해석 | **미구현** | 아래 H-3 |
| 5. 후보별 수렴 자동 판정 | **미구현(차단 해제만)** | 하드코딩을 '미확정' 으로 바꿔 거짓 표시를 막았다 |
| 6. 브라우저 증명 | **완료** | `_fea_자동탐지_20261010_1~3.jpg` |

## H-2. 브라우저 실측 (전체 146부품, 기본 `-p` 모드, 화면에서 실행)

해석 21.8초 · 절점 51,580 · 요소 21,571 · 133부품 해석 / 13부품 제외 ·
구조최대 47.3 MPa · 최대변위 2.007mm · 반력검증 ✓ 0.01%

**새로 보이게 된 것:**
· 요소 품질 — **쓸 수 없는 요소 36.75%** / 모양점수 중앙 0.041 / 종횡비 중앙 8.23 (최대 2,755)
· **벽당 0.72겹 — 1겹 미달: 굽힘 정확도 미보장**
· **⚠ 쓸 수 없는 요소가 5%를 넘습니다 — 이 결과의 응력값으로 판정하지 마세요**
· 솔버 응력오차(ERR%) 중앙 **30.5%** / p90 36.2% / 최대 47.0%
· 컴플라이언스 ΣF·u = **27,270 N·mm**
· 메시 수렴: **✗ — 이 해석의 계산값이 아니라 2026-10-09 시험 기록입니다** (하드코딩을 정직하게 표시)

**★ 자동 탐지가 한 일 — 가장 중요한 결과:**
1위·2위 후보를 전부 **"메시 결함"** 으로 분류했다.
· 1위 @ (3692, 3103, 250) 부재 21번 Group73 — **이 영역 요소의 16.56% 가 쓸 수 없는 품질**
· 2위 @ (3381, 3099, 242) 부재 36번 Group73 — **6.70%**
· 두 후보 모두 세 지표 합의 1.00(von Mises·구배·변형에너지밀도 모두 상위 0%)인데,
  **"응력값이 형상 때문인지 메시 때문인지 가릴 수 없습니다" 로 판정을 보류했다.**

**→ 이것이 CEO 지시의 핵심이 작동한 증거다.** 종전 코드였다면 이 자리가
"최대응력 상위 3곳 = 가장 먼저 깨지는 곳" 으로 올라갔을 것이다. 지금은 올라가지 않는다.

## H-3. 못 한 것 (숫자로)

| 번호 | 항목 | 왜 못 했나 |
|---|---|---|
| 1 | **용접 씨앗점 고정(1단계)** | 미착수. 이것이 사는 자리는 4단계의 국부 재해석이다(전체 모델은 2배 사다리가 메모리로 막혀 있어 수렴 지표 자체를 못 만든다 — F-9·G-3) |
| 2 | **적응형 국부 재해석(4단계)** | 미착수. 후보 반경 → 부품 선별 → 전체해석 변위를 경계에 강제(`prescribed` 통로는 이미 있다) → `-q` 재해석. 설계는 D-3 에 있다 |
| 3 | **후보별 수렴 자동 판정(5단계)** | 4단계가 없으면 비교할 2단계가 없다. 대신 **거짓 표시는 막았다** — 서버가 계산한 값이 없으면 '미확정' 으로 적는다 |
| 4 | **품질 모드의 브라우저 실행** | 체크박스는 만들었고 헤드리스로 2회 완주했으나, 화면에서 켠 채로는 돌리지 않았다(약 4분·20GB) |
| 5 | **ERR% 의 ccx 내부 정규화 정의** | 원문 미확인(A-6 그대로). 거동이 메시 품질에 반응한다는 것만 실측 |
| 6 | **피로 지표(⑥)의 서버 계산** | 후보에는 '가장 가까운 용접 이음부의 FAT80 비율' 을 붙였을 뿐, 후보 자체의 피로 순위는 화면 로직(`fatigueTop`) 그대로다 |

**146부품 중 실제로 풀린 것:** 기본 모드 133개(제외 13) / 품질 모드 136개(형상실패 6 + 자동제외 4).
**"146 전부 풀었다" 고 말하지 않는다.**

## H-4. ★ 자기정정 — B-6 '용접 전달력 수정' 은 처음에 무효였다

커밋 `6f94e89` 의 메시지가 "B-6 용접 전달력 버그 수정" 이라고 단정했는데, **그 수정은
실제로 걸리지 않는 상태였다.** 뒤늦게 확인한 사실 두 가지:

1. **거름망을 중심거리로 다시 걸고 있었다.** 점↔삼각형 정확거리를 계산하기 **전에**
   `dA <= wtol * 6.0` 으로 후보를 좁혔는데, `dA` 가 바로 B-6 이 "틀렸다" 고 지목한
   **면중심끼리의 거리**다. `wtol` 이 약 3mm 라 문턱이 약 18mm 인데, 실측 요소크기가
   14.7mm 이고 성긴 메시의 면은 수백 mm 다 → **참인 접촉면이 정확거리를 재 보기도 전에
   탈락한다.** 고친 코드가 호출조차 안 되는 구조였다.
   · **고침:** 문턱을 `wtol + (A 면의 중심→꼭짓점 최대거리)` 로 바꿨다. 이것은
     어림수가 아니라 **수학적으로 안전한 상한**이다 — 삼각형 위 어떤 점까지 거리가
     wtol 이하면 중심까지 거리는 반드시 이 값 이하다. 참인 접촉면을 놓칠 수 없다.
2. **`iface_area_mm2` 는 어디에서도 채워지지 않는 키였다.** 결과 JSON 과 화면이
   언제나 `0.0` 을 보여주고 있었고, 그래서 선별이 제대로 되는지 확인할 방법이 없었다.
   · **고침:** 선별된 접합면의 삼각형 면적 합을 실제로 계산해 채운다.

**그리고 "0건 → 5건으로 살아났다" 는 G-7 의 문장도 근거가 없었다**(위 G-7 정정 참조).
hs=75 실험은 수정 **이전** 코드로 4건, hs=55 는 이후 코드로 5건이며 메시도 달라
둘을 '수정 효과' 로 비교할 수 없다. **같은 모델·같은 메시에서 수정 전후를 비교한 적이 없다.**

**→ 지금 상태: 거름망은 올바른 경계로 바꿨고 면적도 계산하게 했지만,
`iface_area_mm2` 가 0 이 아닌 값으로 나오는 것을 아직 눈으로 확인하지 못했다 — [미확인].
다음 세션의 첫 확인 항목이다.** (확인 방법: 전체해석 1회 → 결과 JSON 의
`welds[*].iface_area_mm2` 가 0 보다 큰지. 0 이면 거름망이 아니라 다른 곳이 원인이다.)

## H-5. ★ H-4 의 [미확인] 해결 — 품질 메시 위에서 전부 실측했다 (최종 실행)

저장소 현행 코드(`quality_bulk=True`)로 전체 146부품을 한 번 더 돌렸다. **232초 완주.**

### (1) 용접 접합면 선별 — 고쳐졌다

| | 수정 전 | **수정 후(이번)** |
|---|---|---|
| `iface_area_mm2` | **전부 0.0** (키가 채워진 적 없음) | **6,995 / 8,334 / 7,560 / 4,524 / 1,989 mm²** |
| 용접 건수 | 5 | 5 |
| 용접선 길이 | 659 / 718 / 889 / 593 / 307 mm | 동일 |

**→ 접합면이 실제로 선별되고 면적이 계산된다. H-4 의 [미확인] 이 해결됐다.**
(전달력 12,207N 은 종전과 같다 — 설계상 전달력은 접합면 응력 적분이 아니라
'용접 건너편 부재에 걸린 외력의 정역학 합' 이기 때문이다. 접합면 면적은 그 선별이
제대로 되는지 확인하는 숫자이지 전달력의 입력이 아니다.)

### (2) 품질 메시 위의 전체 지표 (기본 `-p` 모드와 나란히)

| | 기본 `-p` (화면 실측) | **품질 `-pq2.0` (이번)** |
|---|---|---|
| 절점 / 요소 | 51,580 / 21,571 | **893,076 / 458,169** |
| **쓸 수 없는 요소(sj<0.02)** | **36.75%** | **0.144%** |
| 종횡비 중앙 / p99 / 최대 | 8.23 / — / 2,755 | **1.84 / 3.8 / 3,354** |
| **벽당 겹수** | **0.72** | **1.09** |
| 요소크기 중앙(실측) | 14.7mm | **9.7mm** |
| **ERR%(솔버 응력오차) 중앙 / p90 / 최대** | **30.5 / 36.2 / 47.0** | **20.9 / 32.3 / 59.6** |
| 컴플라이언스 ΣF·u | 27,270 N·mm | **56,994 N·mm** |
| 평형오차 | 0.01% | **0.0015%** |
| 지지점 반력 차이 | 6.3% | 6.91% |
| 구조최대 / 전역첨두 | 47.3 / — MPa | **323.9 / 1,640.6 MPa** |
| 최대변위 | 2.007mm | **4.16mm** |
| 해석 부품 | 133 | **136** (형상실패 6 + 자동제외 4) |
| ccx / 전체 | 10.8초 / 21.8초 | **181.7초 / 232초** |

### (3) ★ 자동 탐지가 품질 메시에서 한 일 — '메시 결함' 이 사라지고 '특이점 의심' 이 남았다

| 메시 | 1·2위 후보 분류 | 그 영역 불량요소 |
|---|---|---|
| 기본 `-p` | **메시 결함** | 16.56% / 6.70% |
| **품질 `-pq2.0`** | **특이점 의심** (8/8 전부) | **0.00%** |

품질 메시에서는 불량요소가 0% 라 '메시 결함' 분류가 나오지 않고, 대신 상위 후보가
**전부 용접 구속 1.3mm / 0.9mm / 10.0mm 이내**(요소 9.7mm 의 2배 이내)에 있다.

**→ 이것이 CEO 지시 "특이점·접촉·구속 근처 고응력을 무조건 위험으로 해석 금지" 가
작동하는 모습이다.** 세 지표 합의가 1.00(전부 상위 0%)인 자리들인데도 위험으로 올리지
않고, **구속까지의 거리를 mm 로 적어 운전자가 직접 보게 한다.**
동시에 그 자리가 **용접 이음부라는 사실 자체는 숨기지 않는다**(가장 가까운 이음부의
전달력 12,207N · 피로 11.4% 를 후보마다 붙인다) — 피로 균열이 실제로 시작되는 자리이기 때문이다.

**단, 이 메시에서 "구속에서 충분히 떨어진 순수 구조 후보" 는 한 건도 나오지 않았다.**
용접 MPC 가 절점의 29.7% 를 덮고 있어 본체 대부분이 구속 1요소 이내이기 때문이다.
**이것은 4단계(국부 재해석)와 1단계(용접 씨앗점 고정)가 왜 필요한지를 숫자로 보여준다 —
묶음이 너무 넓어 "구조 본체" 가 남지 않는다.** 다음 세션의 첫 작업이 여기다.

### (4) 그래도 확정 금지 (변함없음)
구조최대 323.9MPa 는 항복(275MPa)의 118% 지만 **전역 첨두가 1,640.6MPa 로 5.1배**이고
**수렴은 여전히 미증명**이다(2배=179만은 메모리 벽). 안전/위험 확정 금지를 유지한다.

---

# 1~3단계 실측 기록 (2026-10-10)

## 1단계 — 용접 씨앗점 고정 (전체 146부품 품질메시, quality_bulk)

| 항목 | 종전(메시 기준 접촉) | 씨앗점 고정 |
|---|---|---|
| 절점 | 893,076 | 890,007 |
| 용접으로 묶인 절점 | 약 265,000 (추정, MPC 덮임 29.7%) | **2,354** |
| MPC 로 판정에서 제외된 절점 | 29.7% | **10.98%** (97,728 / 890,007) |
| 판정대상 비율 | — | 76.96% |
| 최대변위 | 4.19 mm | **4.1663 mm** (-0.6%) |
| 구조 최대 | 323.9 MPa | **493.1 MPa** (제외 영역이 줄어 더 많은 본체가 판정에 들어옴) |
| 전체 소요 | ccx 220초 | 전체 405초(국부 재해석 6회 포함) |
| CAD 접촉쌍 vs 메시 접촉쌍 | — | CAD 259 / 메시 267 / 공통 256 (CAD만 3, 메시만 11) |
| 씨앗점 | — | 3,425점 (격자 25mm, 34쌍은 3점 확보를 위해 격자 세분) |
| 씨앗→절점 겹침(충돌) | — | 507 (14.8%) |

**순수 구조 후보(구속에서 떨어진 본체) = 0건.** 상위 8개가 모두 '특이점 의심' 이고,
가장 가까운 용접 구속까지 0.7~4.0mm 다. MPC 덮임이 29.7% → 11.0% 로 내려갔는데도
후보 자리 자체가 용접 접합부 바로 위다 — 즉 "용접 MPC 가 가려서 안 보였다" 가 아니라
**이 기계에서 응력 상위 자리가 실제로 용접 접합부**라는 뜻이다.

## 2단계 — 적응형 국부 재해석 (서브모델링)

영역 선택: 후보 중심에서 경계상자 거리순으로 **부재 12개**(상한 25 → 12 로 내림).
경계: 영역 밖과 잇던 **CAD 용접 씨앗점**마다 최근접 절점 1개에 전체 해석의 변위를
3방향 강제(사면체 무게중심 보간, 못 찾으면 최근접 절점 대체).

| 후보 | 단계 | 절점 | 부재(메시) | 요소 mm | 묶인절점 | 경계강제 절점 | 보간(사면체/최근접) | 변위 mm | 후보자리 MPa | ΣF·u Nmm | 경계단면력 전체/국부 N | 어긋남 % | 초 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | 16,627 | 7/12 | 21.29 | 95 | 145 | 142/3 | 2.2344 | 2877.86 | 26,722 | 8,175 / 27,289 | 274.7 | 8.9 |
| 1 | 2 | 295,677 | 8/12 | 8.46 | 204 | 146 | 141/5 | 2.2355 | 18.68 | 21,227 | 8,175 / 25,257 | 252.0 | 55.8 |
| 2 | 1 | 16,627 | 7/12 | 21.29 | 95 | 145 | 142/3 | 2.2344 | 2877.86 | 26,722 | 8,175 / 27,289 | 274.7 | 8.8 |
| 2 | 2 | 295,677 | 8/12 | 8.46 | 204 | 146 | 141/5 | 2.2355 | 18.68 | 21,227 | 8,175 / 25,257 | 252.0 | 55.0 |
| 3 | 1 | 19,140 | 11/12 | 30.66 | 227 | 350 | 257/93 | 3.3540 | 257.44 | 4,207,523 | 119,438 / 1,994,849 | 1764.1 | 5.4 |
| 3 | 2 | 262,989 | 12/12 | 11.19 | 525 | 468 | 395/73 | 3.3540 | 436.79 | 373,361 | 119,438 / 13,614 | 89.0 | 39.8 |

## 3단계 — 후보별 수렴 자동 판정

| 후보 | 분류(전체해석) | 판정 | 사유 |
|---|---|---|---|
| 1 | 특이점 의심 | **판정 불가** | 후보 부재 67번이 국부 메시에서 형상 처리 실패 — 이 자리 응력을 잴 수 없다 |
| 2 | 특이점 의심 | **판정 불가** | 같음(부재 67번) |
| 3 | 특이점 의심 | **판정 불가** | 후보 부재 52번이 국부 메시에서 형상 처리 실패 |

## 못 넘은 벽 (숫자로 기록 — 조정으로 덮지 않는다)

1. **경계 강제변위가 전체 해석의 단면력을 재현하지 못한다.** 잘린 접합면을 지나던
   힘이 전체 8,175N 인데 국부에서 25,257N(어긋남 252%), 후보3 은 119,438N vs
   13,614N(89%). 원인 후보: ① 영역 안 부재의 20~40%가 형상 실패로 빠져 강성이
   다르다 ② 씨앗점마다 절점 1개만 강제하므로 점 하나에 힘이 몰린다.
   → 경계 강제의 타당성은 **아직 확인되지 않았다.**
2. **묶인절점이 단계마다 달라진다** (95 → 204, 227 → 525). 씨앗점 자체는 CAD 로
   고정되지만, 단계마다 **메시에 성공한 부재 집합이 달라져**(7 → 8, 11 → 12)
   씨앗 쌍 수가 172 → 282, 423 → 588 로 변한다. 1단계의 목표(묶음 수 고정)는
   '같은 부재가 전부 메시에 성공할 때만' 성립한다.
3. **후보 부재 자체가 국부 메시에서 죽는다**(67번·52번). 수리 사다리를 써도 CAD 가
   열린 부품은 복구되지 않는다. 이 세 후보는 그래서 전부 판정 불가다.
4. 후보 1·2 는 사실상 같은 자리(9mm 간격)라 같은 영역·같은 결과가 나온다.
   상위 N 개를 그냥 쓰면 같은 자리를 두 번 계산한다.

---

# 결함 5건 수리 기록 (2026-10-11, 화면 실측)

## 가장 중요한 정정 — "형상 처리 실패" 는 오진이었다

1~3단계 기록의 "후보 부재 67번·52번이 국부 메시에서 형상 처리 실패" 는 **틀린 사유**였다.
국부 영역 12부재 × 2단계를 전수 확인한 결과 탈락 사유 10건이 **전부 '절점 예산 초과'**
였고 형상 실패는 0건이다. 후보 부재는 두 단계 모두 메시에 성공한다.

진짜 원인은 둘이었다.
1. `local_refine` 이 `_orig_nos` 를 안 넘겨 국부 해석의 부품번호가 1..12 로 새로 붙었다.
   후보의 전체 부품번호(51번)와는 **절대 일치할 수 없어** `cand_parts_in_mesh` 가 항상
   비었고, 코드는 그것을 '형상 처리 실패' 라는 문장으로 적었다. 확인 없이 단정한 문장이
   기록으로 남아 다음 세션을 엉뚱한 곳으로 보냈다.
2. 국부 경로는 `_bulk` 가 아니라 PER_CAP 대신 `per = 총예산 × 부피비` 로 쪼개지는데,
   1단계 총예산 8만을 12부재가 나누면 작은 부재 몫이 바닥(400)까지 내려가 가장 성긴
   메시조차 못 들어간다. 단계마다 그 경계가 달라져 메시 성공 부재가 7→8, 11→12 로 변했다
   (= 결함 2 '묶음 수가 변한다' 의 원인도 바로 이것이었다).

## 결함별 전 / 후

| 결함 | 전 | 후 |
|---|---|---|
| 1. 국부 부재 누락 | 7/12 · 8/12 · 11/12 · 12/12 | **12/12 (3후보 × 2단계 전부)** |
| 2. 씨앗→절점 충돌 | 507건 (14.8%) | **23건 (0.67%)** — 두 번째 최근접 절점 배정 |
| 2. 단계 간 묶인절점 | 95→204, 227→525 (2.2배) | **206→206 / 551→560 / 179→177 (최대 ±1.6%)** |
| 3. 보간 최근접 대체 | 2~27% | **0% (전부 사면체 보간 또는 면 위 투영)** |
| 3. 경계 힘 ±10% | 89~1764% 어긋남 | **달성 못 함 — 아래 참조(기준 자체가 성립 불가)** |
| 4. 후보 중복 | 후보 1·2 가 9mm 간격, 같은 영역 2회 계산 | **8개 → 6개로 합침(문턱 29.2mm = 요소 9.7×3)** |
| 5. 수렴 판정 | 3후보 전부 '판정 불가' | **특이점 확정 1 / 미수렴(판정 유보) 2 — 판정 불가 0** |

## 결함 3 — ±10% 는 이 방식으로 성립할 수 없다 (통제실험)

후보1 영역에서 씨앗(경계 강제 절점) 수만 바꾸고 나머지는 한 글자도 안 바꿨다.

| 강제 절점 | 207 | 107 | 58 |
|---|---|---|---|
| 후보 자리 응력 | 970.56 | 964.66 | 966.97 MPa |
| Σ강제반력 | 20,525 | 481 | 24 N |
| 컴플라이언스 | 68,532 | 29,052 | 8,549 N·mm |

(전체 해석의 같은 단면 내력은 16,208N 로 고정)

**읽는 법:** 강제 절점에서의 반력 합은 '잘린 단면을 지나는 힘' 이 아니다. 절점마다
3방향을 모두 지정하면 서로 상쇄하는 구속력이 절점 수에 비례해 끼어든다 — 그래서 절점을
1/3.6 로 줄이면 합이 20,525N → 24N 으로 무너진다. 즉 ±10% 게이트는 변위 강제 서브모델
에서는 **정의상 성립할 수 없는 기준**이다. 숫자를 맞추려 조정하지 않고 기준을 폐기한다.

대신 확인된 것: **후보 자리 응력은 강제 절점 수를 3.6배 바꿔도 ±0.6%** 다. 경계 이산화가
후보 응력을 오염시키지 않는다 — 수렴 판정에 필요한 성질은 이것이고, 이것은 충족된다.
원인 분리도 끝났다: 부재 누락(12/12 성공)과 보간(최근접 대체 0%)은 원인이 아니다.

## 수렴 사다리를 '절점 예산' 에서 '요소 크기' 로 바꾼 이유

예산을 8배로 올려도 메시가 안 변했다. `build_tet_mesh` 에 ① 표면삼각형>2000 이면 `-p`
결과를 그대로 반환하는 단축로 ② `h = max(벽두께/1.2, 예산h)` 하한이 있어 CAD 부재는
예산과 무관하게 같은 메시가 나온다. 그 결과 1단계 요소 5.5mm → 2단계 8.4mm 로 **거꾸로**
굵어졌다. '요소를 절반으로 줄였다' 가 전제인 수렴 판정이 무의미했다.
→ tetgen 체적상한으로 요소 크기를 직접 지정(2h → h)하고, 세분화는 **후보 부재에만** 건다
(12부재 전체를 깎으면 절점 234만 = 100만 금지 위반). 둘레는 두 단계 동일 메시라
경계조건·둘레 강성이 안 변하고 후보 자리 요소만 절반이 되는 깨끗한 비교가 된다.

또 하나 잡은 거짓 판정: 후보 자리 응력을 반경만으로 고르면 둘레의 **안 깎은** 부재가
최대값을 차지해 후보3 이 157.82 → 157.82 로 '수렴' 이라고 나왔다. 후보 부재 위 절점만
쓰도록 고치자 34.0 → 66.7 MPa (+95.8%) 로 드러나 '특이점 확정' 이 됐다.
최대변위도 판정에서 뺐다 — 서브모델의 최대변위 절점은 경계 강제 절점이라 전체 해석 값이
그대로 되돌아온다(두 단계 소수 4자리까지 동일). 그것을 '0% 변했으니 수렴' 의 근거로
적는 것은 계산 안 한 것을 표시하는 짓이다.

## 최종 판정 (화면 실측 — 전체 890,373절점 / 묶인절점 2,561 / 변위 3.8843mm / 구조최대 442.2MPa)

### 3후보 x 2단계 전체 표 (화면 최종 실행 — 증거 사진과 같은 회차)

| 후보 | 단계 | 절점 | 부재 | 묶인절점 | 변위 mm※ | 후보자리 MPa | 후보부재 실제 요소 mm | ΣF·u N·mm | 경계반력 전체/국부 N※※ |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | 383,574 | 12/12 | 206 | 1.9285 | 1,020.19 | 8.4 | 75,292.8 | 16,982 / 21,558 |
| 1 | 2 | 475,493 | 12/12 | 206 | 1.9285 | 1,115.54 | 7.7 | 75,230.3 | 16,982 / 21,588 |
| 2 | 1 | 258,168 | 12/12 | 551 | 3.2842 | 586.15 | 13.5 | 364,486 | 126,995 / 15,478 |
| 2 | 2 | 462,066 | 12/12 | 560 | 3.2842 | 513.58 | 7.4 | 344,896 | 126,995 / 11,811 |
| 3 | 1 | 215,312 | 12/12 | 179 | 3.2842 | 35.70 | 8.1 | 54,458.8 | 113,092 / 3,953 |
| 3 | 2 | 221,607 | 12/12 | 177 | 3.2842 | 68.17 | 6.2 | 54,403.2 | 113,092 / 3,965 |

전체 해석: 절점 890,373 / 묶인절점 2,561 / 씨앗 3,449(충돌 23) / 부재 129 해석 · 17 제외 /
변위 4.0843mm / 구조최대 464.2MPa.

※ **변위는 판정에 쓰지 않는다.** 서브모델의 최대변위 절점은 경계 강제 절점이라 전체
해석 값이 그대로 되돌아온다(두 단계 소수 4자리까지 동일). 그래서 '특이점 = 응력은 발산,
변형은 수렴' 의 '변형은 수렴' 쪽 근거는 변위가 아니라 **ΣF·u(후보3 0.10% 변화)** 다.

※※ 경계반력 두 값은 **일치율을 내지 않는다** — 위 통제실험대로 강제 절점 수에 딸린
값이라 비율이 뜻을 갖지 못한다. 숨기지 않고 두 값 그대로 적는다.

| 후보 | 합쳐진 후보 | 후보응력 변화 | ΣF·u 변화 | 요소 실제 축소비 | 판정 |
|---|---|---|---|---|---|
| 1 | 2개(29mm 안) | +9.35% | 0.08% | 1.09배 | **미수렴(판정 유보)** |
| 2 | 0 | -12.38% | 5.37% | 1.83배 | **미수렴(판정 유보)** |
| 3 | 0 | **+90.95%** | 0.10% | 1.30배 | **특이점 확정** |

**요소는 '절반' 이 안 됐다.** 목표는 19.45 → 9.73mm(2배)였지만 체적상한은 벽두께가 더
빡빡하면 구속력이 없어 실제 축소비는 1.09~1.83배다. 이 숫자를 '2배' 로 적지 않는다.
오히려 후보3 은 1.30배만 가늘게 했는데 응력이 90.95% 커졌으므로 발산 근거가 더 강하다.
**후보1 은 축소비가 1.09배뿐이라 '미수렴' 이 메시 때문인지조차 아직 못 가린다 — 판정 유보가
정확한 상태다.**

**묶인절점이 후보2·3 에서 완전히 같지 않은 이유**(551→560, 179→177, 최대 ±1.6%):
후보 부재는 **일부러 세분화**하므로 그 부재의 표면 절점 위치가 바뀌고, `build_weld_equations`
의 거리 기준 탈락 수가 따라 변한다. 둘레 부재는 두 단계 동일 메시다. 후보1 은 206→206 으로
정확히 같고, 후보3 의 +90.95% 는 ±1.6% 를 압도하므로 판정이 뒤집히지 않는다.

### 아직 남은 흔들림 — 같은 설정 두 번 실행이 5% 다르다 [미해결]
설정을 하나도 안 바꾸고 화면에서 두 번 돌렸더니
구조최대 442.2 → 464.2MPa (+5.0%), 변위 3.8843 → 4.0843mm (+5.1%) 였다.
절점(890,373)·묶인절점(2,561)·씨앗(3,449)·충돌(23)은 **완전히 같다**. 남는 설명은
`grabMachine` 의 BFS 가 `allParts()` 순서에 딸려 부재 담기는 순서가 바뀌고, 그 결과
절점 번호와 MPC 배정이 미세하게 달라지는 것이다. **판정은 두 회차 모두 같았다**
(미수렴 2 / 특이점 확정 1). 수치를 고정하려면 부재 순서를 부품번호로 정렬해야 한다 —
다음 숙제로 적어 둔다. 지금은 숫자를 '±5% 흔들린다' 고 밝히고 쓴다.

## 두 가지 '판정' 을 헷갈리지 말 것

화면에는 성격이 다른 두 개의 판정이 있다.

| | 이번 결과 | 뜻 |
|---|---|---|
| **수렴 배지**(이번 작업 대상) | 특이점 확정 1 / 미수렴 2 — **판정 불가 0** | 후보 자리 응력이 메시에 수렴하는가 |
| **전체 결과 배너** | 여전히 **판정 불가** | 전체 해석 결과로 안전을 말할 수 있는가 |

전체 배너가 판정 불가인 사유는 **부품 17개가 해석에서 빠졌기 때문**이며, 이번 수리와
무관한 별개의 숙제다. 오히려 10-10 기준(126 해석 / 20 제외)보다 나아졌다(129 / 17).
증거 사진 1장만 보고 '실패' 로 읽지 말 것.

증거 화면: `_fea_수렴판정_20261011_1_전체품질해석.jpg` / `_2_특이점확정배지.jpg` /
`_3_미수렴배지_후보합침.jpg`

---

# 고칠 것 1 — 실행 재현성 (2026-10-11, 헤드리스 통제실험)

## 먼저 한 일: '같은 설정 두 번이 5% 다르다' 의 원인을 가리는 통제실험

종전 기록은 원인을 `grabMachine` 의 부재 담기 순서로 **추정**만 해 두었다. 추정으로
코드를 고치지 않기 위해 시험대(`_fea_국부시험.py`)에 두 모드를 넣었다.

| 모드 | 무엇을 재는가 | 한계 |
|---|---|---|
| `repeat N` | 같은 요청(`last_request.json`)을 N 회 — **솔버가 결정론적인가** | 순서를 고정해 놓고 재므로 순서 의존성은 구조적으로 못 본다 |
| `shuffle N` | **부품 순서만** 섞어 N 회(형상·좌표·조건 한 글자도 안 바꿈) — 순서 의존성 | — |

`repeat` 는 고치기 **전부터** 소수점 아래까지 같았다(구조최대 464.189308 두 번).
즉 ccx 는 결정론적이고, 5% 는 **브라우저가 보내는 부품 순서**에서 온 것이 맞았다.

## 진짜 경로 (추정이 아니라 코드로 확인)

부품 순서 → `find_weld_pairs` 의 `i<j` 루프 순서 → `weld_list` 순서 →
`build_weld_equations` 를 부르는 순서 → **`fixed_set` 누적('한 절점은 최대 한 번만
종속')** → 어느 절점이 용접 MPC 종속이 되는지가 바뀐다.
절점 수·묶인절점 수·씨앗 수는 그대로인데(= 종전 기록이 맞다) 배정만 달라지므로
숫자가 5% 움직였다. 두 번째 경로는 씨앗점이었다: `weld_seeds_cad` 의 `cloud` 가
`i<j` 순서로 쌓이므로 같은 접합면에서도 i/j 역할이 뒤바뀌어 격자 대표점이 달라졌다.

## 고친 곳 (순서 의존성 자체를 없앴다 — 숫자를 맞추는 조정이 아니다)

1. `fab_fea.js grabMachine` — 성분을 **안정 키**(이름 + 경계상자 최소점 + 삼각형 수)로
   정렬해 클릭 위치와 무관하게 같은 순서를 보낸다.
2. `fea_server.py` MPC 루프 전에 `weld_list` 를 **접촉영역 중심 좌표**로 정렬.
3. `find_weld_pairs` 의 종속 방향 선택에서 접촉절점 수가 **동수일 때** 부품번호가
   아니라 좌표합으로 가른다.
4. `weld_seeds_cad` 의 `cloud` 를 좌표 사전식 정렬 → 격자 대표점이 i/j 역할과 무관.
5. `local_refine` 의 `seed_pairs.items()` 를 부품번호 쌍으로 정렬.

## 결과 — 부품 순서만 섞은 3회 (화면이 아니라 헤드리스 실측)

| 회차 | 절점 | 묶인절점 | 부재 | 변위 mm | 구조최대 MPa | 컴플라이언스 N·mm |
|---|---|---|---|---|---|---|
| 원본 순서 | 890,373 | 2,560 | 129(실패 6) | 3.980203 | 448.351913 | 58,197.575 |
| 섞음 seed1001 | 890,373 | 2,560 | 129(실패 6) | 3.980212 | 448.351867 | 58,197.627 |
| 섞음 seed1002 | 890,373 | 2,560 | 129(실패 6) | 3.980202 | 448.351427 | 58,197.568 |

**최대 상대편차: 변위 2.3e-6 / 구조최대 1.1e-6 (종전 5.0%).**
후보 좌표 6개 상위 3개는 세 회차가 소수 둘째자리까지 같다 → **후보 순위도 동일**.

남은 1e-6 은 고칠 수 없고 고칠 필요도 없다. 부품 순서를 섞으면 절점 번호(`n0`)가
바뀌고 희소행렬의 행·열 순서가 바뀌어 **ccx 안의 부동소수 덧셈 순서**가 달라진다.
파이썬에서 무엇을 더 정렬해도 이것은 남는다. 여기서 멈춘다(철칙 제4조).

## ★ 확정 숫자가 이동했다 — 숨기지 않고 적는다

| | 전 | 후 |
|---|---|---|
| 구조최대 | 464.2 MPa | **448.4 MPa** |
| 최대변위 | 4.0843 mm | **3.9802 mm** |
| 묶인절점 | 2,561 | **2,560** |

같은 해석이고 같은 메시다. **용접 MPC 종속절점 배정이 달라졌을 뿐**이다. 순서를
고정한 대가로 확정 숫자가 3.4% 이동했다. 종전 464.2 는 '그 클릭 순서에서 나온 값'
이었고 이제는 클릭과 무관한 값이다. 위 표의 숫자가 새 기준이다.

selftest PASS (판재 처짐 -7.43% / 각파이프 처짐 -6.99% · 굽힘응력 +2.15%).

---

# 고칠 것 2 — 세분화 비율 보장 (2026-10-11, 시험대 실측)

## 왜 축소비가 1.09배밖에 안 됐나 (원인 규명 — 숫자 조정 아님)

1단계 목표 19.45mm 를 걸었더니 실제는 **8.4mm** 가 나왔다. tetgen 체적상한(`-a`)은
**상한**이라, 표면 삼각형과 품질조건이 더 빡빡하면 구속력이 전혀 없다.
그런데 2단계 목표를 '1단계 목표의 절반'(9.73mm)으로 걸었으니, 이미 8.4mm 인 메시에는
아무 영향이 없었다 — 그것이 축소비 1.09배의 전부다.

→ 목표를 **'1단계 목표의 절반' 이 아니라 '1단계 실측 h 의 절반'** 으로 잡는다.
  `-a` 는 상한이므로 실측보다 작은 목표는 **반드시** 구속력을 가진다.

## 되돌린 시도 2건 (실패도 기록한다)

1. **둘레 부재에 성긴 h_target 걸기** — 100만 절점 안에서 후보를 깎으려면 둘레 예산을
   넘겨받아야 한다고 보고 둘레에 19.45mm 를 걸었다. **거꾸로 폭발했다**: tetgen 은
   `-a` 를 주면 품질조건을 기본 적용하므로 둘레가 305,806 → **761,728절점**,
   요소 8.4 → **1.2mm** 가 됐다. 되돌렸다.
2. **메시 전 추정으로 영역 부재 수 줄이기** — 추정식을 세울 수 없었다. 같은 영역
   12부재에서 표면삼각형 기준(3.25×tris)은 실측의 **0.17~1.44배**, 부피·벽두께 기준은
   **0.17~156배**로 틀렸다. 성긴 부재(53번 24삼각형 → 28,819절점)는 품질조건이,
   촘촘한 부재는 `-p` 가 절점을 정하기 때문이다. 맞지도 않는 식으로 영역을 깎는 것은
   '원인 없이 숫자 바꾸기' 라 쓰지 않는다. 영역은 가까운 12부재 그대로 두고,
   2단계가 상한에 들어가는지는 **1단계 실측 절점 수**로만 판정한다.

   ※ 이 시도에서 얻은 것: 후보2 의 1단계 후보자리 응력이 둘레 메시만 바꿨을 때
     **555.91 → 304.35MPa (-45%)** 로 움직였다(후보3 은 111.38 → 110.33 으로 안정).
     즉 **절대값은 둘레 메시에 딸려 있고**, 그래서 판정은 절대값이 아니라
     단계 간 **변화율**로만 내려야 한다는 근거가 하나 더 생겼다.

## 3후보 × 단계 (시험대 실측 — 전체 890,373절점 / 묶인절점 2,560 / 변위 3.9802mm / 구조최대 448.35MPa)

| 후보 | 단계 | h 목표 mm | 절점 | 후보부재 실측 h mm | 목표 못맞춘 부재 | 후보자리 MPa | ΣF·u N·mm |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 19.45 | 425,446 | 7.79 | 없음 | 974.72 | 68,248.8 |
| 1 | 2 | — (멈춤) | — | — | — | — | — |
| 2 | 1 | 19.45 | 321,384 | 13.50 | 없음 | 555.91 | 344,256.5 |
| 2 | 2 | **7.11** | 857,734 | **5.43** | 없음 | 1,110.49 | 322,527.3 |
| 3 | 1 | 19.45 | 254,905 | 13.50 | 없음 | 111.38 | 55,832.5 |
| 3 | 2 | **6.75** | 873,719 | **5.18** | 없음 | 482.80 | 51,339.0 |

## 판정 (전 / 후)

| 후보 | 축소비 전 | 축소비 후 | 응력 변화 전 | 응력 변화 후 | 판정 전 | 판정 후 |
|---|---|---|---|---|---|---|
| 1 | 1.09배 | **불가** | +9.35% | — | 미수렴(판정 유보) | **판정 불가(절점 상한)** |
| 2 | 1.83배 | **2.49배** | -12.38% | **+99.76%** | 미수렴(판정 유보) | **특이점 확정** |
| 3 | 1.30배 | **2.61배** | +90.95% | **+333.47%** | 특이점 확정 | **특이점 확정** |

**축소비 ≥1.8 달성: 3후보 중 2후보.** 두 후보 모두 `h_hit` 이 전 부재 통과(목표 못맞춘
부재 0개)이므로 이 축소비는 '걸었다' 가 아니라 **'실제로 그렇게 됐다'** 다.

**후보1 은 달성 못 했다 — 숫자로 왜인지 적는다.** 후보 부재(51번)가 1단계에서
77,768절점이고, 변을 1.8배만 가늘게 해도 그 부재 하나가 약 816,000절점이 된다.
둘레 347,678절점을 더하면 약 **1,164,055절점**으로 **100만 절점 금지선**을 넘는다.
100만 금지는 축소비 목표보다 상위 제약이므로 넘지 않고 멈춘다. 이것은 조정으로
해결할 문제가 아니라 '이 후보는 이 방식으로는 못 잰다' 는 **측정된 한계**다.
(영역을 줄여도 안 된다 — 후보 부재 하나가 상한의 86%를 쓴다.)

**후보1 의 판정이 '미수렴' → '판정 불가' 로 바뀐 것은 후퇴가 아니다.** 종전 '미수렴'은
축소비 1.09배에서 나온 것이라 아무것도 증명하지 못했다. 재지 못했으면 '판정 불가' 가
정확한 표시다.

**후보2 는 부호가 뒤집혔다**(-12.38% → +99.76%). 종전의 음수는 축소비가 실제로는
없었기 때문에 나온 잡음이었다.

구현: 단계 사다리를 적응식으로(`LOCAL_MAX_STAGES=3`), 다음 목표 = 이번 실측 h ÷ 축소비,
축소비는 들어가는 가장 큰 값(2.0 → 1.9 → 1.8)을 고른다. 2단계 절점 예측은
**실측 과증가 계수 하한**(이상 8배 × 1.8 = 14.4배 — 실측 14.2~17.5배)을 쓰고,
예측이 어긋나 상한을 넘은 단계는 판정에서 뺀다(`over_ceiling`).
`run_fea` 의 하드 벽을 `LOCAL_NODE_CEIL/1.3` 로 넘겨 78만 → 95만으로 올렸다
(종전 78만 벽 때문에 2단계가 '부품이 너무 많습니다' 로 통째로 실패했다).

selftest PASS.

---

# 고칠 것 3 — 제외 17부품 (2026-10-11, 실측)

## 먼저: 17개의 제외 사유를 실제로 뽑았다 (추측 금지)

계획서가 짐작했던 사유 목록(자기교차 / 열린면 / 예산)은 **하나도 없었다.**
서버가 실제로 남긴 `failed_parts` / `auto_dropped` 를 그대로 세면 이렇다.

| 묶음 | 수 | 사유 (서버 원문) |
|---|---|---|
| 두께 0 면 형상 | **5** | `두께가 0인 면 형상입니다(크기 … mm) — 속을 채울 수 없어 해석 대상이 아닙니다` |
| 형상이 없음 | **1** | `정점이 3개뿐 — 형상이 없습니다` |
| 연결 불가 | **11** | `고정된 부재와 용접으로 이어지지 않아 자동 제외` |
| 자기교차 / 열린면 / 예산 | **0** | — (짐작이었다) |

| 번호 | 이름 | 크기 mm | 사유 |
|---|---|---|---|
| 29 | Group44 | 300 × 0 × 300 | 두께 0 면 형상 |
| 100~103 | WINCH_BASE_PLATE_25T_1 (4개) | 27.9 × 30 × 0 | 두께 0 면 형상 |
| 85 | Group74 | 0 × 0.06 × 2.25 | 정점 3개 = 삼각형 1개 |
| 11, 12, 27, 43, 117, 138~143 | G_2110DN_0020_001_1/2 · Group13 · G_2110DN_0019_002_2 · Group73 · Group_89_1/2 · Group_86_1/2 · Group80 · Group_90_1 | — | 연결 불가 |

## 수리 사다리가 왜 안 먹었나 (두께 0 묶음)

사다리(A manifold3d / B 정리 / C 구멍메움 / D 메움+manifold3d / H 볼록껍질)는
**부피가 0 인 형상에는 원리적으로 무용하다.** 무엇을 해도 부피가 0 이고, 볼록껍질조차
납작한 판이 된다. 게다가 `repair_for_tet` 은 입력 V 의 bbox 최소변 `emin` 으로 두께
게이트 상한(`emin×1.2+1`)을 잡는데, 납작한 판은 `emin=0` 이라 상한이 2.2mm 가 되어
**어떤 두께의 압출도 거부한다**. → 그래서 압출은 반드시 `repair_for_tet` **앞**에서
해야 하고, 압출한 형상을 '원본' 으로 넣어야 게이트가 맞는다.

## 구현 — 판두께를 추정해 압출 (라벨 필수)

'bbox 최소변' 은 이 경우에 **쓸 수 없다** — 바로 그 변이 0 이기 때문이다.
1순위 **경계상자가 맞닿는(30mm 여유) 이웃 부재들의 실측 벽두께 중앙값**,
2순위 기계 전체 부재 벽두께 중앙값. 부품 **이름**('25T')은 근거로 쓰지 않는다.

| 번호 | 이름 | 추정 두께 | 근거 |
|---|---|---|---|
| 29 | Group44 | **10.57mm** | 이웃 부재 9개 벽두께 중앙값 |
| 100 / 101 | WINCH_BASE_PLATE_25T_1 | **13.16mm** | 이웃 부재 3개 중앙값 |
| 102 / 103 | WINCH_BASE_PLATE_25T_1 | **12.48mm** | 이웃 부재 3개 중앙값 |

**[CEO확인]** 100~103 번의 부품 이름은 `25T`(25mm)인데 이웃 벽두께 추정은 12~13mm 다.
이름을 근거로 쓰지 않기로 했으니 추정값을 썼지만, 실제 판두께가 25mm 라면 바로잡아야
한다. 화면에 '두께 추정 Nmm (도면값이 아니라 이웃 부재 벽두께로 추정 — 확인 필요)' 로
노란색으로 적어 두었다.

**85번 Group74 는 일부러 살리지 않았다.** 0 × 0.06 × 2.25mm 삼각형 1개다 — 두 변이
동시에 찌그러진 CAD 찌꺼기이고 부재가 아니다. 압출하면 '살렸다' 고 적을 수는 있지만
있지도 않은 부재를 표시하는 짓이다. `SHEET_MIN_SPAN_MM=5.0` 게이트로 거부하고
사유를 그대로 남긴다.

## 결과

| | 전 | 후 |
|---|---|---|
| 부재 해석 | 129 | **134** |
| 형상 처리 실패 | 6 | **1** (85번만) |
| 연결 불가 자동 제외 | 11 | **11** (안 바뀜) |
| **제외 합계** | **17** | **12** |
| 절점 | 890,373 | 894,551 |
| 묶인절점 | 2,560 | **2,647** |
| 변위 | 3.9802mm | **3.8689mm** |
| 구조최대 | 448.35MPa | **434.20MPa** |

**목표(5 이하)는 달성 못 했다 — 12 다.** 남은 12 중 11 이 '연결 불가' 이고, 이것은
두께 0 묶음과 전혀 다른 문제다. 되살린 판 5개가 그 11개의 '다리' 였기를 기대했지만
**연결 불가 수는 11 → 11 로 하나도 줄지 않았다**(측정값이다). 즉 그 11개는 되살린
판과 무관하게 떨어져 있다. 이건 다음 숙제로 따로 잡아야 한다.

## 전체 배너 — '판정 불가' 한 문장을 '실제 상태' 로

종전에는 막는 조건이 무엇이든 머리글이 늘 같은 문장이었다. 그래서 '부재가 빠졌다' 와
'평형이 안 맞는다' 와 '수렴을 증명 못 했다' 가 같은 문장으로 보였다.
→ 막는 조건 목록 중 **가장 센 것**이 머리글을 정한다(숫자는 하나도 안 건드린다).

| 막는 조건 | 머리글 |
|---|---|
| 평형 불일치 / 반력 어긋남 | 계산이 평형을 못 맞췄습니다 — 이 결과는 쓸 수 없습니다 |
| 구조 기준을 쓸 수 없음 | 판정 불가 — 구조 기준을 세울 수 없습니다 |
| 절점 N% 제외 | 판정 불가 — 결과의 상당 부분이 판정에서 빠졌습니다 |
| 부품 N개 해석 제외 | **부재 일부가 빠졌습니다 — 전체 안전 미확정** |
| 수렴 미증명 | **수렴 미증명 — 안전/위험 미확정** |

또 하나 고쳤다: 종전 `verdictBlock` 은 과거 시험기록(`MESH_CONV`)이 이 모델과 맞을
때만 '메시 미수렴' 을 적었다. 그래서 **이 해석에서 국부 재해석을 돌려 '미수렴/판정
불가' 가 나와도 배너는 그 사실을 말하지 않았다.** 이제 `res.local` 의 판정을 보고
'후보 N/M 곳이 메시 수렴 미증명' 을 막는 조건에 넣는다.

이번 결과(제외 12 + 후보1 판정 불가)에서 배너는
**전: '판정 불가 — 이 결과로 안전을 말할 수 없습니다'**
**후: '부재 일부가 빠졌습니다 — 전체 안전 미확정'** 이 된다.
수렴 문구가 아니라 부재 누락 문구가 뜨는 것이 맞다 — 부재가 빠지면 하중 경로 자체가
다를 수 있어 수렴보다 상위의 문제다. 수렴 문구는 부재 누락이 0 이 될 때 나온다.

selftest PASS.

---

# 브라우저 증명 (2026-10-11) — 화면이 실제로 그렇게 말한다

조건: 블럭 `500PRO-R 수정안 20260917`(293부품) → 3D 에서 부재 하나 클릭 →
`이 기계 전체 담기`(146부재) → `전체 품질메시(정밀)` ✓ + `후보 국부 재해석` ✓ →
`기계 전체 해석 실행`. 하중은 화면 기본 프리셋(붐·마스트 조립 상태, 적용 55,543N).

## 판정 1 — 실행 재현성 (이번 작업의 판정 기준)

**헤드리스 같은 설정 3회 → 전부 동일.**

| 회차 | 절점 | 묶인절점 | 변위 mm | 구조최대 MPa |
|---|---|---|---|---|
| 1 | 894,551 | 2,393 | 571.270615 | 2486.383292 |
| 2 | 894,551 | 2,393 | 571.270615 | 2486.383292 |
| 3 | 894,551 | 2,393 | 571.270615 | 2486.383292 |

항목별 동일 여부: 절점·요소·묶인절점·씨앗·부재수·변위·구조최대·첨두·컴플라이언스·
**후보 좌표** 전부 `true`. → **후보 순위까지 소수점 이하 동일.**

**그리고 화면 실행 결과가 이 숫자와 글자 하나까지 같다**(571.270615 / 2486.383292 /
894,551 / 묶인절점 2,393). 종전에는 '화면에서 두 번 돌리면 5% 다르다' 였다.

※ 부품 순서를 일부러 섞은 시험(`shuffle 3`)은 고치기 전 5.0% → 고친 뒤 **1e-6** 이다
(이산 항목은 완전 동일). 남은 1e-6 은 절점 번호가 바뀌어 ccx 안의 부동소수 덧셈
순서가 달라지는 것으로 파이썬에서는 못 없앤다.

## 판정 2 — 세분화 비율 (화면 실측)

| 후보 | 1단계 후보부재 h | 2단계 후보부재 h | **실측 축소비** | 목표 못맞춘 부재 | 응력 변화 | 배지 |
|---|---|---|---|---|---|---|
| 1 | 3.95mm | 2.22mm | **1.78배** | 없음 | +13.87% | 미수렴(판정 유보) |
| 2 | 5.98mm | 2.18mm | **2.74배** | 없음 | **+98.84%** | **특이점 확정** |
| 3 | 4.5mm | 1.7mm | **2.69배** | 없음 | **+258.0%** | **특이점 확정** |

세 후보 모두 `h_hit` 전 부재 통과 — '걸었다' 가 아니라 **실제로 그렇게 됐다**.
배지 문구가 실측 축소비를 그대로 말한다:
`요소를 6.0mm → 2.2mm (2.74배) 로 줄였는데 이 자리 응력이 98.8% 더 커졌습니다`.
3단계(1/4)는 **0후보**가 도달했다 — 세 후보 모두 2단계 뒤 절점 상한(95만)에 걸렸다.

## 판정 3 — 제외 부품과 배너

화면: **부품 134개 해석 / 12개 제외(회색)** (종전 129 / 17).
**두께 추정 5개 — 81번 10.6mm · 140번 12.5mm · 141번 12.5mm · 142번 13.2mm ·
143번 13.2mm (도면값이 아니라 이웃 부재 벽두께로 추정한 값입니다 — 확인 필요)**
가 노란색으로 찍힌다.

배너 전 / 후:

| | 문구 |
|---|---|
| 전 | `판정 불가 — 이 결과로 안전을 말할 수 없습니다` (막는 조건이 무엇이든 항상 이 한 문장) |
| 후 | `판정 불가 — 결과의 상당 부분이 판정에서 빠졌습니다`<br>막는 조건: **절점 64% 제외 · 부품 12개 해석 제외 · 후보 1/3곳이 메시 수렴 미증명** |

이 하중 조건에서는 **절점 64% 제외**가 가장 센 조건이라 그 문구가 떴다.
'후보 1/3곳이 메시 수렴 미증명' 은 **이번에 새로 생긴 줄**이다 — 종전에는 국부
재해석이 '미수렴' 을 내도 배너가 그 사실을 말하지 않았다(과거 시험기록이 이 모델과
맞을 때만 적었다). 머리글은 막는 조건의 우선순위로 정해지며, 부재 누락이 0 이고
수렴만 남으면 `수렴 미증명 — 안전/위험 미확정` 이 뜬다.

증거 화면:
`_fea_수렴판정_20261011_v2_1_전체배너_두께추정.jpg`
`_fea_수렴판정_20261011_v2_2_배지1_미수렴.jpg`
`_fea_수렴판정_20261011_v2_3_배지2_특이점확정_274배.jpg`
`_fea_수렴판정_20261011_v2_4_배지3_특이점확정_269배.jpg`

---

# 연결 불가 복구 (2026-10-11) — 제외 12 → 5, 사유를 전부 실측으로 적는다

## 먼저 바로잡을 것 — '연결 불가 11개' 의 부품번호는 하중 조건마다 다르다

이 문서 앞부분에 적힌 연결 불가 목록(11·12·27·43·117·138~143)은 **붐 프리셋**
(옆으로 +Y, 변위 571mm) 으로 돌렸을 때의 목록이다. 머신 하중(바닥 6고정 / -Z / 3톤)
으로 돌리면 **같은 11개인데 부품이 다르다**: 47·49·50·77·90·115·117·118·119·120·121.
겹치는 것은 117 하나뿐이고, 앞 목록의 나머지는 머신 BC 에서는 **고정 덩어리(134부품)
안에 들어 있다**(실측). 고정점이 어디냐에 따라 '고정까지 이어지는가' 가 달라지므로
당연한 일이다.

근거: 머신 BC 로 돌린 기준 실행이 이 문서의 표와 **절점 894,551 · 묶인절점 2,647 ·
해석 134부품 · 제외 12** 로 정확히 같다. 즉 그 3.8689mm 실행은 머신 BC 였고,
부품번호 목록만 붐 프리셋 것이 섞여 적혀 있었다.

## 원인 — 떨어진 11개가 아니라, 끊긴 다리 3개였다

떠 있는 11부품은 서로 용접으로 이어진 **3덩어리**다.

| 덩어리 | 부품 | 고정 쪽으로 가는 다리 | 실측 표면간격 | 그때 상태 |
|---|---|---|---|---|
| A | 47·49·50 | 49↔18, 50↔18 | **2.920mm** | 씨앗 4·5개가 생겼는데 MPC 0개 |
| B | 77 | 77↔17 | **8.000mm** | 씨앗 0, 접촉쌍도 없음 |
| C | 90·115·117~121 | 90↔91 | **5.635mm** | 접촉쌍은 있는데 씨앗 0 |

(간격은 점↔삼각형 정확거리 실측. 47 은 자기 덩어리 밖 가장 가까운 부재가 62.3mm 라
다리 후보가 아예 없다.)

A 의 원인은 간격이 아니었다. MPC 생성 루프가 `weld_list`(메시 접촉쌍)만 도는데
이 쌍은 거기에 없어서(CAD 씨앗만 있는 쌍) **통째로 건너뛰어졌다**.

## 고친 것 — 다리 잇기(bridge_floating)

떠 있는 덩어리에 한해서만, 실측 표면간격 **10mm 이내**인 부품쌍을 그 쌍만
`간격+1mm` 로 씨앗을 다시 뽑아 용접 방정식을 만든다. **전역 tol(3.0mm)은 한 숫자도
안 건드린다** — 올리면 모델 전체의 묶음이 다시 정해져 기준값과 비교가 깨진다.

- 종속절점을 '씨앗점의 최근접 절점' 으로 고르지 않는다. 전체해석 메시는 요소가 수십
  mm 라 씨앗 최근접 절점도 상대 표면에서 멀어 방정식이 0개가 됐다. 겉면 절점 전부를
  후보로 주고 '상대 표면에서 간격+1mm 안' 인 절점만 묶는다(점↔삼각형 정확거리).
  메시 무관성은 '씨앗마다 후보 1개씩' 으로 유지한다.
- 상대면 선별에 '면 중심이 상자 안' 을 쓰지 않는다(면 하나가 수백 mm 라 빠뜨린다).

## 결과 (머신 BC 6고정/-Z/3톤, 146부품, 전체 품질메시)

| | 전 | 후 |
|---|---|---|
| 부재 해석 | 134 | **141** |
| 제외 | 12 | **5** |
| 절점 | 894,551 | 897,254 |
| 묶인절점 | 2,647 | 2,212 (+다리 3) |
| 변위 | 3.8689mm | **5.5261mm** |
| 구조최대 | 434.20MPa | **594.56MPa** |

변위·응력이 커진 이유는 **아직 가르지 않았다**. 측정된 사실만 적는다: 부재 +7,
묶인절점 -438, 변위 +43%. 부재가 늘면 보통 변위가 줄어드는데 늘었으므로, 부재 7개보다
'묶인절점이 438개 줄어든 것'(부품 구성이 바뀌면서 용접 쌍과 종속절점 경쟁이 달라진다)이
더 큰 원인일 수 있다. 숫자를 맞추려 추측을 적지 않는다 — 다음 숙제다.

다만 이은 다리가 숫자를 만들어 낸 것은 아니다(실측): 최대 변위 자리
(5503, 1993, 112)·구조최대 자리(2648, 3402, 179)·첨두 자리(5675, 3239, 1156) 가
전부 이어 붙인 덩어리(x 1892~2472, y 2998~3081, z 212~288) **밖**이다.

후보는 8곳이 잡혔고 **판정은 0곳이다** — 이번 실행은 국부 재해석을 끄고(local_refine 0)
돌렸다. 수렴 판정은 따로 돌려야 한다.

## 남은 제외 5개 — 전부 실측 사유

| 번호 | 이름 | 사유(실측) |
|---|---|---|
| 102 | Group74 | 정점이 3개뿐 — 형상이 없다 |
| 47 | G_2110DN_0019_002_2 | 10mm 안에 이을 이웃이 없다(가장 가까운 덩어리 밖 부재 62.3mm) |
| 49 | G_2110DN_0020_001_1 | CAD 간격 2.92mm. 그러나 겉면 절점↔상대 메시 최소 11.00mm |
| 50 | G_2110DN_0020_001_2 | 같음(11.00mm) |
| 77 | Group13 | CAD 간격 8.00mm. 겉면 절점↔상대 메시 최소 22.42mm |

49·50·77 은 **메시가 성겨서** 접합면 자리에 절점이 없다(49 의 겉면 모서리절점은 21개뿐).
중간절점까지 후보에 넣어도 11.00 → 9.19mm 로밖에 안 좁혀진다(`replay` 로 확인).
억지로 묶으려면 20~30mm 짜리 강체막대를 만드는 셈이라 **하지 않았다**. 이 셋은
'간격' 문제가 아니라 '메시 밀도' 문제이고, 해결하려면 그 부재들의 메시를 따로
촘촘하게 만들어야 한다 — 다음 숙제다.

## 화면 증명 (브라우저, 머신 프리셋 3톤)

블럭 `500PRO-R 수정안 20260917`(293부품) → 부재 클릭 → `이 기계 전체 담기`(146) →
`전체 품질메시(정밀)` ✓ → 전체 하중 `3톤 (29,400N)` → `기계 전체 해석 실행`.

화면 숫자가 헤드리스와 같다: **최대 변위 5.526mm · 구조 최대 594.6 MPa ·
부품 141개 해석 / 5개 제외 · 적용 하중 29,400N · 평형 검증 0.00%**.
(붐 프리셋이면 571mm 가 나온다 — 그 숫자가 보이면 프리셋을 잘못 고른 것이다.)

화면에 새로 적히는 두 줄:
- `용접 추정 1군데 — 90번↔91번 5.63mm(간격 추정 용접)` (노란색)
- `제외된 부품과 사유(실측)` — 5개 전부 위 표의 사유 그대로

배너: `부재 일부가 빠졌습니다 — 전체 안전 미확정` / 막는 조건 `부품 5개 해석 제외`.

증거 화면:
`_fea_연결복구_20261011_1_제외5개_사유실측.jpg`
`_fea_연결복구_20261011_2_배너_부재일부빠짐.jpg`
`_fea_연결복구_20261011_3_평형검증_변위5.526.jpg`


---

# 변위 +43% 원인 분리 (2026-10-11) — 통제실험. 세 요인이 아니라 한 가지였다

## 먼저 바로잡을 것 — '직전 변위 3.8689mm' 는 재현되지 않는다

다리 잇기 전 커밋(`816f189`)의 `fea_server.py` 를 그대로 꺼내 **같은 요청**
(머신 BC 6고정 / -Z / 3톤 / 146부품 / 전체 품질메시)으로 돌렸다.

| 무엇을 돌렸나 | 절점 | 묶인절점 | 부품 | 변위 mm | 구조최대 MPa |
|---|---|---|---|---|---|
| 816f189 (다리 잇기 전 코드) | 894,551 | 2,647 | 134 | **3.681431** | **413.882903** |
| HEAD + `DZW_FEA_NOBRIDGE=1` (다리만 끔) | 894,551 | 2,647 | 134 | **3.681431** | **413.882903** |
| HEAD 기준(다리 켬) | 897,254 | 2,212 | 141 | **5.526097** | **594.561248** |

두 가지가 동시에 확인된다.
1. 통제 스위치(`DZW_FEA_NOBRIDGE`)는 **다리 잇기 전 코드와 15자리까지 같다** —
   즉 이 스위치는 다리만 끄고 다른 것은 하나도 바꾸지 않는다(그 스위치를 안 쓴
   실행도 기준값 5.526097 / 594.561248 과 15자리 동일하다. 추가한 코드는 무해하다).
2. 이 문서에 적혀 있던 **'직전 변위 3.8689mm / 구조최대 434.20MPa' 는 816f189 를
   돌려도 안 나온다**(3.681431 / 413.882903). 그것은 더 앞선 코드의 숫자였다.
   따라서 **'+43%' 라는 수치 자체가 잘못된 기준에서 계산된 값이었다.**
   실측 증가율은 **변위 +50.1% / 구조최대 +43.6%** 다.

## (a)(b)(c) 세 갈래 통제실험은 성립하지 않는다 — 같은 한 가지 변화다

계획은 (a) 다리 켜기/끄기 (b) 다리 90↔91 만 끊기 (c) 7부품 복귀분만 빼기 를
각각 재라고 했다. 실측으로 확인한 사실:

- 이 모델에서 **실제로 생긴 다리는 처음부터 1군데뿐**이다
  (`90번↔91번`, 간격 5.635mm, 씨앗 3개, 방정식 **3개**). 49·50·77 은 다리가
  거부됐다. → (a) 와 (b) 는 **문자 그대로 같은 실행**이다.
- 돌아온 7부품(90·115·117·118·119·120·121)은 **그 다리가 붙인 덩어리 그 자체**다.
  다리를 끄면 이 7개가 고정 쪽과 끊겨 자동 제외되고, 켜면 돌아온다.
  → (c) 는 (a) 의 결과이고 따로 끌 수 있는 손잡이가 아니다.

세 줄로 나눠 적으면 하지 않은 분리를 한 것처럼 보이게 된다. **자유도는 하나다.**

## 묶인절점 2,647 → 2,212 (-435) 는 어디서 줄었나 — 쌍 단위 실측

접합면별 묶인절점을 덤프해(`DZW_FEA_PAIRDUMP`) 두 실행을 **쌍 단위로** 뺐다.
검산: 분해 합계가 실제 차이와 일치한다(-435 = -435).

| 구분 | 묶인절점 변화 | 몫 |
|---|---|---|
| 새로 들어온 7부품이 한쪽인 쌍 (다리 3개 포함) | **+25** | - |
| **기존 부품끼리의 쌍** | **-460** | - |
| 합 | **-435** | 100% |

즉 줄어든 435개는 새 부품 때문이 아니다. **기존 부재끼리 이미 이어져 있던
접합면에서 460개가 빠졌다.** 원인은 코드 주석이 이미 경고한 그 장치다 —
용접 방정식 루프는 `fixed_set`('한 절점은 최대 한 번만 종속')을 누적하므로
부품 구성이 바뀌면 **어느 절점이 어느 접합면의 종속절점이 되는지가 재배분된다.**

가장 크게 빠진 기존 접합면(실측):

| 쌍 | 묶인절점 |
|---|---|
| 40번↔139번 | 64 → 39 (**-25**) |
| 55번↔126번 | 50 → 30 (-20) |
| 130번↔134번 | 35 → 16 (-19) |
| 112번↔139번 | 47 → 29 (-18) |
| 17번↔81번 | 18 → 4 (-14) |
| 13번↔80번 · 58번↔63번 · 29번↔31번 | 8 → **0** (접합면이 통째로 사라졌다) |

## 변위가 커진 자리는 다리로 붙인 덩어리가 **아니다** (실측)

| 무엇 | 최대 변위 |
|---|---|
| 다리로 붙인 7부품 덩어리 전체 | **0.6883mm** |
| 나머지 134부품 | **5.5261mm** (129번 RB702_0356_1) |

전체 최대 변위 자리 `(5503, 1993, 112)` 는 두 실행 모두에 있는 **기존 부재**다.
그 부재의 접합이 실제로 약해졌다(실측):

| 129번의 접합 | 묶인절점 |
|---|---|
| 129↔133 | 40 → 31 |
| 129↔131 | 24 → 23 |
| 8↔129 | 8 → 5 |
| 7↔129 | 4 → **0** |
| 13↔129 | 3 → **0** |
| 122↔129 | 3 → **0** |
| **129번 합계** | **108 → 85 (-21%)** |

## 원인 확정

변위 +50.1% 는 **부재가 7개 늘어서가 아니다**(그 7개는 0.69mm 밖에 안 움직인다).
다리 1군데(방정식 3개)를 넣어 부품 구성이 134 → 141 로 바뀌자, 용접 종속절점
배정이 재배분되어 **기존 부재끼리의 접합에서 460개가 빠졌고**, 변위 최대 자리인
129번의 접합은 108 → 85 개로 21% 약해졌다. 그래서 기존 구조가 더 유연해졌다.

**숫자로 몇 %씩 갈랐나**: 자유도가 하나이므로 (a)/(b)/(c) 로는 못 가른다.
가른 것은 '묶인절점 -435' 의 출처다 — **새 부품 쪽 +25 / 기존 부품끼리 -460**.
'7부품이 늘어서 변위가 늘었다' 는 가설은 **기각**된다(그 덩어리 변위 0.69mm).

## 남는 숙제 (계산 안 한 것)

- 재배분이 '옳은 쪽' 인지 '틀린 쪽' 인지는 **아직 안 쟀다**. 접합면이 0개로
  사라진 쌍(13↔80 · 58↔63 · 29↔31 · 7↔129 · 13↔129 · 122↔129)은 물리적으로
  용접이 있는 자리인데 방정식이 0개가 된 것이므로, 이 자체가 결함일 수 있다.
  어느 쪽 숫자가 참값에 가까운지는 이 실험으로 판정하지 않는다.


---

# 머신 BC 로 국부 재해석 (2026-10-11) — 후보 판정 표

조건: 머신 하중(바닥 6고정 / -Z / 3톤 29,400N) / 146부품 / 전체 품질메시 /
전체 해석 기준값 절점 897,254 · 묶인절점 2,212 · 변위 5.526097mm ·
구조최대 594.561248MPa · 요소 9.739mm. 후보 8곳 → 중복 제거 6곳 → 상위 3곳 판정.

| 후보 | 자리 (x,y,z) | 1단계 절점 / h | 2단계 절점 / h | 실측 축소비 | 그 자리 응력 변화 | 접합면힘 가중오차 | 판정 |
|---|---|---|---|---|---|---|---|
| 1 | 2648.6, 3401.4, 177.1 | 425,072 / 8.0mm | **없음** | **—** | — | 8272% (최대 31877%) | **판정 불가** |
| 2 | 5432.5, 3820.0, 363.9 | 297,376 / 10.8mm | 913,803 / 5.4mm | **2.61배** | **+169.5%** | 327% (최대 6404%) | 특이점 확정 |
| 3 | 5386.1, 3958.9, 417.0 | 315,192 / 10.5mm | 826,784 / 5.5mm | **2.60배** | **+405.4%** | 226% (최대 1276%) | 특이점 확정 |

소요 693초. 축소비 ≥1.8 요구는 **판정이 나온 두 후보에서 2.61·2.60배로 달성**했고
`h목표 못맞춘부재` 는 세 후보 모두 0개다(걸었다가 아니라 실제로 그렇게 됐다).

## 후보1 은 '미수렴' 이 아니라 '2단계를 못 돌림' 이다 — 둘을 구분한다

후보1 은 단계가 **1개뿐**이므로 축소비도 응력 변화도 **존재하지 않는다**.
서버가 남긴 사유 그대로: *요소를 1.8배 가늘게 하는 것조차 절점 약 **1,160,129**개로
상한 **950,000**개를 넘습니다(후보 부재 77,394절점 / 둘레 347,678절점)*.
'미수렴(두 단계를 비교했는데 값이 안 잦아들었다)' 과 '예산에 걸려 비교 자체를 못 했다'
는 배지에서 같아 보이지만 뜻이 다르다. 후보1 은 뒤쪽이다.

후보2·3 도 **2단계에서 멈췄다**(3단계는 7,212,573 / 6,056,219 절점이 필요).
즉 '응력이 계속 커진다' 는 두 점으로만 본 것이다.

## 반드시 같이 읽어야 하는 숫자 — 접합면힘 가중오차

국부 모델은 영역 경계(용접 씨앗점)에 전체 해석의 변위를 강제해서 푼다.
그 강제가 타당한지는 **접합면을 지나는 힘이 전체 해석과 맞는가**로만 검증된다.
이번 실행의 가중오차는 **후보1 8272% / 후보2 327% / 후보3 226%** (최대 31877% /
6404% / 1276%) 다. 이 숫자를 옆에 적지 않고 '특이점 확정' 배지만 보여 주면
경계 강제가 수백 % 틀어진 모델의 판정을 사실처럼 읽게 된다.
→ **'특이점 확정' 은 "이 자리 값은 메시를 줄일수록 커지므로 설계 판정에 쓰지 말라"
는 뜻으로만 쓴다.** 위험하다/안전하다를 말하는 숫자가 아니다.

## 계산 안 한 것

- 후보1 의 영역 반경을 줄여 2단계를 돌리는 것: **안 했다**. 영역을 줄이면 경계가
  후보에 가까워져 경계 강제의 영향이 커지는데, 접합면힘 오차가 이미 8272% 라
  반경만 줄여 숫자를 얻는 것은 두더지잡기가 된다.
- 3단계(1/4): **0후보 도달**. 세 후보 모두 2단계 뒤 절점 상한에 걸린다.
- 접합면힘 가중오차가 왜 수백~수만 %인지: **원인 미규명**. 이것이 먼저다.

---

# 49·50·77 메시 밀도 상향 (2026-10-11) — 제외 5 → 2

## 원인을 먼저 갈랐다 (전수 정확거리로 재측정)

`cad_min_gap` 은 k=24 로 자른 **상한**이다. 전수 정확거리로 다시 재니:

| 쌍 | k=24 근사 | 전수 정확 | 겉면 절점 ↔ 상대 **메시** (전수 정확) |
|---|---|---|---|
| 49번↔18번 CAD | 2.920mm | **0.1201mm** | 겉면절점 21개 / **11.0027mm** |
| 77번↔17번 CAD | 8.000mm | **8.0000mm** | 겉면절점 24개 / **22.4199mm** |

49번은 사실상 **닿아 있다**(0.12mm). 그런데도 못 이은 이유는 겉면 모서리절점이
21개뿐이어서 접합면 자리에 절점이 없었기 때문이다 — **메시 밀도 문제**가 맞다.

## 고친 것 — 사유가 '메시' 인 부재만 요소크기를 내리고 한 번 더 잇는다

부품번호를 코드에 박지 않는다. 판정 근거는 전부 이 실행의 실측값이다:
`CAD 간격 ≤ 10mm`(이을 범위 안) **이고** `겉면 절점 ↔ 상대 메시 > 간격+1mm`
(그 거리 안에 묶을 절점이 없다) 인 떠 있는 부재만 고른다. 요구 요소크기는
`간격 + 1mm`. 절점 100만을 지키려고 부재당 상한 30,000절점 사다리로 물러난다.

실측(상대 **메시** 기준, `_exp_fine_probe2.py`):

| 49번 목표 h | 실제 h | 절점 | 겉면절점 ↔ 18번 메시 | 요구 3.92mm 안? |
|---|---|---|---|---|
| (지금) | 성긴 | — | **11.003mm** | NO |
| 3.92mm | 3.02mm | 77,503 | 0.005mm | YES (단 상한 초과) |
| 5.88mm | 4.39mm | **26,975** | **0.022mm** | **YES** ← 채택 |

## 결과 (머신 BC 6고정/-Z/3톤, 146부품, 전체 품질메시)

| | 전 | 후 |
|---|---|---|
| 부재 해석 | 141 | **144** |
| **제외** | **5** | **2** |
| 절점 | 897,254 | **951,560** (100만 미만) |
| 묶인절점 | 2,212 | 2,234 |
| 변위 | 5.526097mm | **5.524182mm** |
| 구조최대 | 594.561248MPa | **593.786406MPa** |

이은 다리 3군데(실측): `18번↔49번 방정식 4개` · `18번↔50번 5개` · `90번↔91번 3개`.
**47번도 같이 살아났다** — 47·49·50 이 한 덩어리였고 49·50 이 고정 쪽에 붙자
47번도 이어졌다(실측: 47↔50 접합면 8개 · 47↔49 접합면 5개).

변위·응력은 거의 안 움직였다(-0.03% / -0.13%). 제대로 용접된 부재 3개가 들어오면
구조가 이렇게 조금 바뀌는 것이 정상이다 — 다리 1군데로 7부품을 매달았을 때
변위가 50% 뛴 것(앞 절)과 대비된다.

## 남은 제외 2개 — 전부 실측 사유

| 번호 | 이름 | 사유(실측) |
|---|---|---|
| 102 | Group74 | 정점이 3개뿐 — 형상이 없다 |
| 77 | Group13 | 17번 **메시** 표면까지 22.42mm. 77번을 2.83mm 로 촘촘히 해도 22.42mm 에서 안 줄었다 |

## 77번은 왜 안 되나 — 손댈 쪽이 반대였다 (실측)

| 17번 목표 h | 17번 실제 h | 17번 절점 | 77번 겉면절점 ↔ 17번 메시 |
|---|---|---|---|
| 9.0mm | 7.16mm | **1,147,958** | 22.420mm |
| 13.5mm | 10.59mm | 370,374 | 22.420mm |
| 20.0mm | 15.45mm | 125,413 | 22.420mm |
| 30.0mm | 22.61mm | 42,523 | 22.420mm |

77번 쪽을 촘촘히 해도, 17번 쪽을 1,147,958절점까지 촘촘히 해도 **22.420mm 에서
한 톨도 안 줄었다.** 77번의 형상은 멀쩡하다(수리 방법 '원본', 수리 후 표면이
CAD 표면에서 0.000mm). 77번 CAD ↔ 17번 CAD 는 전수 정확거리로 **8.0000mm** 다.

**즉 '8.0mm 떨어진 CAD' 와 '22.42mm 떨어진 메시' 가 같이 성립한다 —
이 모순의 원인은 아직 규명하지 않았다.** 메시 밀도로는 설명되지 않는다(밀도를
160배 올려도 값이 고정이다). 숫자를 맞추려 추측을 적지 않는다 — 다음 숙제다.


---

# 브라우저 증명 (2026-10-11) — 화면이 헤드리스와 같은 숫자를 말한다

서버는 포트 8097 을 kill 하고 이번 코드로 다시 띄웠다(PID 교체 확인).
블럭 `500PRO-R 수정안 20260917`(293부품) → 3D 에서 부재 클릭 →
`이 기계 전체 담기`(**146**) → `전체 품질메시(정밀)` ✓ + `후보 국부 재해석` ✓ →
전체 하중 `3톤 (29,400N)` → `기계 전체 해석 실행`.
서버가 받은 요청 실측: 부품 146 / 하중 29,400N / quality_bulk True / local_refine 3.

## 화면 = 헤드리스

| 항목 | 헤드리스 | 화면 |
|---|---|---|
| 최대 변위 | 5.524182mm | **5.524 mm** |
| 구조 최대 | 593.786406MPa | **593.8 MPa** |
| 부품 | 144 해석 / 2 제외 | **144개 해석 / 2개 제외(회색)** |
| 적용 하중 | 29,400N | **29400 N** |
| 평형 검증 | — | **✓ 0.00% (평형 성립)** |

## 화면에 새로 적히는 줄

- `용접 추정 3군데 — 49번↔18번 2.92mm(접촉 복구) · 50번↔18번 2.92mm(접촉 복구) ·
  90번↔91번 5.63mm(간격 추정 용접)`
- `메시 밀도 상향 2개 — 49번 요소 4.4mm(절점 26,975) · 50번 요소 4.4mm(절점 27,137)
  (겉면 절점이 성겨 용접을 못 만들던 부재만 요소를 줄였습니다 — 실측 근거)` ← 이번에 추가
- `제외된 부품과 사유(실측)` — 102번 · 77번 2개, 사유 전문 그대로
- 배너: **`부재 일부가 빠졌습니다 — 전체 안전 미확정`** /
  막는 조건 `부품 2개 해석 제외 · 후보 1/3곳이 메시 수렴 미증명`

## 후보 판정 배지 (화면, 144부품 모델)

※ 앞 절의 후보 판정 표는 **141부품 모델**(밀도 상향 전)이다. 밀도 상향으로 모델이
144부품으로 바뀌었으므로 후보 자리와 판정도 다시 나온 값이다 — 같은 표가 아니다.

| 순위 | 자리 | 배지 | 화면 문구(실측) |
|---|---|---|---|
| 1위 | 2649, 3401, 177 | **판정 불가** | 판정에 쓸 수 있는 단계가 1개뿐 — 요소를 1.8배 가늘게 하는 것조차 절점 약 **1,197,353**개로 상한 950,000개를 넘습니다(후보 부재 80,940 / 둘레 347,678) |
| 2위 | 2658, 3407, 177 | **판정 불가** | 같은 사유 — 1,197,353 / 상한 950,000 (후보 부재 80,940 / 둘레 347,678). 1위와 '같은 자리 후보 2개 합침(27mm 안)' 으로 묶인 같은 영역이다 |
| 3위 | 5432, 3820, 363 | **특이점 확정** | 요소를 13.0mm → 5.2mm (**2.48배**) 로 줄였는데 이 자리 응력이 **39.7%** 더 커졌습니다 — 값이 발산하는 특이점입니다(실제 위험이 아님) |

세 배지 전부 촬영했다(1·2위 판정 불가 / 3위 특이점 확정). 배너의
`후보 1/3곳이 메시 수렴 미증명` 과 배지 3개가 서로 맞는다.

## 같은 자리인데 순위도 숫자도 달라졌다 — 모델이 바뀌었기 때문이다

`5432, 3820, 363` 은 141부품 모델에서 **후보2 / 축소비 2.61배 / +169.5%** 였고,
144부품 모델(밀도 상향 뒤)에서는 **3위 / 축소비 2.48배 / +39.7%** 다.
**같은 물리적 자리의 숫자가 이만큼 움직인다.** 부재 3개가 더 들어와 하중 경로가
달라졌기 때문이며, 그래서 두 표를 한 표로 합치면 안 된다. 특이점 판정(값이 메시를
줄일수록 커진다)은 두 모델에서 모두 같은 방향이지만, **증가율 숫자 자체는 모델에
딸린 값**이라 설계 판정에 쓰지 않는다.

증거 화면:
`_fea_판정_20261011_1_제외2개_밀도상향_용접3군데.jpg`
`_fea_판정_20261011_2_배너_부재일부빠짐.jpg`
`_fea_판정_20261011_3_평형검증_변위5.524_593.8MPa.jpg`
`_fea_판정_20261011_4_후보1_판정불가_예산초과.jpg`
`_fea_판정_20261011_5_후보3_특이점확정_2.48배.jpg`
`_fea_판정_20261011_6_후보2_판정불가_예산초과.jpg`
