Смекни!
smekni.com

Программная реализация модального управления для линейных стационарных систем (стр. 3 из 4)

begin

NAlfa := StartAlfa + dAlfa * j;

StringGrid_Roots.Cells [j, 1] := FloatToStr (Cos (NAlfa) * W);

StringGrid_Roots.Cells [Order - Pred (j), 1] := FloatToStr (Cos (-NAlfa) * W);

StringGrid_Roots.Cells [j, 2] := FloatToStr (Sin (NAlfa) * W);

StringGrid_Roots.Cells [Order - Pred (j), 2] := FloatToStr (Sin (-NAlfa) * W);

end;

if Odd (Order) then

begin

StringGrid_Roots.Cells [NHalf +1, 1] := FloatToStr (-W);

StringGrid_Roots.Cells [NHalf +1, 2] := '0';

end;

StringGrid_Roots.Options := DefOptions - [goEditing];

end;

end;

end;

procedure TForm_Main.TabbedNotebook_MainChange(Sender: TObject;

NewTab: Integer; var AllowChange: Boolean);

begin

with BitBtn_Compute do

case NewTab of

0 :begin

SpinEdit_Dim.Enabled := True;

if Tag in [1, 3, 5, 7, 9, 11, 13, 15] then Enabled := False

else Enabled := True;

BitBtn_Compute.Caption := 'Рассчитать модальное управление';

end;

1 :begin

SpinEdit_Dim.Enabled := True;

if Tag in [2, 3, 6, 7, 10, 11, 14, 15] then Enabled := False

else Enabled := True;

BitBtn_Compute.Caption := 'Решить системы дифф. уравнений ';

if Form_Options.CheckBox_Link.State = cbChecked then BindGrids;

end;

2 :begin

SpinEdit_Dim.Enabled := False;

if Tag in [4, 5, 6, 7, 12, 13, 14, 15] then Enabled := False

else Enabled := True;

BitBtn_Compute.Caption := 'Обновить результаты решений ';

end;

3 :begin

SpinEdit_Dim.Enabled := False;

if Tag in [8, 9, 10, 11, 12, 13, 14, 15] then Enabled := False

else Enabled := True;

BitBtn_Compute.Caption := 'Обновить диаграмму решения ';

end;

end;

end;

procedure TForm_Main.StringGrid_SetEditText(Sender: TObject; ACol,

ARow: Longint; const Value: string);

begin

if not BitBtn_Compute.Enabled then

case TabbedNotebook_Main.PageIndex of

0 :if Form_Options.CheckBox_Link.State = cbChecked then

BitBtn_Compute.Tag := BitBtn_Compute.Tag - 3

else

BitBtn_Compute.Tag := BitBtn_Compute.Tag - 1;

1 :BitBtn_Compute.Tag := BitBtn_Compute.Tag - 2;

end;

BitBtn_Compute.Enabled := True;

end;

procedure TForm_Main.BitBtn_HelpClick(Sender: TObject);

begin

Form_Help.ShowModal;

end;

procedure TForm_Main.RadioGroupChartClick(Sender: TObject);

begin

case RadioGroupChart.ItemIndex of

0 :ShowChart(1);

1 :ShowChart(2);

end;

end;

end.
unit SubUnit;

interface

uses

SysUtils, Matrix, Operates, Grids;

procedure CopyGrid(AGrid, BGrid: TStringGrid);

procedure LoadMatrixSolveFromStrGrd (AMatrix: TMatrix; AGrid: TStringGrid);

procedure ComputeFromPage0;

procedure ComputeFromPage1;

procedure ComputeFromPage2;

procedure ComputeFromPage3;

procedure ShowChart(NumberOfChart: Byte);

implementation

uses

MainUnit, OptsUnit, CFXOCX2;

procedure CopyGrid(AGrid, BGrid: TStringGrid);

var

i, j: LongInt;

begin

AGrid.ColCount := BGrid.ColCount;

AGrid.RowCount := BGrid.RowCount;

