Введение в ActiveField
Обзор объектов
Диаграмма иерархии
С чего начать
Работа с задачами
Работа с моделью
Работа с данными
Анализ результатов

Подковообразный магнит
Урок 1: Использование существующей задачи

Есть две версии этого примера:

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

Шаг 1: Создание нового проекта Visual Basic

Начальные шаги в Visual Basic такие же, как и при создании любого другого проекта. Запустите Visual Basic 6.0 и выберите New Standard EXE в диалоговом окне New Project.

Новый проект содержит одну форму Form. В этом уроке показано, как создать очень простой проект с минимальным интерфейсом пользователя. Весь код помещается в функцию Form_Load ().

Sub Form_Load ()
    ' Здесь мы напишем код
End Sub

Процедура Form_Load () вызывается исполняющей средой VB сразу после запуска нашего приложения, до того, как форма появится на экране.

Если создавать проект в Visual Basic for Application, который является частью Microsoft Office, то сначала надо запустить какое-нибудь приложение MS Office, например MS Excel. Потом надо запустить редактор VBA (команда Tools->Macro->Visual Basic Editor).

Не имеет значение, к какому обекту Excel написать код. Например, напишем код в модуле ThisWorkbook. В отличии от VB, здесь необходимо написать начальные строки самим, так как это показано на картинке.

Когда проект создан, необходимо сказать Basic об объектах, которые будут использоваться. Вся информация необходимая для работы с объектами ELCUT хранится в библиотеке типов ELCUT (файл ActiveField.dll). Эта библиотека регистрируется в системе при установке ELCUT (версии 5.1 и выше). Чтобы добавить в проект ссылку на библиотеку типов, выберите команду Project->References в VB или Tools->References в VBA. Потом в диалоговом окне в списке библиотек найдите строку ELCUT Object Library и установите ей флажок.

Теперь сохраним проект. Чтобы сделать это в VB, сохраните проект и все сопутствующие файлы. В VBA надо сохранить документ MS Office, который является контейнером для VBA кода (в нашем случае это Magn1_VBA.xls).

Шаг 2: Запуск ELCUT.

Теперь всё готово для работы с объектами ELCUT. Самый первый объект, который всегда используется это ELCUT.Application. Объект Application предоставляет доступ ко всем другим объектам, поэтому его можно объявить как глобальную переменную.

Public ELC As ELCUT.Application

Sub MyMacro()
    ' Здесь мы напишем код
   Set ELC = CreateObject("ELCUT.Application")
    ELC.MainWindow.Visible = True
End Sub

В первой строчке описывается глобальная переменная ELC, которая представляет объект Application. Если ELCUT уже запущен, то стандартная функция Visual Basic CreateObject возвращает запущенный ELCUT. Если же ELCUT еще не запущен, то функция его запустит.

Попробуйте запустить написанный выше код. В учебных целях наиболее походящий способ работы это выполнение кода строчка за строчкой в режиме отладки. Пожалуйста, выберите Debig->Step Into или просто нажмите F8, чтобы перейти к следующей строке кода.

Если ELCUT не был запущен до этого или находился в невидимом режиме, то на экране окна видно не будет. Последняя строчка кода делает ELCUT видимым. При запуске этой строчки окно ELCUT появляется на экране. Заметьте, что используется свойство Visibe объекта, представляющего главное окно ELCUT, который в свою очередь доступен через свойство MainWindow объекта Application.

Если Вы не знакомы с такими понятиями как объекты их методы и свойства, возможно лучшим для Вас будет просмотреть книгу или файл помощи по программированию в Microsoft Excel (или любому другому приложению поддерживающего программирование на VB). Вы увидите, как такие хорошо знакомые вещи, как книга, лист, и ячейка могут быть представлены как объекты, и как ими можно управлять.

Шаг 3: Открытие существующей задачи ELCUT.

Когда у нас есть объект Application, то открыть документ ELCUT это очень простая задача. Есть несколько коллекций документов, по одной для каждого типа документа. Взгляните на следующий код:

Public ELC As ELCUT.Application

Sub MyMacro()
    ' Здесь мы напишем код
    Set ELC = CreateObject("ELCUT.Application")
    ELC.MainWindow.Visible = True

    ' Октрываем задачу Magn1.pbm
    Dim prb As ELCUT.Problem
    Set prb = ELC.Problems.Open ("H:\ELCUT\Examples\Magn1.pbm")

    End Sub

В первой выделенной жирно строке описывается переменная prb типа ELCUT.Problem. Она становится новой задачей, загружаемой из файла Magn1.pbm.

Параметр метода Open задает полное имя задачи. Другая возможность сначала задать путь к папке в свойстве DefaultFilePath:

ELC.DefaultFilePath = "H:\ELCUT\Examples"
Set prb = ELC.Problems.Open ("Magn1.pbm")

Шаг 4: Изменение геометрической модели.

Через графический интерфейс пользователя модель загружается для редактирования из дерева задачи. Работая с объектной моделью, мы делаем почти тоже самое. Метод LoadModel загружает модель (объект Model), связанную с задачей. Теперь модель доступна через свойство Model.

