русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Программная реализация класса символического метода


Дата добавления: 2015-01-16; просмотров: 620; Нарушение авторских прав


При составлении алгоритмов символического исчисления мы будем широко использовать объекты таких ранее созданных классов, как полиномы и векторы. Большинство данных и обслуживающих методов сосредоточим в заголовочном файле laplas.h (лучше дать в нем только интерфейсную часть, а реализационную перенести в файл laplas.cpp и включить его в состав программного проекта – последний вариант даст возможность использовать однократную предварительную компиляцию заголовочного файла при отладке программы, если не использовать в этом файле процедуры инициализации данных). Если в дальнейшем предполагается создать из файла реализации библиотечный файл, то разделение на интерфейсную и реализационную части обязательно.

Как всегда, в начало программы собираем все понадобившиеся при ее составлении заголовочные файлы интерфейса с библиотеками:

 

//Файл difequat.h

 

#include "vector.h"

#include "equation.h"

#include <windows.h>

#include <alloc.h>

#include "wlaplasm.rh"

#include "matrix.h"

 

 

/*Для упрощения записи конкретизируем типы векторных и матричных элементов */

typedef vector<double> dvector;

typedef matrix<double> dmatrix;

 

/*Шаблон структуры для сведений о корнях характеристического полинома*/

struct CA{

complex ROOT; //значение корня

complex A; //коэффициент для корня в оригинале

int J; //кратность

int O;}; //кому кратен

 

dmatrix SolMtr; /*Матрица решения и его производных*/

dvector userfunc; /*Вектор для произвольного возмущения*/

dvector tc; //Вектор аргумента решений

dmatrix FreqChMtr; /*Матрица для частотных характеристик*/

double w; //Частота среза

double Cufz; //Усиление на частоте среза

/*Класс обыкновенных линейных дифференциальных уравнений (ОЛДУ), содержащий методы работы, базирующиеся на операционном исчислении. */



 

class DifferentialEquation

{

//приватные данные

int rngl, rngr; /*Порядок уравнения - левая и правая часть*/

dvector nv; //Вектор начальных условий

double tend, tstep; /*Конечное время решения и шаг дискретизации по времени*/

int PointSolCnt; //Размерность вектора решения

 

//Полиномы левой, правой части и начальных условий

cpolynom PL,PR,PN;

 

/*Знаменатель и числитель изображения решения в виде полиномов*/

cpolynom PSOL,QSOL;

 

CA *R; /*указатель на структуру со сведениями о корнях*/

long RootCount; /*Количество корней общее - при наличии правой части уравнения оно не совпадает с его порядком слева*/

long rcount; /*Количество различных корней - за вычетом кратных*/

int cod; double omega, alpha; /*Сведения о стандартных возмущениях*/

 

public: //общедоступные члены класса

 

/*Конструктор должен получить коэффициенты уравнения, начальные условия, код стандартного возмущения и его параметры (частоту гармонической функции, постоянную экспоненты), конечное время решения и шаг*/

 

DifferentialEquation(dvector CFNL, dvector CFNR, dvector NU, int COD, double OMEGA, double ALPHA, double TEND, double TSTEP);

 

//Деструктор

~DifferentialEquation()

{

if(RootCount>0)

farfree(R);

}

 

/*Функция для вычисления корней характеристического полинома*/

void GetRoot();

 

/*Функция формирования числителя изображения производных функции решения*/

cpolynom Qsol(int der);/*аргумент - порядок производной*/

 

/*Функция, вычисляющая коэффициенты оригинала для всех корней; результат помещается в массив структур R*/

 

void GetCoeffOrigin(void);

 

 

/*Функция, возвращающая значение выхода при заданном значении аргумента*/

double GetValue(double t);

//Функция вычисления решения дифуравнения

void Sol();

//Функция для вычисления частотных характеристик

void FreqChar();

};

/*Теперь определения подпрограмм.

Нам понадобятся простые служебные функции - вычисления факториала и определения знака числа */

long fact(long x)

{

long ret=1;

for(long i=1;i<=x;i++)

ret*=i;

return ret;

}

 

 

inline long sign(double x)

{

return (x>0)?1:((x<0)?-1:0);

}

 

//Определения методов класса.

//Конструктор по данным пользователя

DifferentialEquation::DifferentialEquation(dvector CFNL,dvector CFNR,dvector NU, int COD, double OMEGA,double ALPHA, double TEND, double TSTEP): cod(COD), omega(OMEGA), alpha(ALPHA), tend(TEND), tstep(TSTEP)

