Угол солнечного зенита для многих координат с использованием PVLIB

Мне нужно рассчитать зенитный угол Солнца примерно для 106 000 000 различных координат. Эти координаты относятся к пикселям изображения, проецируемого на поверхность Земли после того, как изображение было снято камерой в самолете.

Я использую pvlib.solarposition.get_position() для расчета зенитного угла Солнца. Возвращаемые значения рассчитываются правильно (я сравнил некоторые результаты с веб-сайтом NOOA), но, как мне нужно рассчитать угол солнечного зенита для многих пар координат, питон тратит много дней (около 5 дней), чтобы завершить выполнение функции .

Как я новичок в программировании, интересно, есть ли способ ускорить расчет зенитного угла солнца.

Ниже приведена часть реализованного кода, которая вычисляет зенитный угол Солнца:

sol_apar_zen = [] 
    for i in range(size3):
        solar_position = np.array(pvl.solarposition.get_solarposition(Data_time_index, lat_long[i][0], lat_long[i][1]))
        sol_apar_zen.append(solar_position[0][0])
 print(len(sol_apar_zen))

Первый шаг, который я бы сделал, — изолировать проблему производительности между моим кодом и кодом библиотеки. Один из способов сделать это — рассчитать время, скажем, по 1000 координатам. С такими небольшими числами маловероятно, что неэффективность структур данных проявится, и это должно дать меру библиотечного кода. Если общее время, затрачиваемое на 106M координат, примерно в 10^5 раз больше, чем на 1k координат, то вполне вероятно, что код библиотеки работает долго. Если общее время значительно больше этого, сосредоточьтесь на обертывании кода.

gsr 25.07.2019 16:52

Я запускаю алгоритм для 10 000 координат. Зенитный угол Солнца для этих координат вычислялся за 1 мин 12 с. Для 100 000 координат программа потратила 12 минут и 2 секунды на вычисление зенитного угла Солнца.

César de Paula 26.07.2019 10:38

Судя по данным 10k, 106M должно занять ~8 дней. Итак, похоже, библиотека просто требует времени. Пара вариантов: найти параметры настройки, ускоряющие вычисления, или найти другую библиотеку. Кроме того, если расчеты для каждой координаты независимы, вы можете рассмотреть возможность разделения набора данных и выполнения их одновременно (как отдельные процессы) в хорошей многоядерной системе.

gsr 26.07.2019 16:09

Какова длина Data_time_index? solarposition.get_solarposition — это оболочка для нескольких различных алгоритмов определения положения солнца. Большинство реализаций предназначены для эффективного многократного вычисления положения солнца по одной координате. Похоже, вы хотите сделать обратное: эффективно вычислить положение Солнца за один (или относительно небольшой) раз по многим координатам. 10 000 раз для одной координаты на большинстве машин должно занять меньше секунды.

Will Holmgren 26.07.2019 19:43

@WillHolmgren Data_time_index содержит только одно значение, потому что оно относится к времени (времени и дате), когда камера сделала одно изображение. Я так думаю, что лучше найти другую библиотеку для расчета солнечного зенитного угла. Если вы или другой коллега знаете об одной библиотеке, дайте мне знать, пожалуйста!!

César de Paula 29.07.2019 09:55

Возможно, в модуле pvlib.spa можно использовать низкоуровневые ускоренные функции pvlib numba. Другой вариант — использовать функции pvlib.solarposition.*_analytical — большинство из них принимают массивы ndim, но мне не сразу очевидно, как заставить вычисление часового угла работать для вашего варианта использования. Пожалуйста, напишите ответ ниже, если вы найдете решение.

Will Holmgren 29.07.2019 18:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
437
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы хотите ускорить этот расчет, вы можете использовать ядро ​​numba (если оно установлено)

location.get_solarposition(
        datetimes,
        method='nrel_numba'
    )

В противном случае вам придется реализовать свой собственный расчет на основе векторизованных массивов numpy. Я знаю, что это возможно, но мне не разрешено делиться. Вы можете найти формулировку, если вы ищете spencer 1971 solar position

Ответ принят как подходящий

Поскольку ваши координаты представляют собой сетку, другим вариантом будет вычисление зенитного угла для подмножества ваших координат и выполнение двумерной интерполяции для получения остатка. 1 из 100 в обоих направлениях сократит время расчета в 10 000 раз.

Технически, если вам нужно быстро вычислить солнечный зенитный угол для большого списка (массива), существуют более эффективные алгоритмы, чем алгоритм PVLIB. Например, описанный Роберто Греной в 2012 году (https://doi.org/10.1016/j.solener.2012.01.024).

Я нашел подходящую реализацию здесь: https://github.com/david-salac/Fast-SZA-and-SAA-computation (вам нужны некоторые настройки, но ее просто использовать, плюс она также реализована для других языков, кроме Python, таких как C/C++ и Go).

Пример того, как его использовать:

from sza_saa_grena import solar_zenith_and_azimuth_angle
# ...
# A random time series:
time_array = pd.date_range("2020/1/1", periods=87_600, freq = "10T", tz = "UTC")
sza, saa = solar_zenith_and_azimuth_angle(longitude=-0.12435,  # London longitude
                                          latitude=51.48728,   # London latitude
                                          time_utc=time_array)

Тот юнит-тест (в папке проекта) показывает, что в нормальном диапазоне широт ошибка минимальна.

Другие вопросы по теме