Навигация:
<< >> Оглавление Указатель
Текст С++

Руководство программиста

Глава 2. Создание моделей блоков

§2.14. Программное управление расчетом

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

§2.14.1. Запуск и остановка расчета

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

Из всех функций управления расчетом чаще всего используется функция остановки расчета rdsStopCalc. Обычно пользователь запускает расчет самостоятельно, после чего один из блоков схемы останавливает его, когда результат расчета получен. Например, стандартный блок управления динамическим расчетом (планировщик) может останавливать расчет по истечении заданного в его настройках времени, стандартный блок параметрической оптимизации останавливает расчет тогда, когда значения оптимизируемых параметров определены с заданной точностью, и т.д. Необходимость в программном запуске расчета функцией rdsStartCalc возникает значительно реже, однако, в некоторых случаях, она позволяет сделать работу со схемой более удобной. Например, если моделируемая система состоит из нескольких схем, работающих на разных машинах и обменивающихся данными по сети, имеет смысл при запуске расчета в одной из таких схем автоматически запускать расчет во всех остальных, иначе пользователю придется постоянно перемещаться от машины к машине и запускать расчет каждой из схем вручную. Возможны и другие случаи, когда программный запуск расчета может быть полезен: блок может запустить расчет сразу после загрузки схемы, при срабатывании какого-либо аппаратного устройства и т.п.

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

Напишем модель, которая будет запускать и останавливать расчет по щелчку мыши на изображении блока, а также останавливать расчет по сигналу, поступившему на вход (очевидно, запускать расчет по сигналу не получится, поскольку при остановленном расчете данные по связям не передаются). Поскольку никаких других входов, кроме сигнального входа остановки расчета, у нашего блока не будет, в качестве этого входа можно использовать фиксированный сигнал запуска модели блока. Обычно он называется Start, но мы переименуем его в Stop, поскольку подача на него сигнала будет приводить к остановке расчета. Таким образом, блок будет иметь следующую структуру переменных:

Смещение Имя Тип Размер Вход/выход Пуск Начальное значение
0 Start Stop 1 Вход 0
1 Ready Сигнал 1 Выход 0

Выходной сигнал Ready нам, в данном случае, не нужен, но этот выход должен обязательно присутствовать в любом простом блоке RDS, поэтому удалить его мы не сможем. При поступлении сигнала на вход Stop модель автоматически запустится, поэтому в реакции на такт расчета RDS_BFM_MODEL нужно просто вызвать функцию без каких-либо проверок. Разумеется, в параметрах блока нужно отключить флаг запуска каждый такт, иначе он будет останавливать расчет постоянно, независимо от значения входа Stop.

Сама модель будет достаточно простой:

  extern "C" __declspec(dllexport)
    int  StopCalc(int CallMode,
         BlockData,
         ExtParam)
  { switch(CallMode)
      { case : // Один такт расчета
          ();
          break;
        case : // Нажатие кнопки мыши
        case : // Вызов функции настройки
          if(()) // Расчет сейчас запущен
            ();
          else // Расчет сейчас остановлен
            ();
          break;
      }
    return ;
  }
  //=========================================

В такте расчета, как и было написано выше, мы просто останавливаем расчет: если модель запустилась в этом режиме, значит, на первый сигнальный вход пришел сигнал, а этот вход мы используем для остановки расчета. Мы не обнуляем сигнал Stop после срабатывания, как мы это делали с другими сигнальными входами, поскольку первый сигнальный вход блока обнуляется автоматически при запуске модели. Если пользователь нажал на изображении блока кнопку мыши (режим RDS_BFM_MOUSEDOWN) или в режиме редактирования вызвал функцию настройки (RDS_BFM_SETUP), вызывается сервисная функция rdsCalcProcessIsRunning, которая возвращает TRUE, если расчет в данный момент работает, и FALSE, если он остановлен. Если расчет работает, мы его останавливаем, если нет – запускаем. Таким образом, нажатие кнопки мыши будет то запускать, то останавливать расчет.

Реакция на вызов функции настройки добавлена в модель для того, чтобы блок мог запустить расчет в режиме редактирования. Если разрешить в параметрах блока с этой моделью вызов функции настройки (см. рис. 7) и назвать ее «Запустить расчет», выбор пункта контекстного меню с этим названием приведет к вызову модели в режиме . В этот момент, поскольку RDS находится в режиме редактирования, расчет работать не будет, вернет FALSE, и расчет будет запущен вызовом .

Тестирование блока запуска и остановки расчета

Рис. 93. Тестирование блока
запуска и остановки расчета

Для тестирования этого блока можно подключить к его входу «Stop» выход «Click» стандартной кнопки из библиотеки RDS (рис. 93) и разрешить в параметрах блока реакцию на мышь. Теперь нажатие на кнопку при работающем расчете приведет к его остановке. Нажатие на изображение блока будет запускать расчет, если RDS находится в режиме моделирования, или останавливать его, если RDS находится в режиме расчета.


<< >> Оглавление Указатель