{

//Определяем порядки уравнения слева и справа

rngl=CFNL.getm()-1;rngr=CFNR.getm()-1;

PL=cpolynom(rngl+1); PR=cpolynom(rngr+1);

PN=cpolynom(rngl);

/*Инициализация полиномов с преобразованием коэффициентов в комплексные и реверсированием их последовательности - мы предполагаем, что вводятся коэффициенты и начальные условия начиная со старшей производной*/

int i;

for(i=0;i<(rngl+1);i++) PL[i]=complex(CFNL[i],0);

PL=PL.reverse();

for(i=0;i<(rngr+1);i++) PR[i]=complex(CFNR[i],0);

PR=PR.reverse();

 

//Создадим также вектор начальных условий

nv=dvector(rngl);

for(i=0;i<rngl;i++)

nv[i]=NU[rngl-i-1];

 

/*Формирование полинома начальных условий (числителя изображения решения при свободном движении. Если будет ненулевая правая часть, то ее изображение надо прибавить к результату вычисления PN)*/

 

//p-полином первой степени р+0

cpolynom p(2);

p[0]=complex(0.0,0.0);p[1]=complex(1.0,0.0);

cpolynom D=PL,tpn;

for( i=0;i<rngl;i++)

{

D=D/p;//делим полином на p, понижая степень на 1

/*прибавляем произведение значения производной i-го порядка в начальной точке на полиномиальный коэффициент*/

for(int j=0;j<rngl;j++) D[i]*=nv[i];

tpn=nv[i]*D;

PN+=tpn;

}

 

/*Сформируем числитель QSOL и знаменатель PSOL изображения решения - это полиномиальная дробь*/

cpolynom rone;

rone[0]=complex(1.0,0.0);/* веществ. полиномиальная единица */

 

//Если возмущения нет

if(cod==0) {PSOL=PL; QSOL=PN;}

 

/*Если это единичный импульс или произвольная функция*/

if(cod==1||cod==6) {PSOL=PL; QSOL=PR+PN;}

 

/*Если на входе ступенька - изображение 1/p

if(cod==2) {QSOL=PN*p+PR; PSOL=PL*p;}

 

/*Если на входе синусоида - изображение w/(p2+w2).*/

 

if(cod==3)

{

QSOL=PN*((p^2)+((omega*rone)^2))+PR*omega;

PSOL=PL*((p^2)+((omega*rone)^2));

}

 

//Если косинусоида - изображение p/(p2+w2).

if(cod==4)

{

QSOL=PN*((p^2)+((omega*rone)^2))+(PR*p);

PSOL=PL*((p^2)+((omega*rone)^2));

}

 

//Если экспонента - изображение 1/(p+w).

if(cod==5)

{

QSOL=PN*(p+(alpha*rone))+PR;

PSOL=PL*(p+(alpha*rone));

}

 

PointSolCnt=floor(tend/tstep); /*Количество дискретных точек*/

/*Если объект конструируется для расчета частотных характеристик*/

if(cod==7)

{

FreqChar(); /*Вызываем метод расчета частотных характеристик*/

RootCount=0;//Нет необходимости вычислять корни

return; //Досрочно покидаем конструктор

}

 

/*Определим теперь общее количество корней характеристического полинома*/

RootCount=PSOL.getm()-1;

 

//После определения количества корней выделим память для хранения сведений о них*/

R=(CA*)farcalloc(RootCount,sizeof(CA));

memset(R,0,RootCount*sizeof(CA));

 

//Конструируем хранители решений

double j;

 

tc=dvector(PointSolCnt); //Вектор аргумента

for(i=0,j=0.0;i<PointSolCnt;i++,j+=tstep)

tc[i]=j;

/*Матрица решений на RootCount строк - для функции и ее производных*/

SolMtr=dmatrix(RootCount+1,PointSolCnt);

/*Сразу занесем в матрицу решений начальные значения функции и ее производных*/

if(RootCount>0)

for(i=0;i<RootCount;i++) SolMtr[i][0]=nv[i];

 

GetRoot(); //Вычисляем корни х-го полинома

 

}//Конец конструктора

 

 

/*Функция для вычисления корней характеристического полинома*/

void DifferentialEquation::GetRoot()

{

int i,j;

 

//ищем корни характеристического полинома

cvector polyroot=newton(PSOL);

 

//Ограничим точность вычисления корней вблизи нуля

for(i=0;i<RootCount;i++)

{

if(fabs(real(polyroot[i]))<1e-7)

polyroot[i]=complex(0,imag(polyroot[i]));

if(fabs(imag(polyroot[i]))<1e-7)

polyroot[i]=complex(real(polyroot[i]),0);

}

 

//Заносим в структуру значения корней

for(i=0;i<RootCount;i++) R[i].ROOT=polyroot[i];

/*определяем кратность каждого корня и заносим в структуру; признаком -1 пометим корни, уже проверенные на кратность. J=1 будет корень первой кратности корню О и т.д.*/

int repeat;

rcount=RootCount;/* Вначале предполагаем, что все корни различны*/

for(i=0;i<RootCount;i++)

{

repeat=1;

if(R[i].J!=-1) //корень еще не встречался

{

R[i].J=1; //количество повторений i-го корня

for(j=i+1;j<RootCount;j++)

if((R[j].J!=-1)&&(R[i].ROOT==R[j].ROOT))

{

repeat++;

rcount--;R[j].J=-1;R[j].O=i;

/*устанавливаем признак того, что этот корень уже учтён*/

}

R[i].J=repeat;//кратность корня

}

}

}

 

 