for j := 0 to AGrid.ColCount do

for i := 0 to AGrid.RowCount do

AGrid.Cells[j, i] := BGrid.Cells[j, i];

end;

function CropStr (Str: String): String;

var

i: Byte;

Str_1: String;

Begin

for i := Length(Str) downto 1 do

if Str [i] = ' ' then Str := Copy(Str, 1, i-1)

else Break;

Str_1 := Str;

for i := 1 to Length(Str) do

if Str[i] = ' ' then Str_1 := Copy(Str, i+1, Length(Str) - i)

else Break;

CropStr := Str_1;

End;

procedure LoadMatrixFromStrGrd (AMatrix: TMatrix; AGrid: TStringGrid);

var

i, j: Word;

begin

AMatrix.Resize (Pred(AGrid.ColCount), Pred(AGrid.RowCount));

for i := 1 to AMatrix.RowCount do

for j := 1 to AMatrix.ColCount do

begin

if CropStr(AGrid.Cells[j, i]) = '' then AGrid.Cells[j, i] := '0';

AMatrix[j ,i] := StrToFloat(AGrid.Cells[j, i])

end

end;

procedure OutPutMatrixToStrGrd (AMatrix: TMatrix; AGrid: TStringGrid);

var

i, j: Word;

begin

AGrid.ColCount := Succ(AMatrix.ColCount);

AGrid.RowCount := Succ(AMatrix.RowCount);

for i := 1 to AMatrix.RowCount do

for j := 1 to AMatrix.ColCount do

begin

AGrid.Cells[j, 0] := IntToStr (j);

AGrid.Cells[0, i] := IntToStr (i);

AGrid.Cells[j, i] := FloatToStrF(AMatrix[j ,i],ffGeneral,5,3);

end

end;

procedure OutPutMatrixSolveToStrGrd (AMatrix: TMatrix; AGrid: TStringGrid);

var

i, j, k: Word;

begin

AGrid.ColCount := AMatrix.ColCount;

AGrid.RowCount := Succ(AMatrix.RowCount);

for i := 1 to AMatrix.RowCount do

for j := 1 to AMatrix.ColCount do

begin

if j = AMatrix.ColCount then k := 0 else k := j;

AGrid.Cells[j, 0] := 'X' + IntToStr (j);

AGrid.Cells[k, i] := FloatToStrF(AMatrix[j ,i],ffGeneral,5,3);

end;

AGrid.Cells[0, 0] := 'Время';

end;

procedure LoadMatrixSolveFromStrGrd (AMatrix: TMatrix; AGrid: TStringGrid);

var

i, j, k: Word;

begin

AMatrix.Resize (AGrid.ColCount, Pred(AGrid.RowCount));

for i := 1 to AMatrix.RowCount do

for j := 0 to AMatrix.ColCount do

begin

if j = 0 then k := AMatrix.ColCount else k := j;

if CropStr(AGrid.Cells[j, i]) = '' then AGrid.Cells[j, i] := '0';

AMatrix[k ,i] := StrToFloat(AGrid.Cells[j, i])

end

end;

procedure ComputeFromPage0;

var

Order : TOrder;

i, j : byte;

K : ShortInt;

mDummy1, mDummy2,

mA, mB, mKp,

mM, mN, mN1: TMatrix;

cvRoots: TComplexVector;

begin

with Form_Main do

begin

Order := SpinEdit_Dim.Value;

mA := TMatrix.Create(Order, Order);

mB := TMatrix.Create(1, Order);

mM := TMatrix.Create(Order, Order);

mDummy1 := TMatrix.Create(Order, Order);

mN1 := TMatrix.Create(Order, 1);

mN := TMatrix.Create(Order, Order);

mDummy2 := TMatrix.Create(Order, Order);

mKp := TMatrix.Create(Order, 1);

LoadMatrixFromStrGrd (mA, StringGrid_Ap0);

LoadMatrixFromStrGrd (mB, StringGrid_Bp0);

