2014-12-02 5 views
0

Я использую Matlab для поиска корней нелинейной функции. Уравнение является длительным, и я использовал другой .m, чтобы сохранить функцию, то код, который идет какКорни нелинейного уравнения с использованием Matlab

function x_c = f_x_c(s,H,VA,Lo,qc,EA,NF,Sj,Fj) 

if (s < 0) || (s > Lo); 
    disp('The value of s is invalid') 
    disp(['s = ' num2str(s)]); 
    return 
end 

C1 = H/qc; 
if NF == 0 
    n = 0; 
    sn = 0; 
    sum_Fj = 0; 
end 
if NF >= 1 
    Sj_Q = [0; Sj; Lo]; 
    %Determine n and sn if 0 <= s < Lo: 
    if s < Lo 
    STOP = 0; 
    k = 0; 
     while STOP == 0 
     k = k + 1; 
      if (s >= Sj_Q(k,1)) && (s < Sj_Q((k + 1),1)) 
      STOP = 1; 
      end 
     end 
    n = k - 1; 
    sn = Sj_Q(k,1); 
    end 

    %Determine n and sn if s = Lo: 
    if s == Lo 
     n = NF; 
     sn = Sj(NF,1); 
    end 

sum_Fj = sum(Fj(1:n,1)); 
end 


x_c = (H/EA)*s; 
x_c = x_c + C1*asinh((qc*s - VA + sum_Fj)/H) + ... 
- C1*asinh((qc*sn - VA + sum_Fj)/H); 

for j = 1:n 
    sk = Sj_Q((j + 1),1); 
    sk_1 = Sj_Q(j,1); 
    sum_Fj = sum(Fj(1:(j - 1))); 
    x_c = x_c + ... 
    + C1*asinh((qc*sk - VA + sum_Fj)/H) + ... 
    - C1*asinh((qc*sk_1 - VA + sum_Fj)/H); 
end 

переменная H здесь. Нет проблем с кодом, потому что он возвращает мне это длинное уравнение, когда я ввожу следующее в основной файл.

syms x 
equation = -(XB - XA) + f_x_c(s,x,VA,Lo,qc,EA,NF,Sj,Fj); %Replaced H with variable H and all other arguments are pre-defined 

Теперь, я хочу решить это уравнение около H0. Когда я поставил fzero(@(x)equation, H0), он дает мне ошибку, которая идет как

Undefined function 'isfinite' for input arguments of type 'sym'. 

Error in fzero (line 308) 
    elseif ~isfinite(fx) || ~isreal(fx) 

Error in main (line 50) 
fzero(@(x)equation, H0) 

Как я могу решить эту проблему?

EDIT:

уравнение имеет хотя бы один корень, потому что, если я использую ezplot построить функцию, я получаю следующую цифру. enter image description here

+0

@patrik Нет, у меня нет такой переменной. Фактически, в 'fzero.m' есть одна строка, которая имеет' isfinite'. Эта строка имеет вид 'if any (~ isfinite ([fa fb])) || any (~ isreal ([fa fb])) ' –

+0

Извините, мой плохой. Однако я попытался воспроизвести ошибку с более простой функцией, но в настоящее время я не могу воспроизвести ошибку. Строка 'function x_c = equation = XB - XA + f_x_c (s, x, VA, Lo, qc, EA, NF, Sj, Fj);' также не может быть выполнена. Могу я спросить вас, что вы хотите сделать? У вас есть файл функции, который принимает входные данные и дает результат, на который вы хотите найти корень? – patrik

+0

@patrik Да, Sj и Fj должны быть матрицами в функции, поэтому ваш код может не работать. Код слишком большой! Вы хотите, чтобы я опубликовал все это здесь? –

ответ

0

Понятно, что я добрался до того же места, что и вы, однако я получил линию 309, поскольку, по-видимому, с использованием isfinite на sym не вызывает сбой в matlab 2014b. Однако isfinite возвращает false, все еще выдавая ошибку. Но по существу: кажется, что fzero не предполагается использовать для символов. Вы уверены, что здесь нужны символы? Глядя на вызов функции, он не кажется необходимым, поскольку вывод кажется, что он все равно должен быть числовым. Кроме того, вы можете утверждать, что

syms x; fzero(@(x) x^2-1,1) 

работает, но тогда х в @ (х) имеют более высокий приоритет, который не является символом (в программировании мы говорим, что переменная имеет различный объем).

Если важно, чтобы x был sym, вместо этого вы должны использовать решатель уравнений solve, который работает для символического вывода.

syms x; 
equation = x^2-3; 
solve(equation,'x') 

Однако это может произойти сбой или дать вам невероятно длинные ответы на сложные функции (а также для выражений, не имеющих хорошие дробных ответов попробовать syms x; equation = x^3-3.17+1.37*x;). Он также медленнее и, следовательно, не рекомендуется, если у вас нет произвольных констант в выражении (например, f = x^2-a < => x = + - a^(1/2), где a должно быть определено позже, или вы хотите что-то сделать для решения для нескольких значений a).

0

Я не знаю, что вызвало проблему, поскольку я не знаком с символическим пакетом в Matlab.

Однако вы должны быть в состоянии решить эту проблему довольно легко с помощью численного решателя. Из того, что я могу прочитать о вашем коде, вы хотите решить вышеупомянутое уравнение равным нулю, это именно то, что делает Ньютон Рапсон. Вы можете найти способ здесь: http://en.wikipedia.org/wiki/Newton 's_method

Как вы, вероятно, не знаете точную производную от вашей функции, вы можете оценить ее с помощью приближения первого порядка, где вы просто используете определение дифференциалов, но поскольку мы не можем позволить h перейдите к 0, выберем h очень маленьким, в matlab я обычно использую sqrt (eps). Таким образом, приближение становится: f '(x) = (f (x + sqrt (eps)) - f (x))/sqrt (eps).

В противном случае вы можете использовать мой метод, который работает в 1 измерение, вы можете найти его здесь: http://imada.sdu.dk/~nmatt11/MM533-2014/ Вы должны скачать fpisimple.m и mynewton.m как метод ньютона является только применением точки затруднительной итерации это сборка более того.

+0

Не работает. Показывает мне эту ошибку: 'Ошибка при помощи/subsref сима (строка 9) Ошибки с помощью maplemex Ошибки, (в MTM: -subsref) индексы должны быть положительными целыми числами, получил 229396153,846153855 Ошибки в mynewton> @ (x) xf (x)/fprime (x) (строка 8) g = @ (x) x - f (x)/fprime (x); Ошибка в fpisimple (строка 9) x = f (x); Ошибка в mynewton (строка 11) x = fpisimple (g, x0, tol); Ошибка в главном (строка 51) mynewton (уравнение, H0,100) ' –