Содержание ↓
Глава 9

От входного файла до проверяемого результата

Текущая МКЭ‑Ф — GNU Octave-программа с функциональным численным ядром. Данные модели создаются один раз, решатели возвращают новые структуры результатов, а графика и печать не участвуют в вычислении.

Границы ответственности

СлойЗадачаОсновной код
ВводЧтение секций до EOF, проверка записей и создание элементов.FEMesh.m, createStructuralElement.m
СборкаНакопление элементных вкладов в разреженные глобальные K и M.assembleGlobalMatrices.m
МодельСнимок матриц, карты СС, опор, нагрузок и данных элементов.createAnalysisModel.m
Численное ядроРедукция СС, решение и создание новой структуры ответа.solveStatic.m, solveModal.m, solveTransient.m
РезультатыРеакции, равновесие, локальные усилия и спектр.calculateStaticEquilibrium.m, recoverElementResults.m, computeSingleSidedSpectrum.m
Совместимость и представлениеПривычные команды RunStatic, RunModal, RunTransient, необязательные печать и графики.StructFEProblem.m, plotTransientResult.m

Корневая функция setup явно добавляет каталоги src/model, src/analysis, src/results и scripts в путь Octave. Поставляемые модели находятся в examples/cases, готовые данные постпроцессора — в examples/results, а новые результаты записываются в игнорируемый каталог output.

addpath(pwd);
setup;

problem = StructFEProblem(fullfile( ...
    "examples", "cases", "CaseBeam.txt"));
model = problem.GetAnalysisModel();

staticResult = solveStatic(model);
modalResult = solveModal(model);
Запуск прикладного расчёта через GUI

Контейнерный интерфейс запускается из корня проекта командой docker compose up --build или docker-compose up --build. В препроцессоре создайте модель либо откройте TXT-файл с секцией analysis и нажмите Run analysis. Backend всегда вызывает фиксированный RunSelected(); браузер не передаёт имена скриптов, пути или выражения Octave.

Вызов решателя не меняет model, problem.K или problem.M. Нагрузки строятся с нуля на каждый запуск, поэтому повторный расчёт и перестановка видов анализа не должны менять ответ.

Элементы и разреженная сборка

Элемент — обычная структура значений, а не изменяемый объект-наследник. createStructuralElement создаёт общий контракт для типов 112 и 113: type, nodeNumbers, properties, единый вектор dofs, матрицы и сохранённые length и transformation. Одна и та же карта СС используется при сборке и восстановлении усилий.

assembleGlobalMatrices сначала формирует триплеты «строка — столбец — значение», затем одним вызовом sparse создаёт глобальные матрицы. При совпадении адресов Octave суммирует вклады. Память определяется числом элементных коэффициентов, а не квадратом числа СС.

Инвариант архитектуры

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

Валидация и работа без GUI

FEMesh проверяет открытие файла, порядок секций, число полей, конечность чисел, номера узлов, свойства элементов, типы нагрузок и запрет смешанной сетки. onCleanup закрывает файл и при ошибке. Сообщение парсера содержит имя файла и строку; полный контракт приведён в главе 10.

По умолчанию verbose=false и plotting=false. Поэтому создание задачи и все три расчёта работают локально в терминале без графического дисплея. Отрисовка сетки и истории — отдельные действия; axis equal не искажает геометрию сетки.

octave --no-gui --quiet --eval "addpath(pwd); setup; run_octave_tests;"

Порядок проверки

  1. run_octave_smoke_tests читает поставляемые задачи, проверяет разреженную сборку и запускает доступные виды анализа.
  2. run_verification_tests проверяет элементные и глобальные инварианты, независимые формулы, реакции, нагрузки и порядок вызовов.
  3. Специализированные файлы проверяют матрицы элементов, сборку, модальный пример Mario Paz, Ньюмарка, усилия и ввод.
  4. Лабораторные справочника добавляют учебные, но исполняемые проверки реального производственного кода.
Что не является эталоном

Матрицы, частоты и формы Illustrative Example 11.1 из Mario Paz и William Leigh восстановлены и проверяются отдельным тестом. Старые снимки вывода и расхождение с ANSYS по-прежнему не объявлены оракулами: эталонами служат опубликованный пример, аналитические решения и явно записанные инварианты.