for j := 1 to Order do

begin

mDummy1.Assign(mA);

mDummy1.NthPower(j - 1);

mDummy1.MultFromRight(mB);

for i := 1 to Order do

mM[j, i] := mDummy1[1, i];

end;

if not mM.Inverse then

Raise ESingularMatrix.Create('Система неполностью управляема:' +

'матрица M - вырожденная !!!'#10 +

'Измените значения коэффициентов матриц А и B');

mN1.SetNull;

mN1[Order, 1] := 1;

mN1.MultFromRight(mM);

for i := 1 to Order do

begin

mDummy2.Assign(mA);

mDummy2.NthPower(i-1);

mDummy1.Assign(mN1);

mDummy1.MultFromRight(mDummy2);

for j := 1 to Order do mN[j, i] := mDummy1[j, 1];

end;

mDummy1.Assign(mN);

if not mDummy1.Inverse then

Raise ESingularMatrix.Create('Не могу обратить матрицу N !!!'#10 +

'(не разбрасывайтесь порядками коэффициентов матриц)');

mA.MultFromLeft(mN);

mA.MultFromRight(mDummy1);

OutPutMatrixToStrGrd(mA, StringGrid_Anp0);

cvRoots.Dim := Order;

for j := 1 to Order do

begin

cvRoots.Data[j].Re := StrToFloat(StringGrid_Roots.Cells[j, 1]);

cvRoots.Data[j].Im := StrToFloat(StringGrid_Roots.Cells[j, 2]);

end;

for j := 1 to Order do

begin

if Odd (j) then K := -1 else K := +1;

mKp[Order-Pred(j), 1] := - mA[Order-Pred(j), Order] -

K * SymmetricalFunction(cvRoots, j);

end;

mKp.MultFromRight(mN);

OutPutMatrixToStrGrd (mKp, StringGrid_Kpp0);

mDummy1.Free;

mDummy2.Free;

mA.Free;

mB.Free;

mKp.Free;

mM.Free;

mN.Free;

mN1.Free;

end;

end;

procedure ComputeFromPage1;

var

Order: TOrder;

mA, mB, mABKp, mInCond, mKp: TMatrix;

mSolutionValues: TMatrix;

LowerLimit, UpperLimit, NumReturn, NumIntervals: Word;

begin

with Form_Main do

begin

Order := SpinEdit_Dim.Value;

mA := TMatrix.Create(Order, Order);

mB := TMatrix.Create(1, Order);

mKp := TMatrix.Create(Order, 1);

mInCond := TMatrix.Create(Order, 1);

LoadMatrixFromStrGrd(mA, StringGrid_Ap1);

LoadMatrixFromStrGrd(mB, StringGrid_Bp1);

LoadMatrixFromStrGrd(mKp, StringGrid_Kpp1);

LoadMatrixFromStrGrd(mInCond, StringGrid_InCond);

mABKp := TMatrix.Create(Order, Order);

mABKp.Assign(mB);

mABKp.MultFromRight(mKp);

mABKp.AddMatrix(mA);

OutPutMatrixToStrGrd(mABKp, StringGrid_ABKpp1);

mB.MultConst(StrToFloat(Edit_U.Text));

with Form_Options do

begin

LowerLimit := SpinEdit0.Value;

UpperLimit := SpinEdit1.Value;

NumReturn := SpinEdit2.Value;

NumIntervals := SpinEdit3.Value;

end;

mSolutionValues := TMatrix.Create(1, 1);

try

DiffSystemSolve (mA, mB,

LowerLimit, UpperLimit,

mInCond,

NumReturn, NumIntervals,

mSolutionValues);

OutPutMatrixSolveToStrGrd(mSolutionValues, StringGrid_Solve1);

mSolutionValues.ReSize(1, 1);

DiffSystemSolve (mABKp, mB,

LowerLimit, UpperLimit,

mInCond,

NumReturn, NumIntervals,

mSolutionValues);