/*Подпрограмма определения числителя изображения производной решения*/

cpolynom DifferentialEquation::Qsol(int der)

{

cpolynom Q=QSOL, p(2),sum;

//доформируем числитель изображения

p[0]=complex(0,0);p[1]=complex(1.0,0.0);

if(der>0 && cod!=6)

{

for(int i=0;i<der;i++)

sum+=PN[RootCount-i-1]*p^(der-i-1);

Q=Q*(p^der)-PSOL*sum;

}

return Q;

}

 

 

/*Функция, вычисляющая коэффициенты оригинала для всех корней; результат помещается в массив структур R*/

 

void DifferentialEquation::GetCoeffOrigin()

{

complex ap, tp;/*Для значений числителя и знаменателя*/

/*при подстановке значения корня числитель может оказаться полиномом или просто числом*/

int qi=QSOL.getm();//Выясняем это

int pi=PSOL.getm();

//Если это число

if(qi==1) ap=QSOL[0];/*Его и используем в качестве значения числителя*/

if(pi==1) tp=PSOL[0];

if(RootCount==1)//Единственный некратный корень

{

/*Вычисляем значение производной знаменателя изображения решения при подстановке в нее значения единственного корня*/

if(pi>1) tp=derive(PSOL,1)(R[0].ROOT);

if(qi>1) ap=QSOL(R[0].ROOT);/*Если числитель - полином, подставляем в него значение корня*/

R[0].A=ap/tp;

return;

}

 

//Если корней больше одного

long i,j,k,l;

cpolynom CH=QSOL,ZN=PSOL,RCH,RZN;

cpolynom pw=2;

cpolynom A;

//dcomplex ch;

 

for(k=0;k<RootCount;k++)

{

if(R[k].J==1) //Для некратного корня

{ //Формируем полином pw вида p+0

cpolynom pw(2);

pw[0]=-R[k].ROOT;pw[1]=complex(1.0,0.0);

if(qi>1) ap=QSOL(R[k].ROOT);

if(pi>1) tp=(PSOL/pw)(R[k].ROOT);

R[k].A=ap/tp;

}

 

//Если корень кратный

if(R[k].J>1)

{

cpolynom pw(2);pw[0]=-R[k].ROOT;

pw[1]=complex(1.0,0.0);

cpolynom pw1=(pw^R[k].J);

//До кратности этого корня

for(j=1;j<=R[k].J;)

{

if(j==1)

{

if(qi>1) ap=QSOL(R[k].ROOT);

if(pi>1) tp=(PSOL/pw1)(R[k].ROOT);

R[k].A=ap/tp;j++;

}

else

{

for(i=k+1;i<RootCount;i++)

{

//Если нашли кратный текущему

if(R[i].O==k)

{

cpolynom tmp=PSOL/pw1;

//Восстанавливаем знаменатель

cpolynom chisl=QSOL, znamen=PSOL/pw1,

dchisl, dznamen, m1, m2;

/*Дифференцируем дробь изображения

решения j-1 раз*/

for(l=1;l<=(j-1);l++)

{

dchisl=derive(chisl,1);

dznamen=derive(znamen,1);

m1=dchisl*znamen;

m2=dznamen*chisl;

chisl=m1-m2;

znamen^=2;

}

R[i].A=chisl(R[k].ROOT)/

(znamen(R[k].ROOT)*fact(j-1));

j++;

}

}

}

}

}

}

}

 

 

/*Подпрограмма, возвращающая значение функции решения ОЛДУ или ее производной заданного порядка при заданном t. Она реализует формулу

=f(t),

где

.*/

double DifferentialEquation::GetValue(double t)

{

int k,i,index;

double d;

complex result(0,0);

if(RootCount>0)

{

for(k=0;k<rcount;k++)

{

index=0;

if(R[k].J==1)//Если корень простой

result+=R[k].A*exp(R[k].ROOT*t);

if(R[k].J>1)//Если корень кратный

{

result+=R[k].A*exp(R[k].ROOT*t);index++;

for(i=k+1;i<rcount;i++)

{

if((R[i].O==k)&&(R[i].J==-1))

{

double dpw=R[k].J-index;

result+=R[k].A*pow(t,dpw)*

exp(R[k].ROOT*t)/fact(R[k].J-index);

index++;

}

}

}

}

d=real(result);

return d;

}

return 0;

}

 

 

/*Подпрограмма решения дифуравнения - она просто вызывает имеющиеся методы*/

void DifferentialEquation::Sol()