Версии 2017 года и текущая программа

Статьи автора фиксируют происхождение проекта, но описывают MATLAB-архитектуру своего времени. Их имена классов, точки останова, порядок изменения матриц и численные расхождения нельзя переносить в текущую инструкцию.

Исторический материалЧто он фиксируетТекущий эквивалент
«МКЭ‑Ф — метод Ньюмарка», v0.4Переход к методу Ньюмарка и старый MATLAB-вызов переходного расчёта.solveTransient, начальные условия, полные истории и проверяемая схема β=1/4, γ=1/2.
«Матрица масс и матрица жёсткости», v0.6.0Типы 112/113, согласованная масса и прежняя иерархия FiniteElementStructural/Beam2DElement/Truss2DElement.createStructuralElement возвращает структуру; единая триплетная сборка заменяет изменяемые классы и методы Assembler.
«Расчёт рамы в МКЭ‑Ф», период v0.6.0Происхождение задачи ANSYSBeamStatic01.txt и историческое сравнение с Beam188.Файл остаётся регрессионным входом, но 5%-ное расхождение старой статьи не считается требуемым результатом.

Метка «период v0.6.0» для статьи о раме — хронологическая привязка: на следующий день автор прямо назвал актуальную версию v0.6.0. Сама статья о раме номер версии не печатает.

Карта выполненного плана улучшений

Ниже сохранены все отмеченные выполненными пункты прежнего ToDo.md. Для каждого указан действующий код и проверка; где промежуточное решение позже заменено, указан его нынешний эквивалент.

1. Совместимость GNU Octave и локальная проверка

  1. Минимальная версия GNU Octave 8.4 и локальная проверка на 11.3 указаны в главе о локальном запуске; точка проверки — run_octave_tests.m.
  2. Команда без графического интерфейса реализована в run_octave_smoke_tests.m и запускается разработчиком локально.
  3. Все поставляемые задачи собираются, а статика, моды, импульс и гармоника запускаются в run_octave_smoke_tests.m; матричные инварианты повторяются в tests/run_verification_tests.m.
  4. Промежуточные конкретные резервные методы старого абстрактного класса позже заменены структурами в createStructuralElement.m; интерфейс проверяет tests/test_element_matrices.m.
  5. Проверка массивов однородных элементов handle-классов стала неактуальна после перехода на структуры; их массив создаёт FEMesh.m и проверяет smoke-тест.
  6. Необязательные печать и графика реализованы в StructFEProblem.m; значения по умолчанию проверяет tests/test_input_validation.m.
  7. UTF‑8 закреплён в .editorconfig; чтение русских файлов фактически проходит во всех smoke-тестах.
  8. Поддерживаемые Octave операции и повторное решение сосредоточены в solveTransient.m и validateReducedSystem.m; их проверяет tests/test_newmark_transient.m.
  9. Небольшая функция локального запуска — run_octave_smoke_tests.m; успешное завершение является самой проверкой.
  10. Одноаргументный конструктор сохранён в StructFEProblem.m, а настройки работы без графического интерфейса проверены в tests/test_input_validation.m.

2. Самодостаточная проверочная база

  1. Набор проверок только для Octave находится в tests/run_verification_tests.m и включён через run_octave_tests.m.
  2. Размеры, конечность, симметрия K/M проверяет testMatrixInvariants в том же файле и tests/test_element_matrices.m.
  3. Формулы FL/(EA) и PL³/(3EI) проверяют testSingleAxialTruss и testCantileverBeam.
  4. Реакции, масса, одношаговый импульс и гармонические отсчёты проверяет tests/run_verification_tests.m.
  5. Все поставляемые файлы служат регрессионными проверками отсутствия аварий в run_octave_smoke_tests.m.
  6. Явные абсолютные и относительные допуски реализуют вспомогательные функции assertClose и assertRelativeSmall в тестах.
  7. Полный локальный набор запускается через run_octave_tests.m.
  8. Пример Mario Paz проверяется по опубликованным матрицам, частотам и формам в tests/test_mario_paz_modal.m; пример ANSYS остаётся только сведением о происхождении проекта.

