Я хочу построить следующее:
L<-((2*pi*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T)-1))))
все переменные, кроме l, постоянны:
T<-6000
h<-6.626070040*10^-34
c<-2.99792458*10^8
k<-1.38064852*10^-23
l имеет диапазон от 20*10^-9 до 2000*10^-9.
Я пробовал l<-seq(20*10^-9,2000*10^-9,by=1*10^-9), но это не дало мне ожидаемых результатов.
Есть ли простое решение для этого в R, или мне нужно попробовать на другом языке?
Спасибо.
«однако это не дает мне ожидаемых результатов» - как вы пытались использовать это и чем оно отличается от того, что вы ожидаете? Пожалуйста, дайте минимальный воспроизводимый пример. Кроме того, использование строчной буквы «L» в качестве переменной часто считается плохим выбором, поскольку ее слишком легко спутать с числом 1.
Вам просто нужно построить график функции или вам нужен диапазон значений L в виде вектора (например, для выполнения дальнейших операций)?
С такими маленькими числами у вас будут серьезные проблемы с числовой стабильностью. Вероятно, вам нужен лучший алгоритм, а не другой язык.
Ценность моей продукции примерно в 1000 раз выше, чем ожидалось. Когда я делаю это выше, я получаю сюжет, но цифры неверны. Я проверил все остальные переменные, поэтому считаю, что, возможно, непонимание того, как работает "seq", и незнание альтернативы для присвоения диапазона чисел переменной, приводит к этой проблеме. Обновлено: мне просто нужно построить "L". Предполагается, что «L» является результатом закона Планка: «L <- ((2 * piчасc ^ 2) / l ^ 5) * ((1 / (exp ((hв) / (lk * T) -1))))» это уравнение.
Как минимум, укажите неустановленные значения констант и последовательность команд, которые вы используете для создания графика. seq вряд ли будет проблемой. Ваш l состоит из значений 1981 года: 2.0e-08, 2.1e-08, ..., 1.999e-06, 2.000e-06
T <-6000 h <-6.626070040 * 10 ^ -34 c <-2.99792458 * 10 ^ 8 k <-1.38064852 * 10 ^ -23 - мои константы, мои попытки построить "L" состоят из команды plot () при добавлении только визуальные параметры.
Причина, по которой я подозреваю, что проблема в «seq ()» заключается в том, что когда я ввожу 20 * 10 ^ -9 или 2000 * 10 ^ -9 в «L», я получаю результаты, близкие к ожидаемым.
Осмотрите l в консоли. Он состоит примерно из 2000 значений, которые равномерно распределены между указанными вами конечными точками. Я не думаю, что проблема в этом. Я думаю, что вы имеете дело с тем фактом, что точность с плавающей запятой нарушается с очень большими и очень маленькими числами. Возможно, вы могли бы изменить масштаб, изменив единицы измерения. Или, возможно, вы могли бы сначала вычислить log(L), а затем возвести в степень.
Спасибо, я учту оба ваших предложения.
Я не очень разбираюсь в физике, но ваш l кажется длинноволновым. Статья в Википедии по закону Планка имеет довольно разумные графики, когда l измеряется в микрометрах. Возможно, это будет разумный выбор единиц, а не то, что вы используете в настоящее время (метры?).
Да, «l» - это длина волны, можно использовать и нанометры, и микрометры, формула лучше всего работает при использовании основных единиц СИ (в данном случае метры ^ -9). Я полностью доволен формой получаемого графика, меня беспокоят слишком высокие значения, я ищу здесь синий график: en.wikipedia.org/wiki/Planck%27s_law#/media/File:Black_ body.svg только с более высоким максимумом. Работа с масштабом осей может помочь.