{

int i,k;

cpolynom Q=QSOL;

if(cod==6)

{

GetCoeffOrigin();

/*Вычисляем реакцию на импульс и пишем в 0-ю строку SolMtr*/

for(k=1;k<PointSolCnt;k++)

SolMtr[0][k]=GetValue(tc[k]);

/*Реакцию на произвольное возмущение разместим в 1-й строке SolMtr*/

for(i=1;i<PointSolCnt;i++)

{

SolMtr[1][i]=0;

for(k=0;k<i;k++)

SolMtr[1][i]+=SolMtr[0][i-k]*

userfunc[i]*tstep;

}

}

else

for(i=0;i<RootCount;i++)

{

QSOL=Qsol(i);

GetCoeffOrigin();

for(k=1;k<PointSolCnt;k++)

SolMtr[i][k]=GetValue(tc[k]);

QSOL=Q;

}

}

 

 

/* Подпрограмма вычисления частотных характеристик. Вначале подбирает частоту среза - то есть определяет верхнюю границу диапазона частот для исследования - по заданному пользователем коэффициенту снижения коэффициента усиления по отношению к нулевой частоте. Для этого частота меняется по простому алгоритму с переменным по величине и знаку шагом и вычисляется выходная амплитуда на этой частоте как модуль передаточной функции после подстановки в нее p=jw.*/

void DifferentialEquation::FreqChar()

{

FreqChMtr=dmatrix(5,PointSolCnt);

complex jone=complex(0.0,1.0);// мнимая единица

//QSOL=PR;PSOL=PL;

 

double KU0=fabs(real(PR[0]/PL[0])); /*Усиление на нулевой частоте*/

double KUZ=Cufz*KU0; //Заданное усиление

double wstep=1.0, //Начальный шаг по частоте

QW, //Значение числителя АФХ при частоте w.

PW, //Значение знаменателя АФХ при частоте w.

KU=KU0, /*Усиление при частоте w - вначале равно KU0.*/

RQ, //Вещественная часть значения числителя

IQ, //Мнимая часть значения числителя

RP, //Вещественная часть значения знаменателя

IP; //Мнимая часть значения знаменателя

 

if(PR.getm()==1)

QW=real(PR[0]); //Если справа - просто число

//Подбираем частоту среза

for(w=wstep;;w+=wstep)

{

if(PR.getm()>1) /*Если изображение правой части – полином*/

QW=sqrt(real(PR(w*jone))*real(PR(w*jone))+

imag(PR(w*jone))*imag(PR(w*jone)));

PW=sqrt(real(PL(w*jone))*real(PL(w*jone))+

imag(PL(w*jone))*imag(PL(w*jone)));

KU=QW/PW; //Усиление на текущей частоте

if((KU< 1.1*KUZ) && (KU>0.9*KUZ))

break; //Если попали в диапазон

if((KU<0.9*KUZ) && (wstep>0)) wstep=-0.1*wstep;

if((KU>1.1*KUZ) && (wstep<0)) wstep=-0.1*wstep;

}

/*Заполним вектор частоты в матрице - мы разместим его в 0-й строке*/

wstep=w/PointSolCnt;

int i;

for(i=0;i<PointSolCnt;i++)

FreqChMtr[0][i]=i*wstep;

//Вычисляем частотные характеристики

if(PR.getm()==1) {RQ=real(PR[0]); IQ=0;}

for(i=0;i<PointSolCnt;i++)

{

if(PR.getm()>1)

{

RQ=real(PR(jone*FreqChMtr[0][i]));

IQ=imag(PR(jone*FreqChMtr[0][i]));

}

RP=real(PL(jone*FreqChMtr[0][i]));

IP=imag(PL(jone*FreqChMtr[0][i]));

FreqChMtr[1][i]=(RQ*RP+IQ*IP)/(RP*RP+IP*IP);

//Вещественная частотная

FreqChMtr[2][i]=(IQ*RP-RQ*IP)/(RP*RP+IP*IP);

//Мнимая частотная

FreqChMtr[3][i]=sqrt(FreqChMtr[1][i]*

FreqChMtr[1][i]+FreqChMtr[2][i]*

FreqChMtr[2][i]); //Амплитудная

/*При расчете фазовой х-ки учтем скачек тангенса при фазе p/2*/

if(FreqChMtr[1][i]>0)

FreqChMtr[4][i]=atan(FreqChMtr[2][i]/

FreqChMtr[1][i]);

if(FreqChMtr[1][i]<=0)

FreqChMtr[4][i]=-M_PI+atan(FreqChMtr[2][i]/

FreqChMtr[1][i]);

//Если скачек не учитывать, то можно проще:

/*FreqChMtr[4][i]=atan(FreqChMtr[2][i]/

FreqChMtr[1][i]);//Фазовая */

}

}

 

 

/*Программа для решения ОЛДУ с постоянными коэффициентами символическим методом - файл difequat.cpp*/

 

#include "difequatm.h"

int sc; //Количество точек решения