Стоит поместить код, в котором происходит изменение геометрической модели, в отдельную процедуру, чтобы запускать его с различными параметрами.

Объявим переменную типа ELCUT.Model, которая будет хранить модель (объект Model). Потом получим геометрическую модель, используя метод LoadModel и свойство Model объекта Problem.

Sub MoveKeeper(prb As ELCUT.Problem, _
ByVal left As Double, ByVal bottom As Double)

Dim mdl As ELCUT.Model       ' геометрическая модель
prb.LoadModel
Set mdl = prb.Model

'    Коллекция Shapes, содержащая
'    все геометрические объекты в модели и
'     предоставляющая методы для добавления рёбер и вершин

With mdl.Shapes
    .RemoveMesh
    '    Удаление старого блока Steel Keeper
    .LabeledAs(Block:="Steel Keeper").Delete
    '    и создание нового:
    .AddEdge ELC.PointXY(left, bottom), _
            ELC.PointXY(left, bottom + skHigh)
    .AddEdge ELC.PointXY(left, bottom + skHigh), _
            ELC.PointXY(left + skWidth, bottom + skHigh)
    .AddEdge ELC.PointXY(left + skWidth, bottom + skHigh), _
            ELC.PointXY(left + skWidth, bottom)
    .AddEdge ELC.PointXY(left + skWidth, bottom), _
            ELC.PointXY(left, bottom)
    '    Определение позиции нового блока и присвоение еу метки
    .Nearest(ELC.PointXY(left + skWidth / 2, _
            bottom + skHigh / 2)).Blocks.Label = "Steel Keeper"
    .BuildMesh
End With

mdl.Save
mdl.Close

End Sub

Большинство операций с моделью проводятся через коллекцию Shapes, которая содержит все геометрические объекты модели. Чтобы сделать текст программы более простым, поместим несколько строчек в оператор With. Метод Delete удаляет блок, помеченный как "Steel Keeper". Обратите внимание на то, как был указан блок: свойство LabeledAs возвращает коллекцию объектов с одинаковой меткой - точно так же, как если щелкнуть мышкой по метке в дереве задачи.

Потом мы добавили 4 ребра и получили прямоугольный блок. Для обозначения размеров использовались параметры left и bottom (тип Double), задающие позицию блока и локальные переменные skWidth и skHigh, задающие размеры блока. Заметьте, что метод AddEdge требует два параметра типа Point. Мы задействовали дополнительный метод PointXY объекта Application, чтобы создать новую точку (объект Point) с нужными координатами.

Когда ребра построены, необходимо присвоить метку вновь созданному блоку. Самый удобный способ указать блок это использовать свойство Nearest, которое возвращает ближайший блок (объект Block), ребро (объект Edge) и вершину (объект Vertex) к данной точке. Свойство Label возвращает и устанавливает метку геометрическому объекту.

Перед тем как закончить с геометрической моделью, мы построим сетку конечных элементов (метод BuildMesh) и потом сохраним и закроем модель.

Шаг 5: Изменение физических свойств.

Представим, то надо изучить влияние коэрцитивной силы магнита АЛНИКО на механическую силу. В этом случае потребуется изменить свойства метки. Процедура, устанавливающая заданную величину коэрцитивной силы для обеих меток магнитов "ALNICO up" и "ALNICO down", показана ниже.

Sub SetCoerciveForce(prb As ELCUT.Problem, ByVal Hc As Double)
    '    Переменные для хранения метки и её содержимого
    Dim lab As ELCUT.Label
    Dim labCnt As LabelBlockMS

    '    Получение желаемой метки
    Set lab = prb.Labels(qfBlock).Item("ALNICO up")
    '    Получение содержимого метки для редактирования
    Set labCnt = lab.Content
    '    Изменение содержимого метки
    labCnt.Coercive = ELC.PointRA(Hc, PI / 2)
    '    Возвращение измененного содержимого метки обратно метке
    lab.Content = labCnt

    '    Тоже самое для другой метки
    Set lab = prb.Labels(qfBlock).Item("ALNICO down")
    Set labCnt = lab.Content
    labCnt.Coercive = ELC.PointRA(Hc, -PI / 2)
    lab.Content = labCnt
    '    Сохраниние файла описания свойств
    lab.DataDoc.Save
End Sub

Самый главный объект здесь это объект Label и его содержимое (в нашем случае LabelBlockMS). Чтобы изменить физические данные, необходимо найти метку в одной из коллекций Labels, получить содержимое метки, используя свойство Contents, изменить это содержимое (объект Content) и вернуть его обратно объекту Label.

Точный тип объекта Content зависит от типа задачи (электростатика, теплопередача и другие). В нашем примере решается задача магнитостатики, так что содержимое имеет тип LabelBlockMS.

Закончив редактирование меток, следует сохранить соответствующий файл описания свойств. Каждая метка "знает" к какому документу она принадлежит (свойство DataDoc).

