Страницы

Поиск по вопросам

понедельник, 15 июля 2019 г.

Некорректное вычисление графика в ZedGraph

Вопрос с преобразованием решился но вопрос с рисованием графика всё тот же. Нужно нарисовать такой график

С математической точки зрения,всё сделано по формулам f-частота была найдена путём деления 1 на период Т(тау) w-амега частота была найдена согласно формулам и выражена в аргументе.
Но это математически,но реализация в программе совсем другая. на вход я подаю frc,frc1-это мои границы построения графика,к примеру от -3 до 3 И следовательно в цикле уже находить значение f и w.
public static Complex GetSpectralDensity(double U, double frequency, double T,double x) { NumericalIntegration integration = new NumericalIntegration(); for (double fx= frc, counter = 1; fx <= frc1; fx++, counter++) { double f = 1 / T; double w = 2 * Math.PI * f; } return U * integration.Calculate(t => Math.Cos(w * t), 0, T) - Complex.ImaginaryOne * U * integration.Calculate(t => Math.Sin(w * t), 0, T); }
После происходит процедура взятия числа и его модуля.

Было перепробовано много различных вариантов(такие как взятие мнимого числа,изменения параметров по умолчанию) но приемлемый реализован ниже.
public static double GetSinModul(double U, double frequency, double T,int frc,int frc1) { double x2=0; List value = new List(); value.Add(GetSpectralDensity(U, frequency, T, 1,frc,frc1)); value.ForEach(x1=>x2=x1.Real); return U * T * Math.Abs(Math.Sin(x2) /x2); }
Отрывок метода рисования моего графика.Впрочем это отрывок рисует то что ему даст метод.
for (double fr = xmin; fr <= xmax; fr += shag) { for (frequency = frc, counter = 1; frequency <= frc1; frequency++, counter++) { list.Add(fr,GetSinModul(U,frequency,T,frc,frc1)); } }
LineItem curve = panel1.AddCurve("Line",list,Color.Blue,SymbolType.None);
Приблизительно график совсем чуть-чуть близок к тому что нужно но не хватает т.н. лепестков(полукругов между числами где спектральная плотность уходит в 0).
И оно так и выводит,но до оригинала далеко.


Ответ

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

Эту формулу можно упростить, посчитав интеграл, тем самым нам не придется высчитывать интеграл программно:

Только при реализации нужно будет учесть деление на 0. При омега = 0, спектральная плотность равна:

Дальше вы приводите формулу, которая высчитывает спектральную плотность амплитуд. Эта формула неверна для сигнала заданного на промежутках от 0 до тау. Вы верно сказали, что для нахождения спектральной плотности амплитуд нужно посчитать модуль спектральной плотности, но в в вашей формуле этот модуль высчитывается на основе преобразованной формулы спектральной плотности для сигнала на промежутках [-тау/2,тау/2]. Вам эта формула, во-первых, не подходит, а во-вторых, она Вам и не нужна. Когда Вы найдете спектральную плотность, вы возьмете модуль ее значения (модуль комплексного числа), тем самым получите спектральную плотность амплитуд.
Реализация
Получается, что не нужны классы для высчитывания определенных интегралов, которые я Вам в прошлый раз показывал. Но если Вы уже написали ту, часть, которую я давал раньше, можете ее оставить. У Вас тогда получится, что задачу решаете двумя способами: первый через интегрирование, а второй уже по формуле, которую описал выше:
public static Complex GetSpectralDensity(double amplitude, double angularFrequency, double duration) { // Учитываем деление на 0 if (angularFrequency == 0) return new Complex(amplitude * duration, 0); return (amplitude / (Complex.ImaginaryOne * angularFrequency)) * (1 - Complex.Exp(-Complex.ImaginaryOne * angularFrequency * duration)); }
Для вычисления спектральной плотности амплитуд нужно высчитать модуль спектральной плотности:
public static double GetSpectralDensityOfAmplitude(Complex spectralDensity) { return Complex.Abs(spectralDensity); }
По вашему коду и реализации:
Метод GetSpectralDensity. Зачем вы здесь считаете омегу? Омега это и есть аргумент frequency, его конечно, лучше переименовать в angularFrequency Метод GetSinModul. Считает непонято что, а не спектральную плотность амплитуд. Вместо выражения омега*t/2 из формулы, Вы зачем-то подставляете значение спектральной плотности, хотя эта формула и есть спектральная плотность. Цикл в построении графика. Зачем здесь counter, который нигде не используется? Для отладки/логгирования делали?
UPD
Метод GetSpectralDensityOfAmplitude дает значения спектральной плотности амплитуд. Вы находите на разных угловых частотах эти значения, и строите по ним график, т.е. должно получится что-то подобное этому:
double amplitude = 10; double duration = 1; double frequencyMin = -100; double frequenceMax = 100; double step = 0.01;
for (double frequency = frequencyMin; frequency <= frequenceMax; frequency += step) { double angularFrequency = 2 * Math.PI * frequency; pointList.Add(angularFrequency, GetSpectralDensityOfAmplitude( GetSpectralDensity(amplitude, angularFrequency, duration) )); }
pane.AddCurve("Spectral density of the amplitude", pointList, Color.Blue, SymbolType.None);

Комментариев нет:

Отправить комментарий