# R8: независимый расчётный аудит, итерация 01

19.09.2026. Проверены `tools/r8/structure.py`, `stiffness_screen.py`, `assembly.py`, `node.py`, сохранённые локальные JSON и `docs/architect/r8_structure.md`. CAD, прежние отчёты R6/R7/R8 и Site не изменены.

**Вердикт: R8 можно показать как промежуточную геометрию с `construction_ready=false`; утверждение о подтверждённой устойчивости ног и прочности всех узлов сейчас не обосновано.** Найдены конкретные расхождения расчётной модели с деталями, а не только отсутствующие внешние данные. Автоматически увеличивать сечения из этого вывода не следует.

## Воспроизводимость

Добавлен независимый проверочный скрипт:

```
tools/venv/bin/python -m tools.r8.audit_structure_01
```

Он читает существующие входы, вызывает функции расчёта без их `main()`, пишет только `build/r8/audit_structure_01.json`. В JSON сохранены SHA256 всех прочитанных расчётных/CAD-файлов и самого аудитора. Подтверждено, что исходные файлы за время проверки не изменились. Восемь проверок балочного элемента и равновесие двух повторённых случаев пройдены. Это подтверждает работу линейного балочного решателя, но не физические допущения ниже.

## 1. Три перекладины не обосновывают длину потери устойчивости L/4

В CAD есть **12 перекладин**, по три у каждой пары ног. В расчёте `Screen` остаются **13 узлов и 24 исходных ребра**: `stiffness_screen.py` собирает элементы только из `topology['edges']`. Расчётных узлов в местах перекладин, самих перекладин и их соединений нет.

В `structure.py:110` выполнено только:

```python
L = mem['length_mm'] / (RUNGS + 1 if mem['at_foot'] else 1)
```

При `RUNGS=3` критическая сила отдельной ноги увеличивается в **16 раз**. Это отдельная арифметическая скидка в формуле Эйлера, а не результат пространственной проверки раскрепления.

Связь между двумя податливыми ногами ограничивает прежде всего их относительное движение. Если концы перекладины одинаково смещаются, её осевая деформация `n·(u₂−u₁)` равна нулю. Такая проверка выполнена в аудиторском скрипте. Значит, перекладина не является неподвижной боковой опорой для каждой ноги по самому факту наличия. Её изгиб, кручение и моментные соединения **могут** повысить устойчивость всей пары, но эту работу надо включить в модель и проверить, особенно для общей пространственной формы обеих ног. Здесь она не включена.