3. Матрицы элементов

  1. Симметричный коэффициент -22*L согласованной массы рамного элемента находится в createStructuralElement.m; симметрию проверяет tests/test_element_matrices.m.
  2. Коэффициенты EA/L, 12EI/L³, 6EI/L² записаны напрямую там же и сравниваются с независимой матрицей в том же тесте.
  3. Нулевая длина и неположительные A, E, ρ, I отклоняются в createStructuralElement.m; testInvalidElementData проверяет ошибки.
  4. Горизонтальная, вертикальная и наклонная ориентации проверяются функциями testTrussOrientations и testBeamOrientations.
  5. Симметрия, ранг, твёрдые моды, инвариантность поворота и масса проверяются в tests/test_element_matrices.m.

4. Функциональное ядро

  1. Модель отделяет данные от ответа в createAnalysisModel.m; testFunctionalAnalysisCore проверяет неизменность.
  2. Чистые точки входа — solveStatic.m, solveModal.m, solveTransient.m; фасад делегирует им в StructFEProblem.m.
  3. K и M не редактируются: это явно проверяет testFunctionalAnalysisCore.
  4. Новые нагрузки для каждого запуска создают buildStaticLoad.m и buildTransientLoad.m; повторные вызовы сравнивает тот же тест.
  5. Два одинаковых запуска сравниваются в testFunctionalAnalysisCore.
  6. Независимость от порядка статики, мод и динамики проверяется там же.
  7. Именованные поля формируют три solve*.m; наличие ключевых полей проверяет тот же тест.
  8. Построение графика вынесено в plotTransientResult.m, печать оставлена фасаду; работу без графического интерфейса проверяют smoke-тест и tests/test_input_validation.m.

5. Редукция свободных СС

  1. fixedDOFs и freeDOFs строит partitionDOFs.m; карту проверяет testFreeDOFReduction.
  2. Редуцированные K и M используют три решателя; соответствующие срезы проверяются в tests/run_verification_tests.m.
  3. Фиктивные нулевые моды устранены в solveModal.m; положительность частот проверяет testFreeDOFReduction.
  4. Нагрузка на закреплённой СС сохраняется в solveStatic.m; реакцию проверяет тот же тест.
  5. Глобальное равновесие вычисляет calculateStaticEquilibrium.m; bar/cantilever tests проверяют нулевую невязку.
  6. Повторные, неверные и недостаточные связи отклоняют partitionDOFs.m и validateReducedSystem.m; ошибки проверяет testConstraintValidation.

6. Семантика узловых нагрузок

  1. Индексную сборку по СС выполняет getNodalLoadComponents.m вместе с функциями построения нагрузок; несколько записей проверяет testNodalLoadSemantics.
  2. Третья компонента рамы трактуется как Mz, а у фермы отклоняется; код и тест те же.
  3. Исторический тип 10 даёт один прямоугольный шаг в buildTransientLoad.m; точный отсчёт проверяет testNodalLoadSemantics.
  4. Явный bcforce_pulse/тип 12 читает FEMesh.m; входной файл CaseExplicitPulseBeam.txt проверяется в тесте нагрузок.
  5. bcforce_step/тип 13 реализован теми же файлами; входной файл CaseStepBeam.txt проверяет постоянную историю.
  6. Суммирование нескольких нагрузок в одном и разных узлах проверяет testNodalLoadSemantics.

7. Переходный расчёт Ньюмарка

  1. Средние ускорения β=1/4, γ=1/2 реализованы в solveTransient.m; параметры проверяет tests/test_newmark_transient.m.
  2. Сетка с первым столбцом t=0 реализована там же и проверяется в testFreeVibrationAndInitialState.
  3. Начальные u, v и ускорение из равновесия реализованы там же; проверяются тем же тестом и сценариями ошибочного ввода.
  4. Истории размера stepCount+1 предвыделяются в solveTransient.m; размер проверяет тест переходного анализа.
  5. Постоянная эффективная матрица факторизуется один раз там же; согласованность ответа проверяет весь набор тестов переходного расчёта.
  6. FFT и одностороннюю нормировку выполняет computeSingleSidedSpectrum.m; пик проверяет testSingleSidedSpectrum.
  7. Истории и спектр возвращаются независимо от графики; поля проверяют тесты переходного анализа, построение вынесено в plotTransientResult.m.
  8. Аналитический SDOF, энергия и сходимость проверяются в testFreeVibrationAndInitialState, testImpulseResponseAndConvergence и testBeamImpulseRefinement.