Шаг 6: Решение задачи.

Когда модель и физические свойства готовы, а соответствующие файлы сохранены, можно запустить процесс решения. Самый простой способ сделать это использовать метод SolveProblem объекта Problem. Можно проверить, готовы ли модель и физически свойства, перед тем как решать задачу. Свойство CalSolve объекта Problem возвращает True если всё нормально. Свойство Solved позволяет узнать решена ли задача или нет.

If prb.CanSolve Then prb.SolveProblem
If prb.Solved Then prb.AnalyzeResults

Этот подход можно использовать, если время решения короткое. Когда процесс решения занимает несколько минут и более, удобнее использовать асинхронную версию метода SolveProblem:

prb.SolveProblem True

Установим параметру NoWait значение True, вместо False, используемого по умолчанию. В этом случае метод SolveProblem возвращает управление сразу после запуска процесса решения. Можно проконтролировать процесс решения, используя специальный объект SolvingState:

Dim state As ELCUT.SolvingState
Set state = prb.SolveProblem(True)

Шаг 7: Анализ результатов: вычисление локальных и интегральных величин.

Когда задача решена, можно посмотреть результаты. Для этого используйте метод AnalyzeResults объекта Problem. После этого можно получить объект Result, позволяющий работать с графиками, таблицами и окнами для показа результатов. Объект Result содержит коллекцию окон. Это окна картины поля (объект FieldWindow), окна графиков (объект XYPlotWindow) и окна таблиц (объект TableWindow).

Как и при работе с графическим интерфейсом пользователя, можно построить контур (объект Contour) в окне картины поля (объект FieldWindow), который может быть использован для вычисления интегралов, построения графиков и таблиц.

Код, вычисляющий силу, помещен в отдельную функцию CalculateForce:

    ..........
If prb.Solved Then prb.AnalyzeResults
force = CalculateForce(prb.Result, xPos, yPos)
    ...........

Function CalculateForce(res As ELCUT.Result, _
                ByVal left As Double, ByVal bottom As Double) As Double
    Dim win As FieldWindow
    Set win = res.Windows(1)
    With win.Contour
        .AddLineTo ELC.PointXY(left - 5, bottom - 0.5)
        .AddLineTo ELC.PointXY(left + skWidth + 5, bottom - 0.5)
        .AddLineTo ELC.PointXY(left + skWidth + 5, bottom + skHigh + 5)
        .AddLineTo ELC.PointXY(left - 5, bottom + skHigh + 5)
        .AddLineTo
    End With
    CalculateForce = res.GetIntegral(qfInt_MaxwellForce).Abs
End Function

У объекта Result мы получили первое окно с картиной поля (активное окно всегда первое в коллекции) и построили в нем контур (объект Contour), окружающий якорь. Чтобы добавить линию к контуру, использовался метод AddLineTo. Последний вызов этого метода без параметров замыкает контур.

Замкнув контур можно вычислить силу, действующую на тела внутри контура. Чтобы сделать это, используем метод GetIntegral объекта Problem. Метод возвращает интегральную величину типа Quantity, которая объединяет физические величины нескольких типов. Свойство Abs объекта Quantity возвращает абсолютную величину.

Заключение

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

При нажатии на кнопку Start запускается процедура DoCalculation:

Public Sub DoCalculation(Hc As Double, _
        Ymin As Double, YMax As Double, Step As Double)
    Set ELC = CreateObject("ELCUT.Application")
    ELC.MainWindow.Visible = True
   
        ' Открываем задачу Magn1.pbm
    Dim prb As ELCUT.Problem
        ' Предполагается, что файлы находятся
        ' в папке Magn1 внутри рабочей папки проекта

    ELC.DefaultFilePath = VB.App.Path & "\Magn1"
    Set prb = ELC.Problems.Open("Magn1.pbm")

    '    Изменение физических свойств
    '    смотрите Шаг 5

    SetCoerciveForce prb, Hc

    Dim yPos As Double, xPos As Double ' Позиция якоря
    Dim force As Double ' Механическая сила
    Dim i As Integer ' Счетчик цикла
    For i = 1 To (YMax - Ymin) / Step + 1
        ' Изменение позиции якоря
        xPos = XposBase
        yPos = YposBase + Ymin + Step * (i - 1)
            ' Изменение геометрической модели.
            ' смотрите шаг 4

        MoveKeeper prb, xPos, yPos

            ' Решение задачи
            ' смотрите шаг 6

        If prb.CanSolve Then prb.SolveProblem
        If prb.Solved Then
                ' Анализ результатов
                ' смотрите шаг 7

            prb.AnalyzeResults
            force = CalculateForce(prb.Result, xPos, yPos)
        End If
            ' Печать строки результатов на экране
        MainDialog.DisplayStepResult yPos, force
    Next

        ' Завершение работы ELCUT
    ELC.Quit
    Set ELC = Nothing
End Sub

Закончив работу с ELCUT, надо закрыть приложение. Метод Quit объекта Application, работает почти также, как команда Файл->Выход.