Глядя на страницу википедии уравнение спектральной яркости, кажется, что ваша формула немного неверна. Ваша формула умножает дополнительный pi (не уверен, что это задумано), и -1 находится внутри exp, а не снаружи:
L <- ((2*pi*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T)-1))))
Ниже приведена исправленная формула. Также обратите внимание, что я преобразовал его в функцию с параметром l, поскольку это переменная:
T <- 6000 # Absolute temperature
h <- 6.626070040*10^-34 # Plank's constant
c <- 2.99792458*10^8 # Speed of light in the medium
k <- 1.38064852*10^-23 # Boltzmann constant
L <- function(l){((2*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T))-1)))}
# Plotting
plot(L, xlim = c(20*10^-9,2000*10^-9),
xlab = "Wavelength (nm)",
ylab = bquote("Spectral Radiance" ~(KW*sr^-1*m^-2*nm^-1)),
main = "Plank's Law",
xaxt = "n", yaxt = "n")
xtick <- seq(20*10^-9, 2000*10^-9,by=220*10^-9)
ytick <- seq(0, 4*10^13,by=5*10^12)
axis(side=1, at=xtick, labels = (1*10^9)*seq(20*10^-9,2000*10^-9,by=220*10^-9))
axis(side=2, at=ytick, labels = (1*10^-12)*seq(0, 4*10^13,by=5*10^12))
Сюжет выше неплох, но я думаю, что с ggplot2 мы можем добиться большего:
h <- 6.626070040*10^-34 # Plank's constant
c <- 2.99792458*10^8 # Speed of light in the medium
k <- 1.38064852*10^-23 # Boltzmann constant
L2 <- function(l, T){((2*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T))-1)))} # Plank's Law
classical_L <- function(l, T){(2*c*k*T)/l^4} # Rayleigh-Jeans Law
library(ggplot2)
ggplot(data.frame(l = c(20*10^-9,2000*10^-9)), aes(l)) +
geom_rect(aes(xmin=390*10^-9, xmax=700*10^-9, ymin=0, ymax=Inf),
alpha = 0.3, fill = "lightblue") +
stat_function(fun=L2, color = "red", size = 1, args = list(T = 3000)) +
stat_function(fun=L2, color = "green", size = 1, args = list(T = 4000)) +
stat_function(fun=L2, color = "blue", size = 1, args = list(T = 5000)) +
stat_function(fun=L2, color = "purple", size = 1, args = list(T = 6000)) +
stat_function(fun=classical_L, color = "black", size = 1, args = list(T = 5000)) +
theme_bw() +
scale_x_continuous(breaks = seq(20*10^-9, 2000*10^-9,by=220*10^-9),
labels = (1*10^9)*seq(20*10^-9,2000*10^-9,by=220*10^-9),
sec.axis = dup_axis(labels = (1*10^6)*seq(20*10^-9,2000*10^-9,by=220*10^-9),
name = "Wavelength (\U003BCm)")) +
scale_y_continuous(breaks = seq(0, 4*10^13,by=5*10^12),
labels = (1*10^-12)*seq(0, 4*10^13,by=5*10^12),
limits = c(0, 3.5*10^13)) +
labs(title = "Black Body Radiation described by Plank's Law",
x = "Wavelength (nm)",
y = expression("Spectral Radiance" ~(kWsr^-1*m^-2*nm^-1)),
caption = expression(''^'\U02020' ~'Spectral Radiance described by Rayleigh-Jeans Law, which demonstrates the ultraviolet catastrophe.')) +
annotate("text",
x = c(640*10^-9, 640*10^-9, 640*10^-9, 640*10^-9,
150*10^-9, (((700-390)/2)+390)*10^-9, 1340*10^-9),
y = c(2*10^12, 5*10^12, 14*10^12, 31*10^12,
35*10^12, 35*10^12, 35*10^12),
label = c("3000 K", "4000 K", "5000 K", "6000 K",
"UV", "VISIBLE", "INFRARED"),
color = c(rep("black", 4), "purple", "blue", "red"),
alpha = c(rep(1, 4), rep(0.6, 3)),
size = 4.5) +
annotate("text", x = 1350*10^-9, y = 23*10^12,
label = deparse(bquote("Classical theory (5000 K)"^"\U02020")),
color = "black", parse = TRUE)
Заметки:
L2, также сделав абсолютную температуру T переменнойT я строю график функции L2, используя разные цвета для представления. Я также добавил функцию classical_L, чтобы продемонстрировать классическую теорию спектральной яркости.geom_rect создает светло-голубую заштрихованную область для "ВИДИМОГО" диапазона длин волн света.scale_x_continuous устанавливает разрывы оси x, а labels устанавливает метки деления оси. Обратите внимание, я умножил seq на (1*10^9), чтобы преобразовать единицы в нанометры (нм). Вторая ось X добавлена для отображения шкалы микрометра.scale_y_continuous устанавливает разрывы и метки для оси y. Здесь я умножил на (1*10^-12) или (1*10^(-3-9)), чтобы преобразовать из ватт (Вт) в киловатты (кВт) и из обратного метра (м ^ -1) в обратный нанометр (нм ^ -1).bquote правильно отображает верхние индексы в метке оси Yannotate устанавливает координаты и текст меток кривых. Я также добавил метки для длин волн света "УФ", "ВИДИМОЙ" и "ИНФРАКРАСНЫЙ".ggplot2
Сюжет из википедии:
Источник изображения: https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Black_body.svg/600px-Black_body.svg.png
Вы на самом деле не говорите, что хотите, или чем результат, который вы получаете, отличается от желаемого.