8. Восстановление результатов

  1. Совместимое имя StressCalc.m делегирует новой реализации recoverElementResults.m; интерфейс проверяет tests/test_result_recovery.m.
  2. Деформацию, напряжение и осевую силу стержня вычисляет recoverElementResults.m; прямой и повёрнутый стержни проверяются там же.
  3. Локальные концевые усилия рамы возвращает та же функция; эпюры сознательно отложены до появления распределённых нагрузок, а консоль проверяет testCantileverEndForces.
  4. Одностержневой и консольный эталоны находятся в tests/test_result_recovery.m.

9. Упрощение и ускорение сборки

  1. Выбор структур и чистых функций реализован в createStructuralElement.m; интерфейс проверяют тесты матриц и восстановления результатов.
  2. Пункт о семантике значений классов закрыт удалением изменяемой иерархии; отсутствие элементов handle-классов следует из структур FEMesh.allMeshElems и проверяется smoke-тестом.
  3. Единый интерфейс полей используется assembleGlobalMatrices.m и recoverElementResults.m; оба пути покрыты отдельными тестами.
  4. Один element.dofs создаёт createStructuralElement.m; карту и суммирование проверяет tests/test_sparse_assembly.m.
  5. Триплетные sparse-матрицы создаёт assembleGlobalMatrices.m; testSuppliedCasesAreSparse и testLargeTrussChain проверяют результат.
  6. Длина и преобразование кешируются в структуре элемента; тесты матриц и восстановления результатов используют и проверяют эти данные.
  7. Сохранение базовых результатов контролируют полный набор проверок и smoke-тесты.

10. Ввод, документация и представление

  1. Цикл чтения до конца файла находится в FEMesh.m; повторные секции и неизвестный маркер проверяет tests/test_input_validation.m.
  2. fopen, onCleanup и номера строк реализованы там же; ошибки открытия и неверные записи проверяет тот же тест.
  3. Повторные опоры и нагрузки дописываются в FEMesh.m; CaseRepeatedSections.txt проверяет количество и сумму.
  4. Номера узлов, связность, число свойств и выбор СС графика проверяют FEMesh.m/StructFEProblem.m; тестовые входные файлы и testPlotSelectionAndDefaults проверяют ошибки.
  5. Смешанные типы отклоняются как MKEF:UnsupportedMixedMesh; CaseMixedElements.txt проверяет строку ошибки.
  6. Необязательные графика и печать находятся в StructFEProblem.m, а axis equal — в FEMesh.m; значения по умолчанию проверяет тест входных данных.
  7. Единицы, СС, нагрузки, ограничения, источники и команды сохранены в этом справочнике, прежде всего в главе 10; исполняемое подтверждение дают лабораторные и полный набор тестов.

Диагностика расчёта

СимптомВероятная причинаЧто проверить
MKEF:SingularStiffnessМеханизм, отсоединённый узел или недостаточные опоры.Связность, длины элементов, fixedDOFs; не «лечите» механизм добавлением единиц в K.
MKEF:SingularMass или неверная модальная задачаНеположительная/вырожденная редуцированная масса.ρ, A, I, свободные СС и связность.
Неожиданный знак реакции или усилияСмешаны глобальная и локальная системы либо сила на конструкцию и сила на элемент.element.transformation, порядок localEndForces и главу 8.
Неожиданный динамический импульсТип 10 принят за постоянную ступень.Для явного импульса используйте тип 12, для ступени — тип 13; см. главу 4.
Ошибка с именем файла и строкойНарушен формат секции.Сверьте запись с главой 10; не удаляйте номер строки из отчёта об ошибке.

Исходный код главы

История проекта

  • Даниил Денисов, «МКЭ‑Ф — метод Ньюмарка», 25 ноября 2017, версия 0.4.
  • Даниил Денисов, «Матрица масс и матрица жёсткости», 20 декабря 2017, версия 0.6.0.
  • Даниил Денисов, «Расчёт рамы в МКЭ‑Ф», 19 декабря 2017, период версии 0.6.0.