char Userfile[80]; /*Для имени файла с произвольным возмущением*/

 

/*Для графического отображения функций решения объявим массив структур типа POINT, в который потом перенесем пересчитанные в координаты значения отображаемой функции и значения ее аргумента */

POINT *pt;

int DeriveNumber=0; //Порядок производной

/*Переменные для хранения размеров клиентской области окна вывода */

int cxClient, cyClient;

 

int Cod, //Код возмущения

Rngl,Rngr; //Порядок уравнения слева и справа

double Tend,Tstep, /*Конечное время решения и шаг по времени*/

Omega,Alpha; //Параметры гармоник и экспоненты

 

char* buf; //Буфер приема строк ввода пользователя

char*tmp; //Для приема указателя на слово от strtok

BOOL err;

//Прототипы функции окна и диалога

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

HINSTANCE hInst; /*Для сохранения идентификатора приложения*/

 

//Главная функция программы

#pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

hInst=hInstance;

WNDCLASSEX wc;

 

wc.cbSize=sizeof(wc);

wc.style=CS_HREDRAW|CS_VREDRAW;

wc.lpfnWndProc=(WNDPROC)WndProc;

wc.cbClsExtra=0;

wc.cbWndExtra=0;

wc.hInstance=hInstance;

wc.hIcon=(HICON)LoadIcon(0,IDI_WINLOGO);

wc.hCursor=(HCURSOR)LoadCursor(0,IDC_ARROW);

wc.hbrBackground=(HBRUSH)GetStockObject

(COLOR_BACKGROUND);//COLOR_BACKGROUND;

wc.lpszMenuName="Laplas";

wc.lpszClassName="Numerical Methods Class";

wc.hIconSm=0;

 

if(!RegisterClassEx(&wc))