Для общего принципа достаточности раскрепления необходимы и его жёсткость, и прочность, а не только число точек: это отдельно обсуждается в исследовании AISC [Notes on the Nodal and Relative Lateral Stability Bracing Requirements](https://ej.aisc.org/index.php/engj/article/view/1046). Ссылка объясняет механику раскрепления; нормы для стали и их численные сопротивления к фанере здесь не применялись.

Повторена только исходная формула для ног с теми же усилиями и материалом, но без деления длины:

| Величина | Равномерный снег + вес | Односторонний снег + вес |
|---|---:|---:|
| Максимальное сжатие ноги | 6,270 кН | 9,432 кН |
| Полная длина оси ноги | 2463,49 мм | 2463,49 мм |
| Принятая в исходнике длина L/4 | 615,87 мм | 615,87 мм |
| Эйлер для полного L, без коэффициента 1,3 | 9,880 кН | 9,880 кН |
| Максимальный индекс **ноги** при L/4 | 0,052 | 0,078 |
| Тот же индекс ноги при полном L | **0,825** | **1,241** |

Числа 0,61/0,81 в прежней общей таблице определяются другими элементами, а не ногой с L/4. Поэтому умножать общие 0,61/0,81 на 16 было бы неверно. Значение 1,241 — **диагностический результат изолированного шарнирного стержня по прежней формуле**, не доказательство потери устойчивости реально собранной лестницы. Оно показывает, что прежний благоприятный вывод зависит от недоказанного раскрепления.

Даже если условно считать три поперечины неподвижными опорами, их уровни не делят исходную ось точно на четыре части. Проекция отметок 650/1200/1750 мм на ось даёт участки около 656/651/651/506 мм; максимальный больше принятого 616 мм. Реальные места опор и ось сечения дополнительно отличаются от этих исходных осей.

**Исправление постановки:** включить обе ноги и все перекладины с реальными узлами, податливостью и условиями удержания; проверить общую форму потери устойчивости и формы отдельных ног между перекладинами. Для промежуточного обзора графа «устойчивость ног» должна иметь статус «раскрепление не подтверждено», а не PASS по L/4.

## 2. У перекладин не задано положительное удержание на растяжение

`assembly.py:264–317` формирует прямые шипы, проходящие через косые окна в ногах. Они заканчиваются на 1 мм до внешней пласти (`tenon_flush=1`). Плечики опираются на внутреннюю сторону ноги. Наружных запирающих деталей, болтов, клиньев или клеевого соединения перекладины в `hardware` нет.

При сжатии плечики имеют понятный контакт. При расхождении ног простому шипу нечем удержаться от вытягивания из окна. Поперечный контакт со стенками окна не заменяет осевое удержание при растяжении. Это независимо подтверждено геометрическим рецензентом по тому же CAD.

Следовательно, даже до расчёта жёсткости нельзя приписать перекладине произвольное двустороннее усилие связи. Нужно либо явно спроектировать удержание, либо моделировать допустимые односторонние контакты и доказать устойчивость при таком поведении. Этот аудит не назначает новое металлическое соединение.

## 3. Жёсткость шипового узла не выведена из согласованной контактной модели

`node_stiffness()` берёт пробные модули смятия 4000/500 МПа и произвольные эффективные толщины сжатия 30/12 мм. Затем получает для конца сильную/слабую/крутильную жёсткости **6139 / 16820 / 333 кН·м/рад**. Щёки при этом не деформируются как отдельные пластины, стяжки и втулки не входят в силовую модель, поступательный ход концов запрещён точно. Эти числа не являются измеренной или завершённо рассчитанной характеристикой узла.

Найдена и **кинематическая ошибка плеча**. В локальной системе балки `x` идёт вдоль полосы, `y` по её глубине, `z` из её пласти. Для бокового контакта с нормалью `z` относительный ход точки `r=(x,y,0)` равен:

```
δz = (θ × r)z = θx · y − θy · x
```

В предельном случае нулевого наклона разнесение верхней и нижней щёк по `y` создаёт плечо **кручения вокруг x**, а продольное распределение контактов по `x` — слабого изгиба вокруг `y`. В коде величина `k_side * arm² / 2` названа слабой жёсткостью, а продольное плечо `tenon_len² / 3` — кручением. При фактическом наклоне луча нужна трансформация осей с взаимными членами, а не эта перестановка двух диагональных чисел. Аудитор содержит явный тест `θ×r`, показывающий различие.

Также нормальная реакция плечика на пласть щеки работает с продольной координатой плечика и связана с поступательным ходом; прибавление `k_shoulder * arm² / 2` к сильной жёсткости без координат контактных площадок этого не описывает. Величина `tenon_len=50` в боковой контактной площади включает разрыв между двумя зубьями: фактические участки 54–74 и 84–104 мм суммарно имеют длину 40 мм. Это дополнительное отличие расчётной площади от CAD.

Зазоры 0,5/0,3 мм вычислены только как справочные углы 3,45/2,07 мрад. В решатель они не попадают. Вариант `K × 0,3`, названный «запас на люфт», остаётся линейной пружиной без свободного хода и переключения контактов. Это **не модель зазора**. Для масштаба максимальное упругое относительное вращение конца в повторённых исходных случаях всего 0,086/0,146 мрад — существенно меньше названного свободного хода. Это не определяет реальную посадку под собственным весом, но показывает, почему процента от K недостаточно для её описания.

**Исправление:** для каждого действительного контакта использовать положение, нормаль, зазор, площадь и направление слоёв; получить связанную матрицу шести компонент или нелинейную зависимость через активные односторонние контакты. Показать податливость щёк, стяжек и самих шипов. Отдельно проверить влияние переворота/смены знака нагрузки. До этого подпись должна быть «пробная контактная жёсткость», а не «расчётная жёсткость узла» с подтверждённым запасом на люфт.

## 4. Местная проверка пропускает три компоненты усилий

Функция `utilisation()` распаковывает `N, Vy, Vz, T, My, Mz`, но `Vy`, `My` и `T` в её местных проверках не используются. Проверочный вызов поочерёдно подаёт каждую компоненту отдельно: для ненулевых `Vy`, `My`, `T` все индексы торцов шипов, плечиков, стенки и нетто-сечения остаются нулевыми.

Это значимо: в текущем одностороннем случае получены отдельные максимумы `Vy ≈ 2,337 кН` и слабого момента `My ≈ 0,313 кН·м`. Эти максимумы не обязательно совпадают по сечению, но исключать обе компоненты из проверки нельзя.

Плечики проверяются по `Vz`, то есть силе **из пласти полосы**. Нормаль опорной щеки лежит **в плоскости полосы**, поэтому для неё требуется преобразованная комбинация `N` и `Vy`, зависящая от наклона луча. `Vz` идёт на боковые контакты шипов/окон. Следовательно, проблема не только в отсутствующем запасе, но и в неверном отнесении компоненты к контакту.

У двух концов одного стержня продольные компоненты в общей локальной системе имеют противоположные знаки. Проверка использует одинаковые `min(N,0)`/`max(N,0)` для обоих концов без перехода к направлению «в узел». Поэтому распределение «сжатие/растяжение — внутренняя/наружная стенка окна» также необходимо привести к согласованной системе каждого конца.

Проверка нетто-сечения использует только `|N|/A + |Mz|/W`. В ней отсутствует слабый изгиб и взаимодействие с устойчивостью. Проверяются концевые сечения, а не все реальные ослабления: в ногах есть окна перекладин и отверстия пятки, тогда как балочный расчёт использует постоянный прямоугольник 30 × 300 мм. Исправление состоит в проверке **совместного вектора усилий в одном и том же физическом сечении**, а не в сумме произвольных глобальных максимумов.

## 5. Реакции принадлежат идеальным точкам, а не рассчитанной пятке

`Screen` фиксирует три перемещения исходных узлов 9–12, оставляя общий поворот узла свободным относительно основания. Оба конца ног связаны с этим общим узлом теми же вращательными пружинами, что и кровельные шиповые соединения. Это не два независимо шарнирных окончания и не модель фанерной пластины с уголками.

В CAD пластина находится на 300 мм внутри от исходного узла; ноги обрезаны выше него, их реальные сечения опущены от осей сетки. Массивная пластина, две группы уголков, болты и анкеры отсутствуют в матрице. Реакции являются полезными результатантами **принятой идеализации**, но не подтверждают её реальное опирание.

Диагностический перенос уже вычисленного результанта от исходной точки к центру реальных анкеров даёт добавочный момент до **3,56/4,83 кН·м**. Это намеренно названо **проверкой несовпадения геометрии и модели**, а не окончательным моментом новой пятки. Реальные срединные линии опущенных полос сходятся внутри от номинального узла; после их включения и пересчёта распределение усилий и плечи изменятся. Нельзя механически назначить этот перенесённый момент готовой пятке или игнорировать смещение вовсе.

Проверка `heel_bolt` учитывает лишь наибольшее продольное усилие ноги и четыре условные осевые несущие способности. Поперечные силы, момент болтовой группы, эксцентриситет, уголки, пластина и дальнейшая передача к анкерам отсутствуют. Текст прежнего отчёта про «4×М10, крыло 6 мм» относится к другой пятке: текущие CAD и код используют М12 и уголок 8 мм. Эта подпись не описывает текущую деталь.

## 6. Прочие существенные пределы текущего результата

- Из веса исключены **33,5 кг стали**, хотя эта масса известна из текущего `summary.json`. Вместо действительной массы всего крепежа использовано 0,15 кг на каждую запись, включая втулки и анкеры. Вес деталей распределён равномерным давлением по кровле, а не приложен к реальным центрам тяжести; для большой нижней пластины и перекладин путь нагрузки отличается.
- `μ=1,6/0,4` — принятая пробная асимметрия, не установленная этим кодом снеговая схема данного купола. Ветер, мембрана, ползучесть и устойчивость всей оболочки действительно не проверялись. Ограничение L/250 не установлено как допустимое перемещение конкретного ПВХ-покрытия и его крепления.
- Свойства фанеры в отчёте имеют ссылки на СП, но настоящая итерация не заверяет правильность применения всех коэффициентов к каждой контактной поверхности и направлениям слоёв. Одного `R_c_along` для всех торцов, окон и наклонных контактных площадок недостаточно без их ориентации.
- Дата прежнего R8-отчёта «12.09.2026» и остаточные подписи R5/R6 не соответствуют его происхождению 19 сентября. В основном `structure.json` не сохранена полная привязка к входным CAD и источникам; её добавляет текущий аудитор, но это не исправляет происхождение старого отчёта автоматически.

## 7. Конкретный API следующего расчёта по реальной геометрии

Не нужно сначала назначать новую сталь или увеличить высоту полос. Следующий экспорт должен связать CAD с расчётом без изменения внешнего силуэта:

```python
{
  "members": [{
    "id": "B_E010", "source_edge": "E010",
    "centreline_world_mm": [[...], [...]],
    "section_frame_world": {"axis": [...], "depth": [...], "normal": [...]},
    "section_stations": [{"s_mm": ..., "profile_part_id": "...",
                          "A_mm2": ..., "Iy_mm4": ..., "Iz_mm4": ...}],
    "grain_direction_world": [...]
  }],
  "joints": [{"id": "N1", "origin_world_mm": [...], "part_ids": [...]}],
  "member_ends": [{
    "member": "B_E010", "end": 0, "joint": "N1",
    "centroid_world_mm": [...], "offset_from_joint_mm": [...],
    "law": "contact_or_full_6x6", "law_id": "..."
  }],
  "contacts": [{
    "parts": ["...", "..."], "point_or_patch_world_mm": [...],
    "normal_world": [...], "gap_mm": ...,
    "law_id": "...", "tension_retained": False
  }],
  "supports": [{
    "id": "F9", "origin_world_mm": [...],
    "plate_part_ids": [...], "fastener_ids": [...],
    "ground_constraint_or_stiffness": "explicit_separate_model"
  }],
  "masses": [{"part_id": "...", "kg": ..., "centre_world_mm": [...]}]
}
```

Смысл полей и минимальные изменения решателя:

1. **Оси полос брать из срединной линии действительного прямого участка CAD**, а не из вершин поверхности покрытия. Контур и отверстия задают отдельные ослабленные сечения. Не подменять реальный торцевой участок полным прямоугольником.
2. Отдельно задать мастер узла, физическое окончание полосы и расстояние `r` между ними. При жёстком кинематическом переносе `u_end = u_joint + θ_joint × r`; сила переносится вместе с моментом `r × F`. Это только перенос координат — он не объявляет сам фанерный соединитель жёстким. Его податливость задаётся полной 6×6 связью или явными контактами.
3. **Вставить узлы и элементы перекладин** в местах реального пересечения со срединными линиями ног. Передать реальные направления контактных поверхностей и отсутствие/наличие удержания на растяжение. Не создавать неподвижных опор в этих точках.
4. Для пятки построить отдельную связь от окончаний ног через реальные группы болтов и пластину к опорам на бетоне. До доказанной жёсткости выполнить чувствительность по её компонентам; не копировать K кровельного узла и не фиксировать все повороты ради результата.
5. Нагрузку покрытия с её действительной поверхности переносить на реальные оси **вместе с моментом от эксцентриситета**. Вес брать по телам и их центрам. Сохранять контроль суммы всех сил и моментов относительно общей мировой точки.
6. После статического расчёта проверить общую пространственную устойчивость с осевыми усилиями в элементах, реальной работой перекладин и активным набором контактов. Затем — чувствительность к начальным несовершенствам. Только после этого можно обосновать расчётные длины отдельных участков либо пользоваться непосредственной проверкой всей системы.

Ожидаемый следующий результат — согласованный расчёт реальной схемы с перечнем определяющих форм и узлов. Эта рецензия не подбирает сечения «до зелёного» и не утверждает ни безопасность, ни неизбежное разрушение пока не рассчитанной пространственной лестницы.
