1705x
001773
2022-10-18

Инструмент веб-сервис для подпорной воды в C#

API для RFEM 6, RSTAB 9 и RSECTION основан на концепции веб-сервисов. Чтобы получить хорошее представление о предмете, в следующей статье будет объяснён еще один пример в C#.

Этот пример представляет собой расчет нагрузки от воды, приложенной к балке, которая увеличивается из-за прогиба балки. Для большей гибкости пользователь должен иметь возможность выбирать балки. Кроме того, не должны изменяться и дополнительные нагрузки, действующие на кровлю, которые применяются к одному и тому же загружению независимо от нагрузки от воды. Известны/применяются следующие граничные условия:

  • Уровень воды над недеформированной системой
  • Ширина зоны питания стержня для нагрузки на площадь
  • Номер загружения, для которого должна быть приложена нагрузка
  • Нагрузка от воды на м уровня воды (10000 Н/м³)
  • Идентификатор, используемый для идентификации нагрузок на площадь

Поэтому в программе создаются следующие переменные:

  1. code.shamp#

двойной h_water = 0,1;//высота воды над недеформированной системой в [м]
двойное w_ref = 2;//исходная ширина при нагрузке на поверхность в [м]
intload_case_no = 1;//номер загружения, в котором приложена нагрузка
stringwater_accu_comment = "водонакопление";//строка идентификатора
двойной std_magnitude = 10000;//нагрузка на поверхность на высоту воды в [Н/м^3]

  1. /код#

Что касается применения, то программа должна включать следующие элементы:

  1. Фильтрация выбранных стержней
  2. Удаление нагрузок от воды из предыдущих прогонов
  3. Создание новых нагрузок
  4. Начать расчет
  5. Определение прогиба
  6. Вернемся к шагу 3 и создадим новые нагрузки от деформаций
  7. Повторение итераций до тех пор, пока не будет достигнуто предельное значение

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

1. Фильтрация выбранных стержней

Сначала мы получим информацию о всех выбранных объектах с помощью функции get_all_selected_objects. Полученный массив содержит элементы типа object_location, которые могут, например, тип, номер и «материнский» номер объекта более высокого порядка. В следующем цикле извлекаются номера всех объектов типа E_OBJECT_TYPE_MEMBER (т.е. все номера стержней) и сохраняются в массиве mem_noes_sel.

  1. code.cshamp#

//получить выбранные объекты
объект_локации [] obj_locs = model.get_all_selected_objects ();

//извлечь стержни
int[] mem_noes_sel = новый int [0];
forach(object_location obj_loc в obj_locs)
{
if (obj_loc.type == object_types.E_OBJECT_TYPE_MEMBER)
{
Array.Resize(ref mem_noes_sel, mem_noes_sel.Length + 1);
mem_noes_sel [mem_noes_sel.Length-1] = obj_loc.no;
}
}

  1. /код#

2. Удаление водных нагрузок из предыдущих прогонов

С помощью номера стержня теперь можно отфильтровать соответствующие нагрузки на стержень из всех нагрузок на стержни. При этом используется цикл, наложенный на значения нагрузок на стержень. В данном цикле мы получаем данные для нагрузки на стержень, проверяем номера стержней на соответствие выбранным номерам стержней и, если найдено соответствие, соответствующая нагрузка на стержень удаляется:

  1. code.cshamp#

/удалить все нагрузки «water_accu»
//получить все номера нагрузок на стержень
int[] mem_load_noes = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_MEMBER_LOAD, load_case_no);