OutPutMatrixSolveToStrGrd(mSolutionValues, StringGrid_Solve2);

except

on EO: EOverflow do

begin

EO.Message := 'Не буду считать !!!'#10 +

'С уменьшите разброс коэффициентов в матрицах'#10 +

'либо измените опции (уменьшите их pls.)';

Raise;

end;

end;

mA.Free;

mB.Free;

mABKp.Free;

mInCond.Free;

mKp.Free;

mSolutionValues.Free;

end;

end;

procedure ShowChart(NumberOfChart: Byte);

var

Order, Serie: TOrder;

NumReturn, Point: Word;

mSolutionValues: TMatrix;

procedure SetAdm;

const

Divisor = 3.4E+38;

var

i, j: LongInt;

Greatest, Least: Float;

begin

Greatest := mSolutionValues[1, 1];

Least := Greatest;

for j := 1 to Order do

for i := 1 to NumReturn do

begin

if mSolutionValues[j, i] > Greatest then Greatest := mSolutionValues[j, i];

if mSolutionValues[j, i] < Least then Least := mSolutionValues[j, i];

end;

Form_Main.ChartFX.Adm[CSA_MAX] := Greatest;

Form_Main.ChartFX.Adm[CSA_MIN] := Least;

Form_Main.ChartFX.Title[CHART_TOPTIT] := 'Y = Y '' * ';

end;

begin

with Form_Main do

begin

Order := SpinEdit_Dim.Value;

NumReturn := Form_Options.SpinEdit2.Value;

mSolutionValues := TMatrix.Create(1, 1);

ComputeFromPage1;

case NumberOfChart of

1 :begin

LoadMatrixSolveFromStrGrd(mSolutionValues, StringGrid_Solve1);

SetAdm;

ChartFX.OpenDataEx(Cod_Values, Order, Pred(NumReturn));

for Serie := 1 to Order do

begin

ChartFX.SerLeg[Pred(Serie)] := 'X ' + IntToStr(Serie);

ChartFX.ThisSerie := Pred(Serie);

for Point := 0 to Pred(NumReturn) do

ChartFX.Value[Point] := mSolutionValues[Serie, Succ(Point)];

end;

ChartFX.CloseData(Cod_Values);

{

ChartFX.OpenDataEx(Cod_XValues, Order, Pred(NumReturn));

for Serie := 1 to Order do

begin

ChartFX.ThisSerie := Pred(Serie);

for Point := 0 to Pred(NumReturn) do

ChartFX.XValue[Point] := mSolutionValues[1, Succ(Point)];

end;

ChartFX.CloseData(Cod_XValues);

}

end;

2 :begin

LoadMatrixSolveFromStrGrd(mSolutionValues, StringGrid_Solve2);

SetAdm;

ChartFX.OpenDataEx(Cod_Values, Order, Pred(NumReturn));

for Serie := 1 to Order do

begin

ChartFX.SerLeg[Pred(Serie)] := 'X ' + IntToStr(Serie);

ChartFX.ThisSerie := Pred(Serie);

for Point := 0 to Pred(NumReturn) do

ChartFX.Value[Point] := mSolutionValues[Serie, Succ(Point)];

end;

ChartFX.CloseData(Cod_Values);

end;

end;

mSolutionValues.Free;

end;

end;

procedure ComputeFromPage2;

begin

ComputeFromPage1;

end;

procedure ComputeFromPage3;

begin

case Form_Main.RadioGroupChart.ItemIndex of

0 :ShowChart(1);

1 :ShowChart(2);

end;

end;

end.


unit Matrix;

interface

uses SysUtils;

type

Float = Extended;

EMatrixOperatingError = class (Exception);

const

NearlyZero = 1E-15;

type

TMatrix = class (TObject)

private

DataPtr: Pointer;

FCols, FRows: Word;

function GetCell (ACol, ARow: Word): Float;

procedure SetCell (ACol, ARow: Word; AValue: Float);

