Объект UserFunction представляет собой интерфейс для вычисления функции, заданной пользователем. В ELCUT 6.2 функция, заданная пользователем, используется в качестве подынтегрального выражения при вычислении пользовательских интегралов методами GetCustomIntegral и GetCustomIntegralTotal объекта Result.
ELCUT не содержит объекта, реализующего этот интерфейс. Напротив, пользователь, желающий вычислить пользовательский интеграл, реализует интерфейс в своей программе.
Интерфейс UserFunction содержит единственный метод:
Sub GetValue(point, bodyLabel, val)
c двумя входными параметрами point, bodyLabel и одним выходным параметром
val.
В языке Visula Basic (и VBA - Visual Basic for Application) все три параметра должны иметь описатель ByVal.
Вычисленное значение val имеет тип Quantity, который является контейнером для физических величин разного типа: скалярных, комплексных, векторных и др.
|
Параметр point типа FieldPoint |
Передает координаты точки, в которой требуется вычислить значение функции, и локальные значения поля в этой точке. Параметр представляет собой объект типа FieldPoint или производный от него (FieldPointES, FieldPointCF, FieldPointTE, FieldPointTV, FieldPointHE, FieldPointSA, FieldPointEC) в зависимости от типа задачи. |
|
Параметр bodyLabel - текстовая строка |
содержит метку текущего блока, через который проходит контур интегрирования |
|
Вычисленное значение val типа Quantity |
Вычисленное значение функции пользователь должен поместить в объект типа Quantity, содержащий информацию о типе и величине. Функция GetValue не должен создавать новый объект Quantity или заботиться об его удалении. Создание и удаление делается в вызывающем коде. |
В следующем примере показан пример UserFunction, реализующий вычисление потерь в ферромагнитном середечнике по формуле Штейнмеца:
p=kloss·Bmα·fβ,
где p - плотность потерь, Bm - максимальная величина магнитной индукции, f - частота, kloss, α, β - константы, зависящие от свойств материала и характера изменения магнитного поля.
Первый вариант реализован на языке Visual Basic for Appliation (VBA) в среде MS Excel. Приведенный код должен располагаться в отдельном Class Module, который в нашем примере имеет имя LossFunction. Модуль класса нужно снабдить аттрибутом Instancing = 2 (PublicNotCreatable) в окне свойств модуля.
Option Explicit
Implements ELCUT.UserFunction
Public pbm As ELCUT.Application
Public Sub UserFunction_GetValue(ByVal Point As ELCUT.FieldPoint, ByVal bodyLabel As String,
ByVal pVal As ELCUT.Quantity)
' приводим параметр Point из базового типа FieldPoint к производному типу FieldPointHE,
' который соотвествует типу решаемой задачи
Dim pointHE As ELCUT.FieldPointHE
Set pointHE = Point
' константы для вычисления потерь по формуле Штейнмеца
Const lossFactor As Double = 0.12345
Const alpha As Double = 2.05
Const beta As Double = 1.3
Const frequency As Double = 50
Dim B As Double
Dim lossDensity As Double
' для вычисления функции нам нужна максимальная величина магнитной индукции:
B = pointHE.FluxDensity.Magnitude.R
lossDensity = lossFactor * WorksheetFunction.Power(frequency, beta) * WorksheetFunction.Power(B, alpha)
' запоминаем вычисленное значение в качестве возвращаемого значения функции
pVal.SetAsScalar lossDensity
End Sub
Cледующий фрагмент кода вычисляет пользовательский интеграл по объему, с использованием переопределенной UserFunction:
Dim flag As Long ' флаг необходим для вызова подынтегральной функции
Dim q As ELCUT.Quantity ' результат вычисления интегрального значения
Dim res As Double '
flag = 0
Set myFunc = New VBAProject.LossFunction '
здесь LossFunction - имя Class Module, в котором описана наша реализация интерфейса UserFunction
Set q = res.GetCustomIntegral(myFunc, qfOverVolume, cnt)
' вызов метода вычисления пользовательского
интеграла по объему, ограниченному замкнутым контуром
Второй вариант реализован на языке C#. Простая реализация интерфейса UserFunction може выглядеть следующим образом:
class CoreLoss : ELCUT.UserFunction
{
public void GetValue(ELCUT.FieldPoint point, string blockLabel, ref ELCUT.Quantity res)
{
const double lossFactor = 0.12345;
const double alpha = 2.05;
const double beta = 1.3;
const double frequency = 50;
var pointHE = point as FieldPointHE;
double B = pointHE.FluxDensity.Magnitude.R;
double val = lossFactor * Math.Pow(frequency, beta) * Math.Pow(B, alpha);
res.SetAsScalar(val);
}
}
Для вычисления пользовательского интеграла по объему, ограниченному замкнутым контуром, нужно создать новый экземпляр класса, реализующего интерефейс ELCUT.UserFunction, и передать его при вызове метода GetCustomIntegral класса ELCUT.Result:
var myUserFunc = new CoreLoss();
double custom = res.GetCustomIntegral(myUserFunc, qfOverVolume, cont, 0).Abs;