//цикл по всем нагрузкам на стержень в загружении
forach (int mem_load_no в mem_load_noes)
{
//получить нагрузку на стержень
Member_load mem_load = model.get_member_load(mem_load_no, load_case_no);

if (mem_load.comment ==water_accu_comment)
{
//цикл нагрузки на стержень по стержням
для (int i = 0; i
{
//цикл нагрузки на стержень по стержням
для (int j = 0; j
{
if (mem_load.members [i] == mem_noes_sel [j])
{
//удалить нагрузку на стержень
model.delete_object(object_types.E_OBJECT_TYPE_MEMBER_LOAD, mem_load_no, load_case_no);
}
}
}


}

}

  1. /код#

Для того, чтобы никакие другие нагрузки на стержень не были перезаписаны, в следующем шаге считывается последний использованный номер нагрузки на стержень:

  1. code.cshamp#

//получить последний номер нагрузки
int no_offset = model.get_nth_object_number(object_types.E_OBJECT_TYPE_MEMBER_LOAD,0, load_case_no) + 1;

  1. /код#

Следующим шагом будет создание новых нагрузок на стержень, которое уже является частью итерационного цикла do-what. Данный цикл устроен следующим образом:

  1. code.cshamp#

do
{
//сбросить дельта-деформацию
delta_def = 0;

//применить нагрузку
model.begin_modification("Нагрузки");

  1. //создать нагрузки на стержень для каждого стержня

...

  1. model.finish_modification ()
  2. ...

//рассчитать загружение
...

//получим деформации концов стержней
...

//критерий проверки
} if (delta_def > 0,0001);

  1. /код#

Для остановки итерационного цикла выберем изменение деформации, определенное при фильтрации результатов. Если все деформации отклоняются от деформаций предыдущего прохода менее чем на 0,0001 м (т.е. 0,1 мм), то цикл останавливается.

3. Создание новых нагрузок

В качестве типа нагрузки была выбрана трапециевидная нагрузка, действующая в глобальном направлении z, которая может иметь различные значения в начале и на конце стержня. Обратите, пожалуйста, внимание также на то, что для передачи всех параметров соответствующая переменная «Задана» должна быть установлена на «true». Это необходимо для того, чтобы не передавать все параметры класса и таким образом сохранить относительно небольшой объем данных, которые должны быть переданы. Значение нагрузки's рассчитывается на основе начальной высоты «h_water» (была задана) и дополнительной узловой деформации в этом месте. Затем нужно умножить высоту, данную в [м], на «std_magnitude» в [Н/м3 ] и ширину зоны нагрузки, указанную в [м], в результате мы получим линейную нагрузку в [Н/м]:

  1. code.cshamp#

//создать нагрузки на стержень для каждого стержня
для (int i = 0; i < mem_noes_sel.Length; ++i)
{
Member_load mem_load = новый Member_load ();
mem_load.no = no_offset + i;
mem_load.comment =water_accu_comment;
mem_load.members = новый int [] { mem_noes_sel [i] };

mem_load.distant_a_is_specific_as_relative = true;
mem_load.distant_a_is_specific_as_relativeStecification = true;
mem_load.distant_a_relative = 0,0;
mem_load.distant_a_relativeStecification = true;

mem_load.расстояние_b_is_specific_as_relative = true;
mem_load.distant_b_is_specific_as_relativeStecification = true;
mem_load.distant_b_relative = 1,0;
mem_load.distant_b_relativeStecification = true;

mem_load.load_direction = Member_load_load_direction.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE;
mem_load.load_directionSspecificed = true;

mem_load.load_type = Member_load_load_type.LOAD_TYPE_FORCE;
mem_load.load_typeSspecificed = true;
mem_load.load_distribution = Member_load_load_distribution.LOAD_DISTRIBUTION_traPEZOIDAL;
mem_load.load_distributionSspecificed = true;

  1. mem_load.magnitude_1 = std_magnitude * ((h_water + mem_end_defs [i,0]) * w_ref);

mem_load.magnitude_1Stecification = true;
mem_load.magnitude_2 = std_magnitude * ((h_water + mem_end_defs [i,1]) * w_ref);
mem_load.magnitude_2Stecification = true;

model.set_member_load(load_case_no, mem_load);

}

  1. /код#

Для передачи нагрузки используется функция set_member_load. Для назначения нагрузок используется в качестве комментария строкаwater_accu_comment. В следующих итерациях нагрузки уже не удаляются, вместо этого, при указании номера нагрузки, они будут заменены при повторной передаче. Таким образом, комментарий требуется только для фильтрации и удаления нагрузок при перезапуске приложения. Кроме того, была выбрана относительная величина для задания нагрузки, которая, однако, колеблется в диапазоне 0-100%.

Следующим шагом будет инициирование самого расчета. Сначала создается поле с объектами типа calculate_specific_loading. Это поле содержит все рассчитываемые загружения/сочетания. В данном случае создается только один элемент типа загружения с указанным номером загружения load_case_no:

  1. code.cshamp#

//рассчитать загружение
calculate_specific_loading[] csl =new calculate_specific_loading[1];
csl[0] = новый calculate_specific_loading();
csl [0] .no = load_case_no;
csl[0].type =case_object_types.E_OBJECT_TYPE_LOAD_CASE;

model.calculate_specific(csl, true);

  1. /код#

Теперь, когда доступны результаты, необходимо отфильтровать общие деформации в начале и в конце каждого стержня. Функция get_results_for_members_global_deformations используется для получения всех общих деформаций стержней для указанного загружения и выбранных стержней. Структура результатов такая же, как в соответствующей таблице в RFEM 6. Одним из вариантов является считывание длины стержня и сравнение результата с позицией x. В другом варианте используется данное описание и тот факт, что экстремумы следуют после всех x-разрезов. Был выбран второй вариант, и при первом упоминании «Экстремумы» в описании используется предыдущий индекс для нахождения последнего х-разреза стержня. Поскольку первое местоположение стержня также влияет на первую запись, дальнейшая фильтрация здесь не требуется:

  1. code.cshamp#

//получим деформации концов стержней
для (int i = 0; i < mem_noes_sel.Length; ++i)
{

  1. Members_global_deformations_row[] mem_defs_glbl = model.get_results_for_members_global_deformations(case_object_types.E_OBJECT_TYPE_LOAD_CASE, load_case_no, mem_noes_sel [i]);
  1. //возьмем начальную точку
  2. //рассчитать дельта-деформацию
  3. if (Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl [0].row.displacement_z) > delta_def)
  4. delta_def = Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl [0].row.displacement_z);
  1. mem_end_defs [i, 0] = mem_defs_glbl [0] .row.displacement_z;
  2. //получить деформацию в конечной точке
  3. для (int j = 0; j
  4. {
  5. if (mem_defs_glbl [j] .description == "Экстремумы")
  6. {
  7. //рассчитать дельта-деформацию
  8. if (Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl [j - 1].row.displacement_z) > delta_def)
  9. delta_def = Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl [j - 1].row.displacement_z);
  1. mem_end_defs [i, 1] = mem_defs_glbl [j - 1].row.displacement_z;
  2. разрыв;
  3. }
  4. }

}

  1. /код#

Кроме определения деформаций, также рассчитывается переменная «delta_def», которая используется для критерия останова. Сначала рассчитывается разница от значения деформации предыдущей итерации (ноль в начале) и текущего значения. Из разности берется абсолютное значение, и затем находитс максимум. Как уже было показано в описании итерационного цикла, мы останавливаемся на значении меньшем, чем 0,0001 м (т.е. 0,1 мм).

В видео, прилагаемом к данной статье, можно увидеть, с одной стороны, фильтр нагрузок, а с другой, шаги итерации до упора. Наконец, найденная нагрузка будет отображена на изображении.

Интерфейс веб-сервис предлагает в RFEM 6/RSTAB 9 множество возможностей для изменения элементов, а также для считывания результатов. С его помощью можно реализовать множество различных проектов. Программа, представленная в нашей статье, включает в себя из множества различных элементов только первый шаг:

  1. Выбрать выбранные элементы
  2. Создание нагрузок
  3. Получить и отфильтровать результаты
  4. Фильтровать элементы по комментариям
  5. Удалить элементы

Благодаря такому разнообразию. программа также может служить образцом для других проектов.


Автор

Г-н Гюнтель осуществляет техническую поддержку пользователей Dlubal Software.

Скачивания


;