function GetItem (NumItem: LongInt): Float;

procedure SetItem (NumItem: LongInt; AValue: Float);

procedure SwitchRows (FirstRow, SecondRow: Word);

public

constructor Create (NCols, NRows: Word);

destructor Destroy; override;

procedure Assign (AMatrix: TMatrix);

procedure ReSize (NewCols, NewRows: Word);

procedure SetNull;

procedure SetSingle;

procedure SetNegative;

procedure AddConst (AConst: Float);

procedure AddMatrix (AMatrix: TMatrix);

procedure MultConst (MConst: Float);

procedure MultFromRight (MMatrix: TMatrix);

procedure MultFromLeft (MMatrix: TMatrix);

procedure NthPower (Power: Word);

procedure Transpose;

function Inverse: Boolean;

function Determinant: Float;

function Rang: Float;

property ColCount: Word read FCols;

property RowCount: Word read FRows;

property Cells [ACol, ARow: Word]: Float read GetCell write SetCell; default;

property Items [NumItem: LongInt]: Float read GetItem write SetItem;

end;

implementation

uses Windows;

function IncPtr (p: Pointer; i: LongInt): Pointer;

asm

push EBX

mov EBX,EAX

add EBX,EDX

mov EAX,EBX

pop EBX

end;

function TMatrix.GetCell (ACol, ARow: Word): Float;

var

CellPtr: ^Float;

begin

CellPtr := IncPtr(DataPtr, (FRows * Pred(ACol) + Pred(ARow)) * SizeOf(Float));

Result := CellPtr^;

end;

procedure TMatrix.SetCell (ACol, ARow: Word; AValue: Float);

var

CellPtr: ^Float;

begin

CellPtr := IncPtr(DataPtr, (FRows * Pred(ACol) + Pred(ARow)) * SizeOf(Float));

CellPtr^ := AValue;

end;

function TMatrix.GetItem (NumItem: LongInt): Float;

var

CellPtr: ^Float;

begin

CellPtr := IncPtr(DataPtr, Pred(NumItem) * SizeOf(Float));

Result := CellPtr^;

end;

procedure TMatrix.SetItem (NumItem: LongInt; AValue: Float);

var

CellPtr: ^Float;

begin

CellPtr := IncPtr(DataPtr, Pred(NumItem) * SizeOf(Float));

CellPtr^ := AValue;

end;

procedure TMatrix.SwitchRows (FirstRow, SecondRow: Word);

var

i: Word;

Buffer: Float;

begin

for i := 1 to FCols do

begin

Buffer := GetCell(i, FirstRow);

SetCell(i, FirstRow, GetCell(i, SecondRow));

SetCell(i, SecondRow, Buffer);

end;

end;

constructor TMatrix.Create (NCols, NRows: Word);

begin

inherited Create;

FCols := NCols;

FRows := NRows;

DataPtr := AllocMem(FCols * FRows * SizeOf(Float));

end;

destructor TMatrix.Destroy;

begin

FreeMem(DataPtr);

inherited Destroy;

end;

procedure TMatrix.Assign (AMatrix: TMatrix);

var

NewMatrixSize: LongInt;

begin

NewMatrixSize := AMatrix.ColCount * AMatrix.RowCount * SizeOf(Float);

ReAllocMem(DataPtr, NewMatrixSize);

CopyMemory(DataPtr, AMatrix.DataPtr, NewMatrixSize);

FCols := AMatrix.ColCount;

FRows := AMatrix.RowCount

end;

procedure TMatrix.ReSize (NewCols, NewRows: Word);

var

NewMatrixSize: LongInt;

begin

NewMatrixSize := NewCols * NewRows * SizeOf(Float);

ReAllocMem(DataPtr, NewMatrixSize);

FCols := NewCols;

FRows := NewRows;

end;

procedure TMatrix.SetNull;

begin

ZeroMemory (DataPtr, FCols * FRows * SizeOf(Float));

end;

procedure TMatrix.SetSingle;