unit Nolines; {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Н Е Л И Н Е Й Н Ы Е Б Л О К И !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} interface uses WinTypes,WinProcs,SysUtils,GlType,GlProc,MathObj,Math,Srcs, Classes,MVTU_TLB; function TNoLin0(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin1(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin2(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin3(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin4(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin5(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin6(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin7(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin8(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin9(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin10(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin11(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin12(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin13(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin14(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin15(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin16(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin17(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin18(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin19(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TImpulse(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin20(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin21(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TRemember(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TTimeRemember(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin22(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNoLin5Rst(at,adt:RealType;var AU,AY:TPtrExt;var AX,ADX:PExtArr; var Prop:TPtrArray;var Vars : Pointer;Action:Integer;var F:File):Integer;export; function TNoLin15Rst(at,adt:RealType;var AU,AY:TPtrExt;var AX,ADX:PExtArr; var Prop:TPtrArray;var Vars : Pointer;Action:Integer;var F:File):Integer;export; type PNoLine2Rec = ^TNoLine2Rec; TNoLine2Rec = record Parms : TExtArray; Y0 : TExtArray end; {********************************************************************************************************} IMPLEMENTATION {********************************************************************************************************} type PNoLine5Rec = ^TNoLine5Rec; TNoLine5Rec = record Tau : TExtArray; PntCnt : ^Integer end; PNoLine20Rec = ^TNoLine20Rec; TNoLine20Rec = record Y0 : TExtArray end; PNoLine5Var = ^TNoLine5Var; TNoLine5Var = record Ind, count : Integer; Stack_x, Stack_t : TExtArray; Stack_u : TExtArray2; end; PNoLine15Var = ^TNoLine15Var; TNoLine15Var = record tau0 : RealType; count : Integer; St_I : TIntArray; St_x : TExtArray; St_u, St_t : TPtrExt; end; PDelayRec = ^TDelayRec; TDelayRec = record Lam : TExtArray; PntCnt : ^Integer end; PNoLin18Rec = ^TNoLin18Rec; TNoLin18Rec = record inp : ^Integer; what : ^Integer end; PImpulseRec = ^TImpulseRec; TImpulseRec = record tFun : ^Integer; tau : TExtArray; Y0 : TExtArray end; PImpulseVar = ^TImpulseVar; TImpulseVar = record ptau : TExtArray; end; PRememberRec = ^TRememberRec; TRememberRec = record N : ^Integer; end; {--------------------------------------------------------------------------- ЛИНЕЙНОЕ С НАСЫЩЕНИЕМ - Блок реализует нелинейную статическую характеристику типа "насыщение": y(t) = K*x(t), если a < x(t) < b; y(t) = y1, если x(t) <= a; y(t) = y2, если x(t) >= b, где К = (y2-y1)/(b-a). Для работы блока необходимо задать параметры a, b, y1, y2. ---------------------------------------------------------------------------} function TNoLin0Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Линейное с насыщением'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'a',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'b',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'y1',PChar(SL[2]),Res); MVTU.SetBlockProp(BlockId,'y2',PChar(SL[3]),Res); finally SL.Free; end; end; end; function TNoLin0; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin0Convert); f_EditErr : if (arr^[1]-arr^[0]) = 0 then Result:=er_parzerodif; f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_InitState, f_UpdateJacoby, f_RestoreOuts, f_UpdateOuts, f_GoodStep : for j:=0 to AY.Ptr(0).Count-1 do if AU.Ptr(0).arr^[j] <= arr^[0] then AY.Ptr(0).arr^[j]:=arr^[2] else if AU.Ptr(0).arr^[j] >= arr^[1] then AY.Ptr(0).arr^[j]:=arr^[3] else AY.Ptr(0).arr^[j]:=arr^[2]+(arr^[3]-arr^[2])/(arr^[1]-arr^[0])*(AU.Ptr(0).arr^[j]-arr^[0]); end{END CASE} end;{END TNoLin0} {--------------------------------------------------------------------------- Линейное с насыщением и зоной нечувствительности Блок реализует нелинейную статическую характеристику по следующему алгоритму: y(t) = y1, если x(t) <= a1; y(t) = K1*[a - x(t)], если a1 < x(t) < a;K1=y1/[a-a1] y(t) = 0, если a <= x(t) <= b; y(t) = K2*[x(t) - b], если b < x(t) < b1;K2=y2/[b1-b] y(t) = y2, если x(t) >= b1. Для работы блока необходимо задать параметры a1, a, b, b1, y1, y2. ---------------------------------------------------------------------------} function TNoLin1Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Линейное с насыщением и зоной нечувствительности'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'a1',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'a',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'b',PChar(SL[2]),Res); MVTU.SetBlockProp(BlockId,'b1',PChar(SL[3]),Res); MVTU.SetBlockProp(BlockId,'y1',PChar(SL[4]),Res); MVTU.SetBlockProp(BlockId,'y2',PChar(SL[5]),Res); finally SL.Free; end; end; end; function TNoLin1; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin1Convert); f_EditErr : if ((arr^[1]-arr^[0]) = 0)or((arr^[3]-arr^[2]) = 0) then Result:=er_parzerodif; f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_InitState, f_UpdateJacoby, f_RestoreOuts, f_UpdateOuts, f_GoodStep : for j:=0 to AY.Ptr(0).Count-1 do if AU.Ptr(0).arr^[j] <= arr^[0] then AY.Ptr(0).arr^[j]:=arr^[4] else if AU.Ptr(0).arr^[j] >= arr^[3] then AY.Ptr(0).arr^[j]:=arr^[5] else if (AU.Ptr(0).arr^[j] > arr^[0]) and (AU.Ptr(0).arr^[j] < arr^[1]) then AY.Ptr(0).arr^[j]:=arr^[4]*(arr^[1]-AU.Ptr(0).arr^[j])/(arr^[1]-arr^[0]) else if (AU.Ptr(0).arr^[j] > arr^[2]) and (AU.Ptr(0).arr^[j] < arr^[3]) then AY.Ptr(0).arr^[j]:=arr^[5]*(AU.Ptr(0).arr^[j]-arr^[2])/(arr^[3]-arr^[2]) else AY.Ptr(0).arr^[j]:=0; end{END CASE} end;{END TNoLin1} {--------------------------------------------------------------------------- Релейное неоднозначное Блок реализует нелинейную статическую характеристикуку типа "двухпозиционное реле" по следующему алгоритму: y(t) = y1, если x(t) < a; y(t) = y(t - dt), если a <= x(t) <= b; y(t) = y2, если x(t) > b, где dt - предыдущий временной шаг интегрирования. Для работы блока необходимо задать параметры a, b, y1, y2 и начальное состояние реле y(0). ---------------------------------------------------------------------------} function TNoLin2Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Релейное неоднозначное (гистерезис)'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'a',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'b',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'y1',PChar(SL[2]),Res); MVTU.SetBlockProp(BlockId,'y2',PChar(SL[3]),Res); MVTU.SetBlockProp(BlockId,'y0',PChar(ConvertVector(PropStr[1])),Res); finally SL.Free; end; end; end; function TNoLin2; var j : Integer; begin Result:=0; with PNoLine2Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin2Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Y0.Count; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_InitMem, f_InitState : Move(Y0.arr^,AY.Ptr(0).arr^,Y0.Count*SOfR); { f_UpdateOuts,} f_GoodStep : for j:=0 to Y0.Count-1 do with Parms do if AU.Ptr(0).arr^[j] < arr^[0] then AY.Ptr(0).arr^[j]:=arr^[2] else if AU.Ptr(0).arr^[j] > arr^[1] then AY.Ptr(0).arr^[j]:=arr^[3]; { else AY.Ptr(0).arr^[j]:=AX[j];} f_RestoreOuts: for j:=0 to Y0.Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; // f_SteadyState, f_GetState : for j:=0 to Y0.Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; end{END CASE} end;{END TNoLin2} {--------------------------------------------------------------------------- Релейная неоднозначная с зоной нечувствительности Блок реализует нелинейную статическую характеристику типа "трехпозиционное реле" по следующему алгоритму: y(t) = y1, если x(t) < a1; y(t) = 0, если a2 < x(t) < b1; y(t) = y(t - dt), если a1 <= x(t) <= a2, или, если b1 <= x(t) <= b2; y(t) = y2, если x(t) > b2; Для работы блока необходимо задать параметры нелинейности a1, a2, b1, b2, y1, y2 и начальное состояние реле y(0). ---------------------------------------------------------------------------} function TNoLin3Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Релейное c зоной нечувствительности'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'a1',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'a',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'b',PChar(SL[2]),Res); MVTU.SetBlockProp(BlockId,'b1',PChar(SL[3]),Res); MVTU.SetBlockProp(BlockId,'y1',PChar(SL[4]),Res); MVTU.SetBlockProp(BlockId,'y2',PChar(SL[5]),Res); MVTU.SetBlockProp(BlockId,'y0',PChar(ConvertVector(PropStr[1])),Res); finally SL.Free; end; end; end; function TNoLin3; var j : Integer; u,y : RealType; y_0 : RealType; begin Result:=0; with PNoLine2Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin3Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Y0.Count; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_InitState : for j:=0 to Y0.Count - 1 do begin AX[j]:=Y0.arr^[j]; with Parms do begin if AX[j] > 0 then AY.Ptr(0).arr^[j]:=arr^[5] else if AX[j] < 0 then AY.Ptr(0).arr^[j]:=arr^[4] else AY.Ptr(0).arr^[j]:=0; end; end; f_RestoreOuts: for j:=0 to Y0.Count-1 do with Parms do begin if AX[j] > 0 then AY.Ptr(0).arr^[j]:=arr^[5] else if AX[j] < 0 then AY.Ptr(0).arr^[j]:=arr^[4] else AY.Ptr(0).arr^[j]:=0; end; f_GoodStep : for j:=0 to Y0.Count-1 do with Parms do begin u:=AU.Ptr(0).arr^[j]; y_0:=AX[j]; if u < arr^[0] then y:=-1 else if u > arr^[3] then y:=1 else if ((y_0 < 0) and (u > arr^[1])) or ((y_0 > 0) and (u < arr^[2])) then y:=0 else y:=y_0; if y < 0 then AY.Ptr(0).arr^[j]:=arr^[4] else if y > 0 then AY.Ptr(0).arr^[j]:=arr^[5] else AY.Ptr(0).arr^[j]:=0; AX[j]:=y; end end{END CASE} end;{END TNoLin3} {--------------------------------------------------------------------------- Линейное с зоной нечувствительности Блок реализует нелинейную статическую характеристику по следующему алгоритму: y(t) = K*[x(t) - a], если x(t) < a; y(t) = 0, если a <= x(t) <= b; y(t) = K*[x(t) - b], если x(t) > b. Для работы блока необходимо задать параметры a, b и К. ---------------------------------------------------------------------------} function TNoLin4Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Линейное с зоной нечувствительности'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'a',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'b',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'k',PChar(SL[2]),Res); finally SL.Free; end; end; end; function TNoLin4; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin4Convert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_InitState, f_UpdateJacoby, f_UpdateOuts, f_RestoreOuts, f_GoodStep : for j:=0 to AY.Ptr(0).Count-1 do if AU.Ptr(0).arr^[j] < arr^[0] then AY.Ptr(0).arr^[j]:=arr^[2]*(AU.Ptr(0).arr^[j]-arr^[0]) else if AU.Ptr(0).arr^[j] > arr^[1] then AY.Ptr(0).arr^[j]:=arr^[2]*(AU.Ptr(0).arr^[j]-arr^[1]) else AY.Ptr(0).arr^[j]:=0; end{END CASE} end;{END TNoLin4} {--------------------------------------------------------------------------- Идеальное запаздывающее звено Блок реализует следующее преобразование сигналов: y(t) = x(t-T), где x(t) - входной сигнал; y(t) - выходной сигнал; T - постоянная запаздывания. Обязательное условие: T > 0. Для работы блока необходимо задать постоянную времени T и начальное условие y(0). ---------------------------------------------------------------------------} function TNoLin5Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Идеальное транспортное запаздывание'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'tau',PChar(ConvertVector(PropStr[0])),Res); MVTU.SetBlockProp(BlockId,'stacksize',PChar(PropStr[1]),Res); finally end; end; end; function TNoLin5; var i,m,j : Integer; s : RealType; begin Result:=0; with PNoLine5Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin5Convert); f_EditErr : for i:=0 to TAU.Count-1 do if TAU.arr^[i] <= 0 then Result:=er_parzeroneg; f_GetStateCount: Result:=1; f_GetCount : begin CY.arr^[0]:=Tau.Count; CU.arr^[0]:=Tau.Count end; f_Create : begin Vars:=New(PNoLine5Var); WITH PNoLine5Var(Vars)^ do begin count:=1; Stack_x:=TExtArray.Create(1); Stack_u:=TExtArray2.Create(Count,1); Stack_t:=TExtArray.Create(1) end end; f_Free : begin WITH PNoLine5Var(Vars)^ do begin Stack_u.Free; Stack_t.Free; Stack_x.Free end; Dispose(PNoLine5Var(Vars)) end; f_InitMem : WITH PNoLine5Var(Vars)^ do begin Stack_x.ChangeCount(Tau.Count); if (countStack_t.Count) then begin Stack_u.Free; Stack_t.Free; Stack_u:=TExtArray2.Create(Tau.Count,PntCnt^); Stack_t:=TExtArray.Create(PntCnt^); end; count:=Tau.Count; Ind:=0; end; f_InitState : WITH PNoLine5Var(Vars)^ do begin AX[0]:=0; Ind:=0; Stack_t.arr^[0]:=at; for j:=0 to Count-1 do Stack_u.z(j,Ind,AU.Ptr(0).arr^[j]); Move(AU.Ptr(0).arr^,AY.Ptr(0).arr^,Count*SOfR); Move(AU.Ptr(0).arr^,Stack_x.arr^,Count*SOfR) end; // f_SteadyState : WITH PNoLine5Var(Vars)^ do // Move(AU.Ptr(0).arr^,Stack_x.arr^,Count*SOfR); f_RestoreOuts : WITH PNoLine5Var(Vars)^ do Move(Stack_x.arr^,AY.Ptr(0).arr^,Count*SOfR); f_GetDelayTime: AX[0]:=TAU.arr^[round(adt)]; f_GoodStep, f_UpdateOuts : WITH PNoLine5Var(Vars)^ do begin for j:=0 to Count-1 do if at >= TAU.arr^[j] then AY.Ptr(0).arr^[j]:=GetVectorData(Ind,at-TAU.arr^[j], Stack_u.arr^[j].arr^,Stack_t.arr^); end; f_GetState : WITH PNoLine5Var(Vars)^ do begin {Запомнить время и входные сигналы в стеках } Inc (Ind) ; AX[0]:=Ind; Stack_t.arr^[Ind] := at; for j:=0 to Count-1 do Stack_u.z(j,Ind,AU.Ptr(0).arr^[j]); Move(AY.Ptr(0).arr^,Stack_x.arr^,Count*SOfR); {Изменение в случае необходимости размера стеков} if Ind >= Stack_t.Count-1 then begin s:=at; for j:=0 to Count-1 do s:=min(s,at-TAU.arr^[j]); i:=0; while (Stack_t.arr^[i] < s) and (i < Ind) do Inc(i); {убрать первые i у;е использованных элементов стеков} if i >= PntCnt^ then begin for m:=0 to Ind-i do begin Stack_t.arr^[m]:=Stack_t.arr^[m+i]; for j:=0 to Count-1 do with Stack_u.arr^[j] do arr^[m]:=arr^[m+i] end; Dec(Ind,i) end else if Stack_t.Count < ArraySize-PntCnt^ then begin //простое увеличение размера стека Stack_t.ChangeCount(Stack_t.Count+PntCnt^); Stack_u.ChangeCount(Stack_u.CountX,Stack_u.CountY+PntCnt^); end else begin //выбросить каждый второй элемент стеков i:=1;m:=2; repeat Stack_t.arr^[i] := Stack_t.arr^[m]; for j := 0 to Count-1 do Stack_u.z(j,i,Stack_u.val(j,m)); Inc(i,1);Inc(m,2); until m >= Stack_t.Count-1; Stack_t.ChangeCount(2*i); Stack_u.ChangeCount(Stack_u.CountX,2*i); Ind:=i end end end; end{END CASE} end;{END TNoLin5} function TNoLin5Rst; var i : Integer; begin Result:=0; with PNoLine5Rec(Prop.arr)^,PNoLine5Var(Vars)^ do case Action of f_ReadRez : try BlockRead(F,Count,SOfI); if Count > 0 then BlockRead(F,Stack_x.arr^,Count*SOfR); except Result:=er_ReadFile end; f_WriteRez : try BlockWrite(F,Count,SOfI); if Count > 0 then BlockWrite(F,Stack_x.arr^,Count*SOfR); except Result:=er_WriteFile end; f_ReadRst : try BlockRead(F,Ind,SOfI); BlockRead(F,Count,SOfI); if Count > 0 then begin Stack_x.ChangeCount(Count); BlockRead(F,Stack_x.arr^,Count*SOfR); end; Stack_t.ChangeCount(Ind+2); Stack_u.ChangeCount(Stack_u.CountX,Ind+2); if Ind >= 0 then begin BlockRead(F,Stack_t.arr^,(Ind+1)*SOfR); for i:=0 to Count-1 do BlockRead(F,Stack_u.arr^[i].arr^,(Ind+1)*SOfR); end except Result:=er_ReadFile end; f_WriteRst : try BlockWrite(F,Ind,SOfI); BlockWrite(F,Count,SOfI); if Count > 0 then BlockWrite(F,Stack_x.arr^,Count*SOfR); if Ind >= 0 then begin BlockWrite(F,Stack_t.arr^,(Ind+1)*SOfR); for i:=0 to Count-1 do BlockWrite(F,Stack_u.arr^[i].arr^,(Ind+1)*SOfR); end except Result:=er_WriteFile end; end end; {--------------------------------------------------------------------------- Переменное транспортное запаздывание Блок реализует звено с переменным запаздыванием и мо;ет использоваться, например, для моделирования процессов конвективного переноса в трубопроводе постоянного сечения с переменным во времени расходом (скоростью) при постоянной плотности потока: yi(t) = xi(t - T(t))*exp[-lam(i)*T(t)], где yi(t) - вектор выходного сигнала; xi(t) - вектор входного сигнала; T(t) - значение транспортного запаздывания. При ориентации блока слева-направо верхний порт - для ввода вектора входного сигнала, а ни;ний - для ввода запаздывания. Обязательное условие: T(t) > 0. Для работы блока необходимо задать значения начального вектора выхода (через пробел) yi(0). ---------------------------------------------------------------------------} function TNoLin15Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Переменное транспортное запаздывание'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'lam',PChar(ConvertVector(PropStr[0])),Res); MVTU.SetBlockProp(BlockId,'stacksize',PChar(PropStr[1]),Res); finally end; end; end; function TNoLin15; var i,m,j, c,k : Integer; px,py : PExtArr; x, xx : RealType; const {cnt = 10000;} x0 = 0.0; begin Result:=0; with PDelayRec(Prop.arr)^ do case Action of { f_GetDeriCount : Result:=0; f_GetInit : Result:=0; { f_GetDeri : if AU.Ptr(1).arr^[0] > 0 then ADX[0]:=1./AU.Ptr(1).arr^[0] else Result:=er_neginp;} f_GetConvertFuncAdr: Result:=integer(@TNoLin15Convert); f_GetStateCount : Result:=1; f_GetCount : begin CU.arr^[0]:=lam.Count; CY.arr^[0]:=lam.Count; CY.arr^[1]:=1; CU.arr^[1]:=1 end; f_Create : begin Vars:=New(PNoLine15Var); WITH PNoLine15Var(Vars)^ do begin count:=1; St_x:=TExtArray.Create(Count+1); st_I:=TIntArray.Create(Count+1); St_u:=TPtrExt.Create(Count+1,1); St_t:=TPtrExt.Create(Count+1,1); end end; f_Free : begin WITH PNoLine15Var(Vars)^ do begin for j:=0 to St_u.Count-1 do St_u.Ptr(j).Free; St_u.Free; for j:=0 to St_t.Count-1 do St_t.Ptr(j).Free; St_t.Free; St_I.Free; St_x.Free end; Dispose(PNoLine15Var(Vars)) end; f_InitMem : WITH PNoLine15Var(Vars)^ do begin St_x.ChangeCount(lam.Count+1); St_I.ChangeCount(lam.Count+1); FillChar(St_I.arr^,(lam.Count+1)*SOfI,0); if count < lam.Count then begin {count:=lam.Count;} for j:=0 to St_u.Count-1 do St_u.Ptr(j).Free; St_u.Free; for j:=0 to St_t.Count-1 do St_t.Ptr(j).Free; St_t.Free; St_u:=TPtrExt.Create(lam.Count+1,PntCnt^); St_t:=TPtrExt.Create(lam.Count+1,PntCnt^); end; Count:=lam.Count; if PntCnt^>St_t.Ptr(0).Count then for j:=0 to Count do begin St_t.Ptr(j).ChangeCount(PntCnt^); St_u.Ptr(j).ChangeCount(PntCnt^); end; end; f_InitState : WITH PNoLine15Var(Vars)^ do begin FillChar(St_I.arr^,(Count+1)*SOfI,0); AX[0]:=x0; tau0:=AU.Ptr(1).arr^[0]; AY.Ptr(1).arr^[0]:=tau0; for j:=0 to Count do St_t.Ptr(j).arr^[0] :=AX[0]; for j:=0 to Count-1 do begin St_u.Ptr(j).arr^[0]:=AU.Ptr(0).arr^[j]; AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]*exp(-lam.arr^[j]*tau0) end; St_u.Ptr(Count).arr^[0]:=at; Move(AY.Ptr(0).arr^,St_x.arr^,Count*SOfR); St_x.arr^[Count]:=AY.Ptr(1).arr^[0]; end; f_GetDelayTime: AX[0]:=AY.Ptr(1).arr^[0]; f_RestoreOuts : WITH PNoLine15Var(Vars)^ do begin Move(St_x.arr^,AY.Ptr(0).arr^,Count*SOfR); AY.Ptr(1).arr^[0]:=St_x.arr^[Count] end; f_GoodStep, f_UpdateOuts : WITH PNoLine15Var(Vars)^ do begin if AU.Ptr(1).arr^[0] > 0 then xx:=AX[0]+1./AU.Ptr(1).arr^[0]*adt else xx:=AX[0]; if xx >= x0+1.0 then begin i:=St_I.arr^[Count]; px:=St_t.Ptr(Count).arr; py:=St_u.Ptr(Count).arr; AY.Ptr(1).arr^[0]:=at-GetVectorData(i,xx-1,py^,px^); x:=xx-1; end else begin AY.Ptr(1).arr^[0]:=at-tau0*(xx-1); x:=x0; end; for j:=0 to Count-1 do begin i:=St_I.arr^[j]; px:=St_t.Ptr(j).arr; py:=St_u.Ptr(j).arr; AY.Ptr(0).arr^[j]:=GetVectorData(i,x,py^,px^); end; for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=AY.Ptr(0).arr^[j]* exp(-lam.arr^[j]*AY.Ptr(1).arr^[0]); if Action = f_GoodStep then if AU.Ptr(1).arr^[0] > 0 then AX[0]:=AX[0]+1./AU.Ptr(1).arr^[0]*adt else Result:=er_neginp; end; f_GetState : WITH PNoLine15Var(Vars)^ do begin {Запомнить время и входные сигналы в стеках } Move(AY.Ptr(0).arr^,St_x.arr^,Count*SOfR); St_x.arr^[Count]:=AY.Ptr(1).arr^[0]; for j:=0 to Count do begin i:=St_I.arr^[j]; px:=St_t.Ptr(j).arr; py:=St_u.Ptr(j).arr; if j = Count then x:=at else x:=AU.Ptr(0).arr^[j]; St_I.arr^[j]:=UpdateStack(i,AX[0],x,px,py,0.001); end; //Изменение в случае необходимости размера стеков for j:=0 to Count do begin k:=St_I.arr^[j]; c:=St_t.Ptr(j).Count; if k >= c-1 then begin i:=0;with St_t.Ptr(j) do while (arr^[i] < AX[0]-1) do Inc(i); if i >= PntCnt^ then begin //убрать первые i уже использованных элементов стеков for m:=0 to k-i do begin St_t.Ptr(j).arr^[m]:=St_t.Ptr(j).arr^[m+i]; St_u.Ptr(j).arr^[m]:=St_u.Ptr(j).arr^[m+i]; end; Dec(St_I.arr^[j],i); end else if c < ArraySize-PntCnt^ then begin //простое увеличение размера стека // tells(0,'Увеличение размера стека. Новый размер:' // +inttostr(St_u.Ptr(j).Count+PntCnt^)); St_t.Ptr(j).ChangeCount(St_t.Ptr(j).Count+PntCnt^); St_u.Ptr(j).ChangeCount(St_u.Ptr(j).Count+PntCnt^); end else begin //выбросить каждый второй элемент стеков i:=1;m:=2; repeat St_t.Ptr(j).arr^[i] := St_t.Ptr(j).arr^[m]; St_u.Ptr(j).arr^[i] := St_u.Ptr(j).arr^[m]; Inc(i,1);Inc(m,2); until m >= c-1; St_t.Ptr(j).ChangeCount(2*i); St_u.Ptr(j).ChangeCount(2*i); St_I.arr^[j]:=i; end end end end; end{END CASE} end;{END TNoLin15} function TNoLin15Rst; var i,k : Integer; begin Result:=0; with PDelayRec(Prop.arr)^,PNoLine15Var(Vars)^ do case Action of f_ReadRez : try BlockRead(F,Count,SOfI); if Count >= 0 then BlockRead(F,St_x.arr^,(Count+1)*SOfR); except Result:=er_ReadFile end; f_WriteRez : try BlockWrite(F,Count,SOfI); if Count >= 0 then BlockWrite(F,St_x.arr^,(Count+1)*SOfR); except Result:=er_WriteFile end; f_ReadRst : try BlockRead(F,Count,SOfI); if Count >= 0 then BlockRead(F,St_x.arr^,(Count+1)*SOfR); for i:=0 to Count do begin BlockRead(F,k,SOfI); St_I.arr^[i]:=k; St_t.Ptr(i).ChangeCount(k+2); St_u.Ptr(i).ChangeCount(k+2); BlockRead(F,St_t.Ptr(i).arr^,(k+1)*SOfR); BlockRead(F,St_u.Ptr(i).arr^,(k+1)*SOfR); end except Result:=er_ReadFile end; f_WriteRst : try BlockWrite(F,Count,SOfI); if Count >= 0 then BlockWrite(F,St_x.arr^,(Count+1)*SOfR); for i:=0 to Count do begin k:=St_I.arr^[i]; BlockWrite(F,k,SOfI); BlockWrite(F,St_t.Ptr(i).arr^,(k+1)*SOfR); BlockWrite(F,St_u.Ptr(i).arr^,(k+1)*SOfR); end; except Result:=er_WriteFile end; end end; {--------------------------------------------------------------------------- ПРОИЗВОДНАЯ ВХОДНОГО СИГНАЛА - Y(t) = dU(t)/dt, Y(0) = Y0 ---------------------------------------------------------------------------} function TNoLin8Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Производная'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'x0',PChar(ConvertVector(PropStr[0])),Res); end; end; end; function TNoLin8; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin8Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Count+2; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Count; CU.arr^[0]:=Count end; f_InitTime : begin AX[Count]:=at; AX[Count+1]:=0 end; f_InitMem, f_InitState : begin Move(arr^,AY.Ptr(0).arr^,Count*SOfR); for j:=0 to Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; end; f_GetState : if (at-AX[Count]) > 0 then begin for j:=0 to Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; AX[Count+1]:=at-AX[Count]; AX[Count]:=at end; f_RestoreOuts: if AX[Count+1] > 0 then for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=(AU.Ptr(0).arr^[j]-AX[j])/AX[Count+1]; f_GoodStep, f_UpdateOuts : if (at-AX[Count]) > 0 then for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=(AU.Ptr(0).arr^[j]-AX[j])/(at-AX[Count]); // f_SteadyState: Move(AY.Ptr(0).arr^,arr^,Count*SOfR); end{END CASE} end;{END TNoLin8} {--------------------------------------------------------------------------- ОГРАНИЧЕНИЕ ПО ПРОИЗВОДНОЙ ВХОДНОГО СИГНАЛА - dU(t)/dt <= A, Y(0) = Y0 ---------------------------------------------------------------------------} function TNoLin9Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Производная с ограничением'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'a',PChar(ConvertVector(PropStr[0])),Res); MVTU.SetBlockProp(BlockId,'x0',PChar(ConvertVector(PropStr[1])),Res); end; end; end; function TNoLin9; var j : Integer; x : RealType; begin Result:=0; with PNoLine2Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin9Convert); f_EditErr : if (Parms.Count <> Y0.Count) then Result:=er_Count; f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Y0.Count+2; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_InitTime : begin AX[Y0.Count]:=at; AX[Y0.Count+1]:=0 end; f_InitMem, f_InitState : begin Move(Y0.arr^,AY.Ptr(0).arr^,Y0.Count*SOfR); for j:=0 to Y0.Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; end; f_GetState : if (at-AX[Y0.Count]) > 0 then begin for j:=0 to Y0.Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; AX[Y0.Count+1]:=at-AX[Y0.Count]; AX[Y0.Count]:=at end; f_RestoreOuts: if AX[Y0.Count+1] > 0 then for j:=0 to Y0.Count-1 do begin x:=AU.Ptr(0).arr^[j]-AX[j]; if ABS(x) >= ABS(Parms.arr^[j]*AX[Y0.Count+1]) then AY.Ptr(0).arr^[j]:=sign_(x)*Parms.arr^[j] else AY.Ptr(0).arr^[j]:=x/AX[Y0.Count+1]; end; f_UpdateOuts, f_GoodStep : if (at-AX[Y0.Count]) > 0 then for j:=0 to Y0.Count-1 do begin x:=AU.Ptr(0).arr^[j]-AX[j]; if ABS(x) >= ABS(Parms.arr^[j]*(at-AX[Y0.Count])) then AY.Ptr(0).arr^[j]:=sign_(x)*Parms.arr^[j] else AY.Ptr(0).arr^[j]:=x/(at-AX[Y0.Count]); end; // f_SteadyState: Move(AY.Ptr(0).arr^,Y0.arr^,Y0.Count*SOfR); end{END CASE} end;{END TNoLin9} {--------------------------------------------------------------------------- ТЕКУЩЕЕ МИНИМАЛЬНОЕ ЗНАЧЕНИЕ ВХОДНОГО СИГНАЛА- Y(t)=MIN[U(t)] ---------------------------------------------------------------------------} function TNoLin10Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Нижний или верхний предел'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'op_type','0',Res); end; end; end; function TNoLin10; var j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin10Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=max(CU.arr^[0],1); f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_GetState : for j:=0 to AY.Ptr(0).Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_InitState : for j:=0 to AY.Ptr(0).Count-1 do begin AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]; AX[j]:=AU.Ptr(0).arr^[j] end; f_UpdateOuts, f_GoodStep, f_UpdateJacoby : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=min(AU.Ptr(0).arr^[j],AX[j]); end{END CASE} end;{END TNoLin10} {--------------------------------------------------------------------------- ТЕКУЩЕЕ МАКСИМАЛЬНОЕ ЗНАЧЕНИЕ ВХОДНОГО СИГНАЛА- Y(t)=MAX[U(t)] ---------------------------------------------------------------------------} function TNoLin11Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Нижний или верхний предел'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'op_type','1',Res); end; end; end; function TNoLin11; var j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin11Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=max(CU.arr^[0],1); f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_GetState : for j:=0 to AY.Ptr(0).Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_InitState : for j:=0 to AY.Ptr(0).Count-1 do begin AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]; AX[j]:=AU.Ptr(0).arr^[j] end; f_UpdateOuts, f_GoodStep, f_UpdateJacoby : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=max(AU.Ptr(0).arr^[j],AX[j]); end{END CASE} end;{END TNoLin11} {--------------------------------------------------------------------------- МИНИМАЛЬНОЕ (МАКСИМАЛЬНОЕ) ЗНАЧЕНИЕ ВХОДНЫХ СИГНАЛОВ ВО ВХОДНЫХ ПОРТАХ Y=Min/Max [U(i,j)],i=1,N;j=1,M(i), где N - число входных портов; M(i) - размер входного массива в каждом из входных портов ---------------------------------------------------------------------------} function TNoLin19Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Минимум по всем элементам вектора'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PNoLin18Rec(Prop.arr)^ do begin MVTU.SetBlockProp(BlockId,'op_type',PChar(IntToStr(what^)),Res); MVTU.SetBlockProp(BlockId,'nport',PChar(IntToStr(inp^)),Res); MVTU.ExecutePropScript(BlockId,Res,Res); end; end; end; function TNoLin19; var i,j : Integer; x : RealType; begin Result:=0; with PNoLin18Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin19Convert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=1; f_InitState, f_GoodStep, f_RestoreOuts, f_UpdateJacoby, f_UpdateOuts : begin x:=ymax; if what^ = 1 then x:=-x; for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do if what^ = 0 then x:=min(x,AU.Ptr(i).arr^[j]) else x:=max(x,AU.Ptr(i).arr^[j]); AY.Ptr(0).arr^[0]:=x end; end{END CASE} end;{END TNoLin19} {--------------------------------------------------------------------------- ВЕКТОР МИНИМАЛЬНЫХ (МАКСИМАЛЬНЫХ) ЗНАЧЕНИЙ ВХОДНЫХ СИГНАЛОВ ВО ВХОДНЫХ ПОРТАХ Y(j)=Min/Max [U(i,j)],i=1,N;j=1,M, где N - число входных портов; M - размер входного массива в каждом из входных портов ---------------------------------------------------------------------------} function TNoLin18Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Минимум по входам'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PNoLin18Rec(Prop.arr)^ do begin MVTU.SetBlockProp(BlockId,'op_type',PChar(IntToStr(what^)),Res); MVTU.SetBlockProp(BlockId,'nport',PChar(IntToStr(inp^)),Res); MVTU.ExecutePropScript(BlockId,Res,Res); end; end; end; function TNoLin18; var i,j,s : Integer; x : RealType; begin Result:=0; with PNoLin18Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin18Convert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : begin s:=CU.arr^[0]; for j:=1 to CU.Count-1 do s:=max(s,CU.arr^[j]); for j:=0 to CU.Count-1 do CU.arr^[j]:=s; CY.arr^[0]:=s; end; f_InitState, f_GoodStep, f_RestoreOuts, f_UpdateJacoby, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do begin x:=AU.Ptr(0).arr^[j]; for i:=1 to AU.Count-1 do if what^ = 0 then x:=min(x,AU.Ptr(i).arr^[j]) else x:=max(x,AU.Ptr(i).arr^[j]); AY.Ptr(0).arr^[j]:=x end; end{END CASE} end;{END TNoLin18} {--------------------------------------------------------------------------- АБСОЛЮТНОЕ ЗНАЧЕНИЕ ВХОДНОГО СИГНАЛА- Y(t)=ABS[U(t)] ---------------------------------------------------------------------------} function TNoLin6Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Абсолютное значение'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TNoLin6; var j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin6Convert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_GoodStep, f_RestoreOuts, f_UpdateOuts, f_UpdateJacoby, f_InitState : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=ABS(AU.Ptr(0).arr^[j]); end{END CASE} end;{END TNoLin6} {--------------------------------------------------------------------------- Знак Блок осуществляет операцию определения знака входного сигнала: y(t) = 1, если x(t) > 0; y(t) = -1, если x(t) < 0; y(t) = 0, если x(t) = 0. Для работы блока параметры не требуются. ---------------------------------------------------------------------------} function TNoLin7Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Знак'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TNoLin7; var j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin7Convert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_GoodStep, f_RestoreOuts, f_UpdateOuts, f_UpdateJacoby, f_InitState : for j:=0 to AY.Ptr(0).Count-1 do if AU.Ptr(0).arr^[j] > 0 then AY.Ptr(0).arr^[j]:=1.0 else if AU.Ptr(0).arr^[j] < 0 then AY.Ptr(0).arr^[j]:=-1.0 else AY.Ptr(0).arr^[j]:=0; end{END CASE} end;{END TNoLin7} {--------------------------------------------------------------------------- Излом Блок реализует нелинейную статическую характеристику типа "излом" по следующему алгоритму: y(t) = k1*x(t), если x(t) < 0; y(t) = k2*x(t), если x(t) > 0; Для работы блока необходимо задать коэффициенты k1 и k2. ---------------------------------------------------------------------------} function TNoLin12Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Излом'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'k1',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'k2',PChar(SL[1]),Res); finally SL.Free; end; end; end; function TNoLin12; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin12Convert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_GoodStep, f_RestoreOuts, f_UpdateOuts, f_InitState : for j:=0 to AY.Ptr(0).Count-1 do if AU.Ptr(0).arr^[j] < 0 then AY.Ptr(0).arr^[j]:=arr^[0]*AU.Ptr(0).arr^[j] else AY.Ptr(0).arr^[j]:=arr^[1]*AU.Ptr(0).arr^[j]; end{END CASE} end;{END TNoLin12} {--------------------------------------------------------------------------- Произвольная однозначная нелинейность Блок реализует однозначную нелинейную статическую характеристику произвольного вида, аппроксимируемую кусочно-ломанной кривой. Для работы блока необходимо в диалоговом окне задать (через пробел) координаты точек излома X = х1,х2, ... , xN ; Y = y1,y2, ... , yN. ---------------------------------------------------------------------------} function TNoLin13Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Ломаная статическая характеристика'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'t',PChar(ConvertVector(PropStr[0])),Res); MVTU.SetBlockProp(BlockId,'y',PChar(ConvertVector(PropStr[1])),Res); end; end; end; function TNoLin13; var j : Integer; begin Result:=0; with PLomRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin13Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_InitState, f_GoodStep, f_RestoreOuts, f_UpdateJacoby, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=GetVectorData(X.Count-1,AU.Ptr(0).arr^[j],Y.arr^,X.arr^); end{END CASE} end;{END TNoLin13} {--------------------------------------------------------------------------- Компенсатор начальных условий Блок реализует преобразование вектора входного сигнала по алгоритму: yi(t) = xi(t) - xi(0), где xi(0) - значение вектора входного сигнала при t = 0, автоматически определяемое на нулевом шаге интегрирования. Для работы блока параметры не требуются. ---------------------------------------------------------------------------} function TNoLin14Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Компенсация начального значения'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TNoLin14; var j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin14Convert); f_GetDeriCount : Result:=0; f_GetStateCount : Result:=max(1,CU.arr^[0]); f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_InitMem : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=0; f_InitState : for j:=0 to AU.Ptr(0).Count-1 do begin AX[j]:=AU.Ptr(0).arr^[j]; AY.Ptr(0).arr^[j]:=0 end; f_GoodStep, f_UpdateJacoby, f_RestoreOuts, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]-AX[j]; end{END CASE} end;{END TNoLin14} {--------------------------------------------------------------------------- Зазор Блок реализует нелинейную статическую характеристику типа "зазор" по следующему алгоритму: y(t) = K*[x(t) - b], если x(t) > [y(t - dt)/ K + b]; y(t) = K*[x(t) +b], если x(t) < [y(t - dt)/ K - b]; y(t) = y(t - dt), если [y(t - dt)/ K - b] <= x(t) <= [y(t - dt)/ K + b], где dt - предыдущий временной шаг интегрирования. Для работы блока необходимо задать половину ширины зазора b, коэффициент К и начальное состояние выхода y(0). ---------------------------------------------------------------------------} function TNoLin16Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Зазор'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'b',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'k',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'y0',PChar(ConvertVector(PropStr[1])),Res); finally SL.Free; end; end; end; function TNoLin16; var j : Integer; begin Result:=0; with PNoLine2Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin16Convert); f_EditErr : if Parms.arr^[1] = 0 then Result:=er_parzero; f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Y0.Count; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_InitState, f_InitMem : begin Move(Y0.arr^,AY.Ptr(0).arr^,Y0.Count*SOfR); for j:=0 to Y0.Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; end; f_GetState : for j:=0 to Y0.Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts: for j:=0 to Y0.Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_GoodStep, f_UpdateJacoby, f_UpdateOuts : for j:=0 to Y0.Count-1 do with Parms do if AU.Ptr(0).arr^[j] > (AX[j]/arr^[1]+arr^[0]) then AY.Ptr(0).arr^[j]:=arr^[1]*(AU.Ptr(0).arr^[j]-arr^[0]) else if AU.Ptr(0).arr^[j] < (AX[j]/arr^[1]-arr^[0]) then AY.Ptr(0).arr^[j]:=arr^[1]*(AU.Ptr(0).arr^[j]+arr^[0]) else AY.Ptr(0).arr^[j]:=AX[j]; // f_SteadyState: Move(AY.Ptr(0).arr^,Y0.arr^,Y0.Count*SOfR); end{END CASE} end;{END TNoLin16} {--------------------------------------------------------------------------- Люфт Блок реализует нелинейную статическую характеристику типа "люфт" по следующему алгоритму: y(t) = y1, если x(t) <= [y1/ K - b]; y(t) = y2, если x(t) >= [y2/ K + b]; y(t) = K*[x(t) - b], если [y(t - dt)/ K + b] < x(t) < [y2/ K + b]; y(t) = K*[x(t) +b], если [y1/ K - b] < x(t) < [y(t - dt)/ K - b]; y(t) = y(t - dt), если [y(t - dt)/ K - b] <= x(t) <= [y(t - dt)/ K + b], где dt - предыдущий временной шаг интегрирования. Для работы блока необходимо задать половину ширины зазора b, значения параметров насыщения y1 и y2, коэффициент К и начальное состояние выхода y(0). ---------------------------------------------------------------------------} function TNoLin17Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Зазор'; var SL: TStringList; Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try SL:=TStringList.Create; //Парсим свойство заданное в одной строчке ExtractStrings([' ',';'],[' '],PChar(PropStr[0]),SL); //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'b',PChar(SL[0]),Res); MVTU.SetBlockProp(BlockId,'k',PChar(SL[1]),Res); MVTU.SetBlockProp(BlockId,'y1',PChar(SL[2]),Res); MVTU.SetBlockProp(BlockId,'y2',PChar(SL[3]),Res); MVTU.SetBlockProp(BlockId,'y0',PChar(ConvertVector(PropStr[1])),Res); finally SL.Free; end; end; end; function TNoLin17; var j : Integer; begin Result:=0; with PNoLine2Rec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin17Convert); f_EditErr : if Parms.arr^[1] = 0 then Result:=er_parzero; f_GetStateCount : Result:=Y0.Count; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_InitState, f_InitMem : begin Move(Y0.arr^,AY.Ptr(0).arr^,Y0.Count*SOfR); for j:=0 to Y0.Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; end; f_GetState : for j:=0 to Y0.Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts: for j:=0 to Y0.Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_GoodStep, f_UpdateJacoby, f_UpdateOuts : for j:=0 to Y0.Count-1 do with Parms do if AU.Ptr(0).arr^[j] <= (arr^[2]/arr^[1]-arr^[0]) then AY.Ptr(0).arr^[j]:=arr^[2] else if AU.Ptr(0).arr^[j] >= (arr^[3]/arr^[1]+arr^[0]) then AY.Ptr(0).arr^[j]:=arr^[3] else if (AU.Ptr(0).arr^[j] < (arr^[3]/arr^[1]+arr^[0])) and (AU.Ptr(0).arr^[j] > (AX[j]/arr^[1]+arr^[0])) then AY.Ptr(0).arr^[j]:=arr^[1]*(AU.Ptr(0).arr^[j]-arr^[0]) else if (AU.Ptr(0).arr^[j] > (arr^[2]/arr^[1]-arr^[0])) and (AU.Ptr(0).arr^[j] < (AX[j]/arr^[1]-arr^[0])) then AY.Ptr(0).arr^[j]:=arr^[1]*(AU.Ptr(0).arr^[j]+arr^[0]) else AY.Ptr(0).arr^[j]:=AX[j]; // f_SteadyState : Move(AY.Ptr(0).arr^,Y0.arr^,Y0.Count*SOfR); end{END CASE} end;{END TNoLin17} {--------------------------------------------------------------------------- Импульсная функция ---------------------------------------------------------------------------} function TImpulseConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Импульсная функция'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PImpulseRec(Prop.arr)^ do begin MVTU.SetBlockProp(BlockId,'iniflag',PChar(IntToStr(tFun^)),Res); MVTU.SetBlockProp(BlockId,'tau',PChar(ConvertVector(PropStr[1])),Res); MVTU.SetBlockProp(BlockId,'y0',PChar(ConvertVector(PropStr[2])),Res); end; end; end; function TImpulse; var j : Integer; fl : Boolean; begin Result:=0; with PImpulseRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TImpulseConvert); f_EditErr : if (tau.Count <> Y0.Count) then Result:=er_Count; f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Y0.Count; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Y0.Count; CU.arr^[0]:=Y0.Count end; f_Create : Vars:=TExtArray.Create(1); f_Free : TExtArray(Vars).Free; f_InitMem : TExtArray(Vars).ChangeCount(Y0.Count); f_InitTime : with TExtArray(Vars) do for j:=0 to Y0.Count-1 do arr^[j]:=at-tau.arr^[j]; f_InitState : with TExtArray(Vars) do begin Move(Y0.arr^,AY.Ptr(0).arr^,Y0.Count*SOfR); for j:=0 to Y0.Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; end; f_GetState : for j:=0 to Y0.Count-1 do AX[j]:=AU.Ptr(0).arr^[j]; f_RestoreOuts: for j:=0 to Y0.Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_GoodStep : with TExtArray(Vars) do for j:=0 to Y0.Count-1 do begin fl:=false; case tFun^ of 0: fl:=AU.Ptr(0).arr^[j] <> AX[j]; 1: fl:=AU.Ptr(0).arr^[j] > AX[j]; 2: fl:=AU.Ptr(0).arr^[j] < AX[j]; 3: fl:=AU.Ptr(0).arr^[j] <> 0; end; if fl and ((at-arr^[j]) > tau.arr^[j]) then begin arr^[j]:=at; AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]; end; if (at-arr^[j]) > tau.arr^[j] then AY.Ptr(0).arr^[j]:=Y0.arr^[j] end; // f_SteadyState: Move(AY.Ptr(0).arr^,Y0.arr^,Y0.Count*SOfR); end; end; {--------------------------------------------------------------------------- Блок реализует решение системы НАУ вида F(Y) = 0. В процессе решения вектор входов Y подбирается таким образом, чтобы вектор входов в блок U был нулевым. Параметры блока : Y0 - вектор начальных состояний векторного выхода Y(0). ---------------------------------------------------------------------------} function TNoLin20Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Нелинейное уравнение F(y) = 0'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'x0',PChar(ConvertVector(PropStr[0])),Res); end; end; end; function TNoLin20; var j : Integer; begin Result:=0; with PNoLine20Rec(Prop.arr)^.Y0 do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin20Convert); f_EditErr : if Count = 0 then Result:=er_parzero; f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Count; f_GetInit : Result:=2; f_GetCount : begin CY.arr^[0]:=Count; CU.arr^[0]:=Count end; f_InitMem : Move(arr^,AY.Ptr(0).arr^,Count*SOfR); f_GetState : for j:=0 to Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts: for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; // f_SteadyState : Move(AY.Ptr(0).arr^,arr^,Count*SOfR); end{END CASE} end;{END TNoLin20} {--------------------------------------------------------------------------- Блок реализует решение системы НАУ вида F(Y) = 0. В процессе решения вектор входов Y подбирается таким образом, чтобы вектор входов в блок U был нулевым. Параметры блока : Y0 - вектор начальных состояний векторного выхода Y(0). ---------------------------------------------------------------------------} function TNoLin21Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Нелинейное уравнение y = F(y)'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'x0',PChar(ConvertVector(PropStr[0])),Res); end; end; end; function TNoLin21; var j : Integer; begin Result:=0; with PNoLine20Rec(Prop.arr)^.Y0 do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin21Convert); f_EditErr : if Count = 0 then Result:=er_parzero; f_GetDeriCount : Result:=0; f_GetStateCount : Result:=Count; f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=Count; CU.arr^[0]:=Count end; f_InitMem : Move(arr^,AY.Ptr(0).arr^,Count*SOfR); f_GetState : for j:=0 to Count-1 do AX[j]:=AY.Ptr(0).arr^[j]; f_RestoreOuts: for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=AX[j]; f_InitState, f_GoodStep, f_UpdateJacoby, f_UpdateOuts : for j:=0 to Count-1 do AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[j]; // f_SteadyState : Move(AY.Ptr(0).arr^,arr^,Count*SOfR); end{END CASE} end;{END TNoLin21} {--------------------------------------------------------------------------- Запоминание входного сигнала Алгоритм работы блока: ---------------------------------------------------------------------------} function TRememberConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Запоминание значения сигналов'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TRemember; var j : Integer; begin Result:=0; with PRememberRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TRememberConvert); f_GetDeriCount, f_GetInit : Result:=0; f_GetStateCount:Result:=N^; f_GetCount : begin CY.arr^[0]:=N^; CU.arr^[0]:=N^; CU.arr^[1]:=N^ end; f_GetState : for j:=0 to N^-1 do if AU.Ptr(1).arr^[j] <> 0.0 then AX[j]:=AU.Ptr(0).arr^[j]; f_InitState : for j:=0 to N^-1 do begin AX[j]:=AU.Ptr(0).arr^[j]; AY.Ptr(0).arr^[j]:=AX[j] end; f_RestoreOuts, f_GoodStep : for j:=0 to N^-1 do AY.Ptr(0).arr^[j]:=AX[j]; end end; {--------------------------------------------------------------------------- Запоминание времени, в течение которого входной сигнал - истина Алгоритм работы блока: ---------------------------------------------------------------------------} function TTimeRememberConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Запоминание длительности истинного сигнала'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TTimeRemember; var j : Integer; begin Result:=0; with PRememberRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TTimeRememberConvert); f_GetDeriCount, f_GetInit : Result:=0; f_GetStateCount:Result:=N^; f_GetCount : begin CY.arr^[0]:=N^; CU.arr^[0]:=N^; end; f_GetState : for j:=0 to N^-1 do if AU.Ptr(0).arr^[j] = 0.0 then AX[j]:=at; f_InitState : for j:=0 to N^-1 do begin AX[j]:=at; AY.Ptr(0).arr^[j]:=at-AX[j] end; f_RestoreOuts: for j:=0 to N^-1 do AY.Ptr(0).arr^[j]:=at-AX[j]; f_UpdateOuts, f_GoodStep : for j:=0 to N^-1 do if AU.Ptr(0).arr^[j] <> 0.0 then AY.Ptr(0).arr^[j]:=at-AX[j] else AY.Ptr(0).arr^[j]:=0; end end; {--------------------------------------------------------------------------- Квантователь по уровню ---------------------------------------------------------------------------} function TNoLin22Convert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Квантователь по уровню'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: begin MVTU.SetBlockProp(BlockId,'step',PChar(ConvertVector(PropStr[0])),Res); end; end; end; function TNoLin22; function sign(a:realtype):realtype; near; begin if a=0 then result := 0 else if a<0 then result:=-1 else result := 1 end; var j : Integer; x : RealType; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TNoLin22Convert); f_EditErr : if CU.arr^[0] <> Count then Result:=er_Count; f_GetCount : CY.arr^[0]:=CU.arr^[0]; f_RestoreOuts, f_UpdateOuts, f_UpdateJacoby, f_GoodStep, f_InitState : for j:=0 to AU.Ptr(0).Count-1 do begin x:=arr^[j]*sign(AU.Ptr(0).arr^[j])*trunc(abs(AU.Ptr(0).arr^[j]/arr^[j])+0.5); if abs(x) > ymax then Result:=er_overflow_y else AY.Ptr(0).arr^[j]:=x end; end{END CASE} end;{END TFUN0} end.