{

MessageBox(0,"Не удалось зарегистрировать класс окна",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

HWND hwnd=CreateWindowEx(WS_EX_CONTEXTHELP, "Numerical Methods Class", "Численные методы. Символический метод решения ОЛДУ",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

0,

0,

hInstance,

);

 

ShowWindow(hwnd,nCmdShow);

UpdateWindow(hwnd);

 

//userfile= new char[250];

MSG msg;

while(GetMessage(&msg,0,0,0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

delete[] pt;

return 0;

}

 

 

/* Массив значений отображаемой функции и ее аргумента нужно преобразовать в массив значений координат в окне отображения. Для такого пересчета напишем подпрограмму GetCoord - в качестве аргументов ей понадобятся массивы значений функции и аргумента. */

 

//Структура для смещений координатных осей

struct OFF{long x,y;}off;

 

void getCoord(dvector y, dvector x)

{

long i;

/*Определим наибольшее, наименьшее значение функции, диапазон изменения- хотя было бы неплохо получать эти значения из класса vector */

double fymax, fymin, fxmax, fxmin;

fymax=fymin=y[0];

fxmax=fxmin=x[0];//Для начала пусть так

for(i=0;i<sc;i++)

{

if(y[i]>fymax) fymax=y[i];

if(y[i]<fymin) fymin=y[i];

if(x[i]>fxmax) fxmax=x[i];

if(x[i]<fxmin) fxmin=x[i];

}

//Отцентрируем все данные относительно минимумов

for(i=0;i<sc;i++)

{x[i]-=fxmin;y[i]-=fymin;}

 

//Теперь заполним массив структур pt

if(fxmax!=fxmin && fymax!=fymin)

{

for(i=0;i<sc;i++)

pt[i].x=x[i]*(double(cxClient)/(fxmax-fxmin));

 

for(i=0;i<sc;i++)

pt[i].y=cyClient-long(y[i]*

(double(cyClient)/(fymax-fymin)));

}

if((fxmax-fxmin)!=0)

off.x=fxmin*((double)cxClient/(fxmax-fxmin));

if((fymax-fymin)!=0)

off.y=fymin*((double)cyClient/(fymax-fymin));

}

 

 

//Оконная процедура

HPEN hpen[6];

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

switch(uMsg)

{

case WM_SIZE:/* Определяем размеры клиентской области окна*/

{

cxClient=LOWORD(lParam);

cyClient=HIWORD(lParam);

return 0;

}

case WM_CREATE:

{

/*Создаем перья для рисования случайными цветами*/

randomize();

for(int i=0;i<6;i++)

hpen[i]=CreatePen(PS_SOLID, 5,

RGB(random(55), random(155),random(255)));

return 0;

}

}

if(uMsg==WM_COMMAND)

switch(LOWORD(wParam))

{

case CM_DATE:

{

DialogBox(hInst, MAKEINTRESOURCE(DIALOG_1),

hwnd, (DLGPROC)DlgProc);

return 0;

}

case CM_CLEAR:

{

InvalidateRect(hwnd,NULL,TRUE);

return 0;

}

 

//Рисуем заданный переходный процесс

case CM_GRAPH:

{

hdc=GetDC(hwnd); //Получаем контекст

if(Cod==6)

{

getCoord(SolMtr[1],tc);

SelectObject(hdc,hpen[3]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

}

else

{

getCoord(SolMtr[0],tc); /*Вычисляем массив координат точек*/

SelectObject(hdc,hpen[0]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

 

/*Вычисляем массив координат точек заданной производной*/

getCoord(SolMtr[DeriveNumber],tc);

SelectObject(hdc,hpen[DeriveNumber]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

}

/* Можно нарисовать координатные оси - но мы этого не делаем, ограничившись качественной картиной процессов; предоставляем это вам для самостоятельной проработки. Один из вариантов:

SelectObject(hdc,hpen[8]);

//Вертикальная ось

MoveToEx(hdc,fabs(off.x),0,NULL);

LineTo(hdc,fabs(off.x),cyClient);

//Горизонтальная ось

MoveToEx(hdc,0,cyClient-fabs(off.y),NULL);

LineTo(hdc,cxClient,cyClient-fabs(off.y));

*/

ReleaseDC(hwnd,hdc);

return 0;

}

 

//Вещественная частотная

case CM_U:

{

hdc=GetDC(hwnd);//Получаем контекст

SelectObject(hdc,hpen[1]);

getCoord(FreqChMtr[1],FreqChMtr[0]);

//Вычисляем массив координат точек

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

ReleaseDC(hwnd,hdc);

return 0;

}

 

//Мнимая частотная

case CM_V:

{

hdc=GetDC(hwnd);//Получаем контекст

SelectObject(hdc,hpen[2]);

getCoord(FreqChMtr[2],FreqChMtr[0]);

//Вычисляем массив координат точек

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

ReleaseDC(hwnd,hdc);

return 0;

}

 

//Аплитудная частотная характеристика

case CM_AMP:

{

hdc=GetDC(hwnd);//Получаем контекст

getCoord(FreqChMtr[3],FreqChMtr[0]);

//Вычисляем массив координат точек

SelectObject(hdc,hpen[3]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

ReleaseDC(hwnd,hdc);

return 0;

}

 

//Фазовая частотная характеристика

case CM_PHAZE:

{

hdc=GetDC(hwnd);//Получаем контекст

SelectObject(hdc,hpen[4]);

getCoord(FreqChMtr[4],FreqChMtr[0]);

//Вычисляем массив координат точек

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

ReleaseDC(hwnd,hdc);

return 0;

}

 

//Амплитудно-фазовая характеристика

case CM_AP:

{

hdc=GetDC(hwnd);//Получаем контекст

SelectObject(hdc,hpen[5]);

//Вычисляем массив координат точек

getCoord(FreqChMtr[2],FreqChMtr[1]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

ReleaseDC(hwnd,hdc);

return 0;

}

 

 

//Фазовый портрет функция-производная

case CM_PORTRET:

{

hdc=GetDC(hwnd);//Получаем контекст

SelectObject(hdc,hpen[4]);

//Вычисляем массив координат точек

getCoord(SolMtr[0],SolMtr[DeriveNumber]);

PolyBezier(hdc,pt,3*(((sc-4)/3)+1)+1);

 

ReleaseDC(hwnd,hdc);

return 0;

}

}

 

if(uMsg==WM_DESTROY)

{

PostQuitMessage(0);

return 0;

}

return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

 

 

//Функция обслуживания диалога с пользователем

 

#pragma argsused

LRESULT CALLBACK DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

int i;

char buf[80];

 

switch (uMsg)

{

case WM_INITDIALOG: return TRUE;

 

case WM_COMMAND:

switch(wParam)

{

case IDOK:/* Пользователь закончил ввод данных о дифуравнении */

{

//Получаем и интерпретируем введенные строки

//Конечное время

SendDlgItemMessage(hdlg, IDC_EDIT12, EM_GETLINE, (WPARAM)0, (LPARAM)(LPSTR)buf);

Tend=atof(buf);

if(Tend<=0)

{

MessageBox(0,"Не введено или ошибочно конечное время", 0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

//Шаг по времени

SendDlgItemMessage(hdlg, IDC_EDIT11, EM_GETLINE, (WPARAM)0, (LPARAM)(LPSTR)buf);

Tstep=atof(buf);

if(Tstep<=0)

{

MessageBox(0,"Ошибочен шаг по времени ", 0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

if(Tstep>Tend)

{

MessageBox(0,"Ошибочен шаг по времени - будет ноль шагов решения ",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

//Количество точек в решении

sc=floor(Tend/Tstep);

if(sc<=0)

{

MessageBox(0,"Ноль шагов решения - ошибка в шаге или конечном времени", 0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

/*После получения количества точек определяются размеры массивов для хранения информации*/

pt=new POINT[sc];

userfunc=dvector(sc);

 

//Порядок справа

Rngr=GetDlgItemInt(hdlg, IDC_EDIT4, &err, FALSE);

if(Rngr>Rngl || Rngr<0)

{

MessageBox(0,"Некорректен код порядка справа",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

dvector Cfnr(Rngr+1);

 

//Символьный формат коэффициентов справа

SendDlgItemMessage(hdlg, IDC_EDIT5, EM_GETLINE, (WPARAM)0, (LPARAM)(LPSTR)buf);

tmp=strtok(buf," ");

for(i=0;tmp!=NULL;i++)

{

Cfnr[i]=atof(tmp);

tmp=strtok(NULL," ");

}

if(i<(Rngr+1))

{

MessageBox(0,"Количество коэффициентов должно быть порядок+1",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

//Порядок уравнения слева

Rngl=GetDlgItemInt(hdlg, IDC_EDIT1, &err, FALSE);

if(Rngl<=0)

{

MessageBox(0,"Нет смысла решать дифуравнение 0-го порядка",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

/*После определения порядка определяем вектор коэффициентов */

dvector Cfnl(Rngl+1);

/*Получаем символьное представление коэффициентов слева*/

SendDlgItemMessage(hdlg, IDC_EDIT2, EM_GETLINE, (WPARAM)0, (LPARAM)(LPSTR)buf);

/*Выполняем разборку строки и заполнение вектора Cfnl*/

tmp=strtok(buf," ");

for(i=0;tmp!=NULL;i++)

{

Cfnl[i]=atof(tmp);

tmp=strtok(NULL," ");

}

if(i<(Rngl+1))

{

MessageBox(0,"Количество коэффициентов должно быть порядок+1",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

//Начальные условия

dvector Nu(Rngl);

/*Получаем символьное представление начальных условий*/

SendDlgItemMessage(hdlg, IDC_EDIT3, EM_GETLINE, (WPARAM)0,(LPARAM)(LPSTR)buf);

tmp=strtok(buf," ");

for(i=0;tmp!=NULL;i++)

{Nu[i]=atof(tmp); tmp=strtok(NULL," ");}

int ncount=i;

//Частота гармонических возмущений

SendDlgItemMessage(hdlg, IDC_EDIT7, EM_GETLINE, (WPARAM)0,(LPARAM)(LPSTR)buf);

Omega=atof(buf);

 

/*Показатель степени экспоненциального воздействия*/

SendDlgItemMessage(hdlg, IDC_EDIT8, EM_GETLINE, (WPARAM)0,(LPARAM)(LPSTR)buf);

Alpha=atof(buf);

 

//Код возмущения

Cod=GetDlgItemInt(hdlg, IDC_EDIT6, &err, FALSE);

if(Cod<0 || Cod>7)

{

MessageBox(0,"Некорректный код возмущения. Задайте от 0 до 6",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

if((Cod==3 || Cod==4) && Omega==0)

{

MessageBox(0,"Для гармоник задайте частоту",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

if(ncount<Rngl && Cod==0)

{

MessageBox(0,"Колич. нач. усл. должно быть равно порядку слева \n или 0 (при ненулевом коде возмущения)",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

if(ncount>0&&ncount<Rngl&&Cod>0&&Cod<7)

{

MessageBox(0,"Колич. нач. усл. должно быть равно порядку слева \n или 0 (при ненулевом коде возмущения)",0, MB_OK|MB_ICONEXCLAMATION);

return 0;

}

 

//Коэффициент усиления на частоте среза

SendDlgItemMessage(hdlg, IDC_EDIT10, EM_GETLINE, (WPARAM)0,(LPARAM)(LPSTR)buf);

Cufz=atof(buf);

//Имя файла с произвольным возмущением

SendDlgItemMessage(hdlg, IDC_EDIT9, EM_GETLINE, (WPARAM)0,(LPARAM)(LPSTR)Userfile);

if(Cod==6 && strlen(Userfile))

{

ifstream uf(Userfile);

/*Если файл открыт - читаем из него в вектор userfunc*/

if(uf) {uf>>userfunc; uf.close();}

else

{

MessageBox(0,"Неудача при открытии файла с произвольным возмущением. \n Вычисляем по имитации",0,MB_OK|MB_ICONEXCLAMATION);

for(i=0;i<sc;i++)

userfunc[i]=exp(-0.02*i*Tstep)*

cos(i*Tstep*0.05);

}

}

/*Порядок производной, график которой надо отрисовать рядом с функцией решения*/

DeriveNumber=GetDlgItemInt(hdlg, IDC_EDIT13, &err, FALSE);

if(DeriveNumber<0&&DeriveNumber>(Rngl-1))

{

MessageBox(0,"Не корректен порядок отображаемой производной",0, MB_OK|MB_ICONEXCLAMATION);

DeriveNumber=0;

}

 

/*После приема ввода пользователя и его преобразования конструируем объект и вызываем подпрограмму решения для заполнения матрицы решения */

DifferentialEquation Dequ(Cfnl,Cfnr, Nu, Cod, Omega, Alpha,Tend, Tstep);

/*Вызываем метод решения, получая матрицу решения*/

if(Cod!=7)

{

Dequ.Sol();

//Сохраним матрицу решений в файле

ofstream os("solmtr.txt");os<<SolMtr;

}

if(Cod==7)

{

Dequ.FreqChar();

//Сохраним матрицу в файле

ofstream os1("freqchar.txt");

os1<<SolMtr;

}

EndDialog(hdlg,0);

return TRUE;

}//idOK

}//switch wparam

}//switch umsg

return FALSE;

}

 

 

//Файл ресурсов

 

#include "wlaplasm.rh"

 

Laplas MENU

{

MENUITEM "Ввод исходных данных", CM_DATE

MENUITEM "График решения",CM_GRAPH

POPUP "Частотные характеристики"

{

MENUITEM "Вещественная частотна\377", CM_U

MENUITEM "Мнимая частотна\377", CM_V

MENUITEM "Амплитудно-частотна\377", CM_AMP

MENUITEM "Фазо-частотна\377", CM_PHAZE

MENUITEM "Амплитудно-фазова\377", CM_AP

}

MENUITEM "Фазовый портрет",CM_PORTRET

 

MENUITEM "Очистка области вывода", CM_CLEAR

}

 

 

DIALOG_1 DIALOG 0, 0, 240, 185

EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP

STYLE DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX

CAPTION "ВВОД ИСХОДНЫХ ДАННЫХ"

FONT 10, "MS Sans Serif"

{

CONTROL "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 168, 50, 14

CONTROL "Порядок левой части уравнения", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 7, 5, 113, 8

CONTROL "Коэффициенты левой части уравнения", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 15, 138, 8

CONTROL "Начальные условия", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 25, 70, 8

CONTROL "Порядок правой части уравнения", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 36, 120, 8

CONTROL "Коэффициенты правой части уравнения", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 48, 141, 8

CONTROL "ЧИСЛА РАЗДЕЛЯЙТЕ ТОЛЬКО ПРОБЕЛАМИ!", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 156, 164, 8

CONTROL "", IDC_EDIT1, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 4, 20, 9

CONTROL "", IDC_EDIT2, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 15, 89, 9

CONTROL "", IDC_EDIT3, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152 , 26, 87, 9

CONTROL "0", IDC_EDIT4, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 36, 23, 9

CONTROL "1.0", IDC_EDIT5, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 48, 89, 9

CONTROL "Частота гармонических возмущений", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 72, 135, 8

CONTROL "Показатель экспоненты", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 84, 142, 8

CONTROL "Имя файла с произвольным возмущением", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 96, 140, 8

CONTROL "0.05", IDC_EDIT7, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 72, 88, 9

CONTROL "0.05", IDC_EDIT8, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 84, 88, 8

CONTROL "", IDC_EDIT9, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 96, 89, 9

CONTROL "Усиление на частоте среза", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 108, 100, 7

CONTROL "0.01", IDC_EDIT10, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 108, 20, 9

CONTROL "Шаг по аргументу", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 120, 115, 8, 0

CONTROL "", IDC_EDIT11, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 120, 20, 8, 0

CONTROL "Максимальное значение аргумента", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 132, 132, 8, 0

CONTROL "", IDC_EDIT12, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 132, 20, 8, 0

CONTROL "Код возмущ.: 0-нет, 1-имп, 2-ступ, 3-sin,4-cos,5-exp, 6-произв. ф-я ", -1, "static", SS_SIMPLE | WS_CHILD | WS_VISIBLE, 4, 60, 212, 8, 0

CONTROL "0", IDC_EDIT6, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 220, 60, 20, 8, 0

CONTROL "Порядок отображаемой производной", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 144, 132, 8, 0

CONTROL "", IDC_EDIT13, "edit", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 152, 144, 20, 8, 0

}

 

//Файл объявления констант для файла ресурсов

#define DIALOG_1 100

#define IDC_EDIT1 101

#define IDC_EDIT2 102

#define IDC_EDIT3 103

#define IDC_EDIT4 104

#define IDC_EDIT5 105

#define IDC_EDIT6 106

#define IDC_EDIT7 107

#define IDC_EDIT8 108

#define IDC_EDIT9 109

#define IDC_EDIT10 110

#define IDC_EDIT11 111

#define IDC_EDIT12 112

#define IDC_EDIT13 113

 

#define CM_DATE 201

#define CM_GRAPH 202

#define CM_AMP 203

#define CM_PHAZE 204

#define CM_AP 205

#define CM_CLEAR 206

#define CM_PORTRET 207

#define CM_U 208

#define CM_V 209

 



<== предыдущая лекция | следующая лекция ==>
Ограничения области применения символического метода | Конечно-разностные методы решения задачи Коши для линейных и нелинейных ОДУ


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.845 сек.