Você está na página 1de 36

Machine Translated by Google

Capítulo 2
Computação e exibição de dados

Resumo Os arrays NumPy são os cavalos de batalha dos numéricos em Python,


estendendo-os por recursos numéricos notáveis. Por exemplo, eles podem ser usados
como variáveis simples para avaliar uma expressão aritmética para muitos valores
diferentes sem programar um loop. Na primeira seção, combinamos o poder de NumPy
e Astropy e calculamos as posições dos objetos na esfera celeste. Além disso,
introduzimos o Matplotlib para produzir gráficos a partir de dados de matriz. Outras
aplicações são mostradas no contexto das leis de Kepler e forças de maré, por exemplo,
imprimir tabelas formatadas e traçar mapas vetoriais.

2.1 Astronomia Esférica

Em astronomia, as posições das estrelas são especificadas por direções no céu, ou seja,
duas coordenadas angulares. A distância radial da estrela da Terra seria a terceira
coordenada, mas as distâncias não são conhecidas para todos os objetos astronômicos.
Desde que as distâncias não importem, todos os objetos astronômicos podem ser
projetados em direções radiais em uma esfera com a Terra no centro (o tamanho da
esfera não importa, mas você pode pensar nela como uma superfície esférica distante).
Esta é a chamada esfera celeste.1 Para um observador na Terra, a posição dos
objetos astronômicos depende da latitude e longitude geográficas e varia com a hora do
dia. Para especificar posições independentes do observador, são usadas as coordenadas
angulares em relação às direções de referência fixas. No sistema de coordenadas
equatorial, uma direção de referência é dada pelo eixo de rotação da Terra (ou,
equivalentemente, a orientação do plano equatorial). A orientação do eixo de rotação é
fixa devido à conservação do momento angular.2 A distância angular de uma estrela do
plano equatorial é chamada de declinação e denotada por ÿ. A outra direção de referência é definida pe

1Nos tempos antigos e medievais, pensava-se que havia realmente uma esfera física com as estrelas ligadas a ela e a Terra
em seu centro. Isso é conhecido como visão de mundo geocêntrica. A esfera celeste na astronomia moderna é meramente
uma construção matemática útil sem qualquer significado físico.

2Isso não é exatamente verdade, pois outros corpos no sistema solar causam perturbações, mas as mudanças são
suficientemente pequenas ao longo da vida de um ser humano.

© Springer Nature Switzerland AG 2021 W. Schmidt 19


e M. Völschow, Python Numérico em Astronomia e Astrofísica, Notas de Palestra de Graduação em
Física, https://doi.org/10.1007/978-3-030-70347-9_2
Machine Translated by Google

20 2 Computação e Exibição de Dados

Fig. 2.1 Esfera celeste n oi r th


com coordenadas ÿ (direita ce est po e
eu_ umaeu eu

ascensão) e ÿ
(declinação) de uma estrela
objeto. plano orbital da Terra
(eclíptica) cruza o
esfera ao longo do círculo vermelho,
que é inclinado pelo outonal
ângulo 0 (obliquidade) com equinócio ÿ
respeito ao celeste
equador. O celestial
equador é o exterior
projeção do equador da Terra
para a esfera celeste. o ce erua ai
eu
eu
ÿ0 eq vocêumapara
r
pontos de interseção do
vernal ÿ
eclíptica e celeste
ec pt c
eu
eueu
equinócio
equador são os dois
equinócios

so th
ce es eu você _ eu
eu uma
po e
eu

o plano equatorial e o plano do movimento orbital da Terra em torno do Sol. O fixo


A orientação do plano orbital, que é chamada de eclíptica, também é consequência da conservação
do momento angular (neste caso, o momento angular do movimento orbital).
A segunda coordenada no sistema equatorial, que é chamada de ascensão reta ÿ, é
o ângulo medido a partir de um dos dois pontos onde a esfera celeste é perfurada
pela linha de intersecção dos planos equatorial e orbital. O ponto zero para o
a ascensão reta é conhecida como equinócio vernal, o ponto oposto como equinócio de outono.
Se tudo isso soa um pouco complicado, ficará claro pela ilustração em
Fig. 2.1. Veja também [3, Seção. 2.5].

2.1.1 Declinação do Sol

Enquanto a declinação das estrelas é constante, a posição do Sol muda no


sistema equatorial no período de um ano. Isso é consequência da inclinação
do eixo de rotação da Terra em relação à direção perpendicular à eclíptica,
que é igual a 0 = 23,44ÿ. O ângulo 0 é chamado de obliquidade da eclíptica. o
variação anual da declinação do Sol é aproximadamente dada por3

360ÿ
ÿ = ÿ arcsin sen 0 cos (N + 10) (2.1)
365,24

3Veja en.wikipedia.org/wiki/Position_of_the_Sun.
Machine Translated by Google

2.1 Astronomia Esférica 21

onde N é a diferença em dias a partir de 1º de janeiro. Assim, o primeiro dia do ano corresponde
a N = 0 e o último a N = 364 (a menos que seja um ano bissexto). A fração 360ÿ/365,24 é igual
à mudança na posição angular da Terra por dia, assumindo uma órbita circular. Esta é apenas
a velocidade angular ÿ do movimento orbital da Terra em torno do Sol em unidades de graus
por dia.4 O Sol tem declinação zero nos equinócios (pontos de intersecção do equador celeste
e da eclíptica) e atinge ± 0 nos solstícios, onde a rotação eixo da Terra está inclinado para
o Sol ou para longe dele. As datas exatas variam
exemplo,
umos
pouco
equinócios
de ano foram
para ano.
em 20
Emde2020,
marçopore 22
de setembro e os solstícios em 20 de junho e 21 de dezembro (desconsideramos os horários
exatos a seguir). No Exercício 2.2 , você é solicitado a determinar os valores correspondentes
de N. Por exemplo, 20 de junho é o 172º dia do ano 2020. Contando de zero, esperamos,
portanto, o máximo da declinação ÿ = 0 (primeiro solstício) para N = 171. Vejamos se isso é
consistente com a aproximação (2.1). O código Python a seguir calcula a declinação ÿ com
base nesta fórmula para um determinado valor de N:

1 import math 2 3
N = 171 # dia do 1º
solstício 4 omega = 2*math.pi/365.24 #
velocidade angular em rad/dia 5 ecl = math.radians (23.44) # obliquidade da eclíptica
6 7 # expressão aproximada para declinação do Sol 8 delta =
-math.asin(math.sin(ecl)*math.cos(omega*(N+10))) 9 print("declinação = {:.2f}
deg".format(math. graus(delta)))

O resultado

declinação = 23,43 graus

está próximo do valor esperado de 23,44ÿ. Para implementar a Eq. (2.1), usamos as funções
seno, cosseno e arcseno da biblioteca matemática . Os argumentos dessas funções devem ser
especificados em radianos. Enquanto a velocidade angular é simplesmente dada por 2ÿ/365,24
rad/d (veja a linha 4), 0 é convertido em radianos
Ambos
com
osavalores
ajuda de
são
math.radians()
atribuídos a variáveis,
na linha 5.o
que nos permite reutilizar em partes subsequentes do programa. Como a função inversa
math.asin() retorna um ângulo em radianos, precisamos converter delta em graus ao imprimir o
resultado na linha 9 ('deg' é a abreviação de graus).

Para calcular a declinação para o segundo solstício e também para os equinócios,


precisamos avaliar o código na linha 8 para os valores correspondentes de N. Se você colocar
o código listado acima em um script Python, poderá alterar o valor atribuído ao variável N e
simplesmente execute novamente o script. Embora isso seja certamente factível para alguns
valores diferentes, seria muito tedioso para muitos valores (chegaremos a isso em breve).
Idealmente, gostaríamos de calcular a declinação do Sol para vários

4A velocidade angular em radianos por unidade de tempo aparece como fator 2ÿ/P na Eq. (1.1).
Machine Translated by Google

22 2 Computação e Exibição de Dados

dias de uma vez. Isso pode ser feito usando estruturas de dados conhecidas como arrays. Uma
matriz é uma coleção ordenada de elementos de dados do mesmo tipo. Segue como exemplo:

10 importar numpy como np 11

12 # equinócios e solstícios em 2020 13 N = np.array([79,


171, 265, 355])

Ao contrário de outras linguagens de programação, os arrays não são nativos do Python.


Eles são definidos no módulo numpy (o nome da biblioteca também é escrito como NumPy,
veja www.numpy.org), que é importado sob o alias np na linha 10. A função np.array() pega
uma lista de valores entre colchetes e, se possível, cria um array com esses valores como
elementos. Como uma matriz, uma lista também é uma coleção ordenada de elementos de
dados. Neste livro, raramente faremos uso de listas (veja, por exemplo, Seção 5.5). Eles são
mais flexíveis que os arrays NumPy, mas a flexibilidade vem com o custo da eficiência. Isso
é demonstrado com mais detalhes no Apêndice B.1. Além disso, o NumPy oferece uma
grande caixa de ferramentas de métodos numéricos que são implementados especificamente
para trabalhar com arrays.5 O array retornado por np.array() é atribuído à variável N (marque
a diferença entre valor único versus array nas linhas 3 e 13, respectivamente). Suas principais
propriedades podem ser exibidas pelas seguintes instruções de impressão:

14 imprimir(N) 15
imprimir(N.size) 16
imprimir(N.dtype)

que produz a saída

[79 171 265 355]


4
int64

A partir disso vemos que N possui quatro elementos (o número de elementos é obtido com o
atributo .size ), que são os inteiros 79, 171, 256 e 355. O tipo de dado pode ser exibido com
o atributo .dtype (por padrão , inteiros de 64 bits são usados para literais sem ponto decimal).

Como podemos trabalhar com os valores em uma matriz? Por exemplo, N[0] refere-se ao
primeiro elemento da matriz, que é o número 79. A referência a um único elemento de uma
matriz por meio de um inteiro entre colchetes, que especifica a posição do elemento na
matriz, é chamado de indexação . O primeiro elemento tem índice 0, o segundo elemento
tem índice 1 e assim por diante (lembre-se, esta é a forma de contagem do Python). Você
também pode indexar elementos do final da matriz. O último elemento tem índice ÿ1, o
elemento antes do último tem índice ÿ2, etc. Então, para o array definido acima,
17 imprimir(N[1]) 18
imprimir(N[-3])

5Veja também [1] para uma introdução abrangente aos arrays.


Machine Translated by Google

2.1 Astronomia Esférica 23

saídas

171
171

Você vê por que o valor 171 é impresso em ambos os casos? Varie os índices e veja por si
mesmo o que você obtém. Antes de prosseguir, vamos resumir as propriedades definidoras de
um array:

Cada elemento de uma matriz deve ter o mesmo tipo de dados. Cada elemento é
identificado por seu índice.

Tendo definido N como uma matriz, poderíamos calcular a declinação do Sol no dia 171 (o
primeiro solstício) copiando o código da linha 8 e substituindo N por N[1] na expressão para
delta. Claro, isso não nos levaria mais perto de calcular a declinação do Sol para todos os quatro
dias de uma só vez. Com NumPy, isso pode ser feito da seguinte maneira.

19 delta = -np.arcsin(math.sin(ecl) * np.cos(omega*(N+10))) 20 print(np.degrees(delta))

Resumindo, a expressão na linha 19 é avaliada para cada elemento do array N e os resultados


são armazenados em um novo array que é atribuído a delta. Os quatro elementos do delta são
os valores da declinação para os dois equinócios e solstícios:

[-0,9055077 23,43035419 -0,41950731 -23,43978827]

Não é perfeito (a declinação nos equinócios deve ser zero), mas razoavelmente próxima. Afinal,
usamos apenas uma fórmula aproximada.
Para ter uma ideia melhor de como o código na linha 19 funciona, nós o expandimos em
várias etapas e usamos um array temporário chamado tmp para resultados intermediários do cálculo:

21 # adiciona 10 a cada elemento de N 22 tmp =


N+10 23 print(tmp) 24 print(tmp.dtype) 25 26 #
multipy by omega 27 tmp = omega*tmp 28
print(tmp) 29 print(tmp.dtype ) 30 31 # calcula o
cosseno de cada elemento no array resultante
32 # e multipy com o seno da obliquidade 33 tmp
= math.sin(ecl)*np.cos(tmp)
Machine Translated by Google

24 2 Computação e Exibição de Dados

34 imprimir(tmp) 35

36 # calcula o arco seno negativo de cada elemento 37 delta = -np.arcsin(tmp)


38 print(np.degrees(delta))

Como você pode ver, é possível realizar operações aritméticas em arrays. Para operadores
como + e *, os operandos devem ser (veja também a Fig. 2.2)

• uma matriz e um único número, • ou


duas matrizes de formato idêntico (para matrizes com apenas um índice, isso equivale a
o mesmo número de elementos).

Por exemplo, usamos a primeira opção na linha 22, onde o número 10 é adicionado a cada
elemento do array N. Os inteiros resultantes são atribuídos elemento a elemento ao array
tmp:

[89 181 275 365]


int64

O próximo passo é uma multiplicação elementar com ômega (velocidade angular da Terra
definida na linha 4). Como o valor de omega é um número de ponto flutuante, o array tmp é
convertido automaticamente do tipo de dados integer para float:

[1,53105764 3,11372396 4,73079608 6,27905661]


float64

Agora temos as posições angulares da Terra em sua órbita, a partir das quais as distâncias
verticais do Sol ao equador celeste podem ser calculadas. Na linha 33, a função NumPy
np.cos() é usada para calcular o cosseno de cada valor no array tmp , enquanto math.sin()
pode receber apenas um argumento de valor único, que é ecl (a obliquidade da eclíptica ).
O produto é

[ 0,01580343 -0,39763404 0,00732172 0,39778512]

e, depois de calcular o arco-seno de cada elemento com np.arcsin, finalmente obtemos as


declinações:

[-0,9055077 23,43035419 -0,41950731 -23,43978827]

Embora fazer as coisas passo a passo seja útil para iniciantes, combinar todas essas
etapas em uma única instrução mostrada na linha 19 é extremamente útil para o
programador mais experiente. Começando com o código para um único dia (veja a linha 8),
a única modificação que deve ser feita é que o módulo math deve ser substituído por numpy
sempre que o argumento de uma função for um array. No entanto, há uma pequena
armadilha. Ao comparar os exemplos de código cuidadosamente, você pode notar que os
identificadores para a função arcsine lêem math.asin() e np.arcsin() nas linhas 8 e 19, respectivamente.
Machine Translated by Google

2.1 Astronomia Esférica 25

variedade
=+ =+variedade número variedade variedade variedade

ab = + ab = +

a[0] = b[0] + c a[0] = b[0] + c[0]


a[1] = b[1] + c a[1] = b[1] + c[1]
a[2] = b[2] + c a[2] = b[2] + c[2]

... ... ... ... ...

a[n-1] = b[n-1] + c a[n-1] = b[n-1] + c[n-1]

Fig. 2.2 Ilustração das operações básicas do NumPy. Adicionar um número (variável) a um array significa que o
mesmo número é adicionado a cada elemento do array (esquerda). Se duas matrizes de tamanho n forem
adicionadas, o operador + será aplicado elemento a elemento (direita)

Um erro provável é substituir math.asin() por np.asin(), o que faria com que o Python lançasse a
seguinte mensagem de erro:

AttributeError: módulo 'numpy' não tem atributo 'asin'

Como math e numpy são módulos independentes, você não pode esperar que a nomenclatura das
funções matemáticas seja sempre consistente.
A impressão de uma matriz resulta na exibição de todos os elementos da matriz em algum formato
padrão. Agora, suponha que queremos formatar bem os elementos como fizemos no início desta seção
antes de introduzir os arrays. É claro que a impressão formatada de um elemento específico de uma
matriz é possível pela indexação do elemento. Por exemplo,

39 print("declinação = {:.2f} graus". format(math.degrees(delta[1]))))


40

produz a mesma saída que a linha 9 (onde delta é uma variável simples):

declinação = 23,43 graus

Para exibir todos os elementos em uma tabela formatada, precisamos percorrer o array.
Na verdade, já trabalhamos com esses loops, por exemplo, na linha 19. Loops desse tipo são chamados
de implícitos. O exemplo a seguir mostra um loop for explícito:

41 para val em delta:


42 print("declinação = {:6.2f} graus". format(math.degrees(val)))
43

O loop começa com o primeiro elemento no array delta, atribui seu valor à variável val, que é a variável
do loop (semelhante ao contador de loop introduzido na Seção 1.3), e então executa o corpo do loop.
O loop no exemplo acima encom passa apenas uma única instrução de impressão. Após executar esta
instrução, o loop continua com o próximo elemento e assim sucessivamente até que o final do array (o
índice mais alto) seja alcançado:
Machine Translated by Google

26 2 Computação e Exibição de Dados

declinação = -0,91 graus


declinação = 23,43 graus
declinação = -0,42 graus declinação =
-23,44 graus

No entanto, a saída ainda não é realmente satisfatória. Embora imprimir repetidamente a


declinação seja redundante, faltam informações importantes para a compreensão dos dados.
Em particular, os dias a que esses valores se referem não são especificados. Uma maneira
melhor de imprimir dados relacionados em arrays é, obviamente, uma tabela. Para imprimir os
dias e as declinações correspondentes, precisamos iterar simultaneamente pelos elementos de
N e delta. Uma solução é definir um contador com a ajuda da função enumerate() do Python :

44 print("i day delta [deg]") 45 for i,val in


enumerate(delta):
46 print("{1:d} {2:3d} {0:8.2f}".\
47 format(matemática.graus(val),i,N[i]))

Comparado com os laços for discutidos na Seção. 1.3, o intervalo do contador i é implicitamente
dado pelo tamanho de um array: ele conta todos os elementos de delta e, ao mesmo tempo,
nos permite referenciar os elementos de N sequencialmente no corpo do laço. A execução do
loop produz a seguinte tabela:

i dia delta [graus]


0 79 -0,91
1 171 23.43
2 265 -0,42
3 355 -23,44

Aqui, os argumentos de format() são explicitamente ordenados. O espaço reservado {1:d} na


linha 46 indica que o segundo argumento (índice 1 antes dos dois pontos) deve ser inserido
como inteiro nesta posição. O próximo espaço reservado se refere ao terceiro argumento
(índice 2 antes dos dois pontos) e o último ao primeiro argumento. Os especificadores de
formato garantem espaço suficiente entre as colunas de números (experimente com as
configurações). O cabeçalho com rótulos para as diferentes colunas é impresso na linha 44
(obviamente, isso deve ser feito apenas uma vez antes do início do loop).
Certamente, em vez de enumerar delta, você poderia enumerar N. É possível escrever um
loop que itere simultaneamente ambos os arrays sem usar um contador explícito? Na verdade,
esse é o propósito da função zip() , que agrega elementos com o mesmo índice de dois ou mais
arrays de igual tamanho.
Nesse caso, a variável de loop é uma tupla contendo um elemento de cada array.
Vamos dar uma olhada nas tuplas abaixo. Tudo o que você precisa saber no momento é que a
linha da tupla no exemplo de código a seguir contém um elemento de N e o elemento
correspondente de delta, formando uma linha da tabela que queremos imprimir.
Elementos de tupla são indexados como elementos de array, então row[0] se refere ao dia e
row[1] à declinação daquele dia.
Machine Translated by Google

2.1 Astronomia Esférica 27

48 print("day delta [deg]") 49 for row in


zip(N,delta): print("{0:3d} {1:8.2f}".
50 format(row[0],math.degrees(row [1])))
51

Além da coluna de índice, obtemos a mesma saída acima:

delta do dia [graus]


79 -0,91
171 23.43
265 -0,42
355 -23,44

Se você substituir as linhas 50–51 pela instrução print não formatada print(row), você
obterá:

(79, -0,01580409076383853)
(171, 0,40893682550286947)
(265, -0,007321783769611206)
(355, -0,4091014813515704)

Enquanto os colchetes são usados para listas e arrays, as tuplas são colocadas entre parênteses.
A diferença mais importante é que as tuplas são imutáveis, ou seja, não é possível
adicionar, alterar ou remover elementos. Por exemplo, as tuplas mostradas acima são
pares fixos de números, semelhantes às coordenadas (x, y) para pontos em um plano.
Suponha que você queira alterar o dia 355 para 364. Embora seja possível modificar o
array N definindo N[3] = 364, você não tem permissão para atribuir um valor a um elemento
individual em uma tupla, como linha[0]. Você só pode substituir a tupla inteira por uma
nova (isso é o que acontece no loop acima).

2.1.2 Arco Diurno

Do ponto de vista de um observador na Terra, o movimento aparente de um objeto na


esfera celeste segue um arco acima do horizonte, que é chamado de arco diurno (ver Fig.
2.3). A posição horizontal dependente do tempo do objeto é medida pelo seu ângulo
horário h. Um ângulo horário de 24h corresponde a um círculo completo de 360ÿ paralelo
ao equador celeste (um exemplo é o círculo vermelho completo na Fig. 2.3). Por esta
razão, h pode ser expresso de forma equivalente em graus ou radianos. No entanto, como
veremos abaixo, um ângulo horário de 1h não equivale a uma diferença horária de uma
hora solar. Por definição, o ângulo horário é zero quando o objeto atinge a maior altitude
acima do horizonte (veja também Exercício 2.4 e Seção 2.1.3). O ângulo horário
correspondente ao tempo de ajuste, quando o objeto simplesmente desaparece abaixo do horizonte, é da

6 Veja [3, Seção. 2.6] se você estiver interessado em saber como essa equação ocorre.
Machine Translated by Google

28 2 Computação e Exibição de Dados

ÿ
e
eu
h po
n
m
ÿ E r r
subir
n
N S

hset
C

h
s
es
eu
ce

Fig. 2.3 Arco diurno de uma estrela se movendo ao redor da esfera celeste (círculo vermelho espesso) na horizontal
sistema (ver Seção 2.1.3) de um observador na latitude ÿ (o plano horizontal é mostrado em cinza). Desde o
plano equatorial é inclinado pelo ângulo 90ÿ ÿ ÿ contra o plano horizontal, o ponto culminante superior
da estrela no meridiano é dado por amax = 90ÿ ÿ ÿ + ÿ, onde ÿ é a declinação. No sistema de co-rotação, a
estrela sobe no ângulo horário, atinge sua altitude mais alta quando cruza o
meridiano em h = 0, e se põe no horizonte em hset = ÿhrise

cos hset = ÿ tan ÿ tan ÿ , (2.2)

onde ÿ é a declinação do objeto (ver Seção 2.1) e ÿ a latitude do


posição do observador na Terra. Como consequência, a variável T = 2hset mede a
o chamado tempo sideral para o qual o objeto é, em princípio, visível no céu (estrelas
são naturalmente ofuscadas pelo Sol durante o dia). Também é conhecido como comprimento do
arco diurno.
Por exemplo, consideremos a estrela Betelgeuse na constelação de Orion.
É uma gigante vermelha que está entre as estrelas mais brilhantes do céu. Sua declinação pode ser
facilmente encontrado com a ajuda de astropy.coordinates, que oferece uma função
que pesquisa o nome de um objeto em bancos de dados online:

1 de astropy.coordinates importam SkyCoord, EarthLocation


2
3 betelgeuse = SkyCoord.from_name('Betelgeuse')
4 impressão (betelgeuse)

Quando você é confrontado com a saída pela primeira vez, pode ser necessário um pouco de
pouco de decifração:

<SkyCoord (ICRS): (ra, dez) em graus


(88.79293899, 7.407064)>
Machine Translated by Google

2.1 Astronomia Esférica 29

Isso nos diz que a ascensão reta (ra) e a declinação (dec) do objeto chamado Betelgeuse
foram 88,79ÿ e 7,41ÿ, respectivamente.7 A variável betelgeuse definida na linha 3
representa não apenas um objeto astronômico; é um objeto Python, mais especificamente
um objeto pertencente à classe SkyCoord (veja a Seção 1.4 para objetos em poucas
palavras). O atributo dec nos permite referenciar diretamente a declinação:

5 delta = betelgeuse.dec 6 print(delta)

A declinação é convenientemente impressa em graus (d), minutos de arco (m) e segundos


de arco (s), que é o formato preferido para expressar coordenadas angulares em astronomia:

7d24m25.4304s

ou seja, ÿ ÿ +07ÿ 24 25 , onde 1 = (1/60)ÿ e 1 = (1/60) .


Suponha que queremos determinar o comprimento do arco diurno de Betelgeuse visto
do Observatório de Hamburgo (ÿ ÿ +53ÿ 28 49 ). Além da declinação da estrela,
precisamos da posição do observador. A contrapartida do SkyCoord para as coordenadas
celestes é EarthLocation (também importado na linha 1), que permite definir a latitude e
longitude geográficas de um local na Terra:
7 import astropy.units como u 8 9 #
posição geográfica do observador 10 obs
= EarthLocation(lat=53*u.deg+28*u.arcmin+49*u.arcsec, 11
lon=10*u.deg+14 *u.arcmin+23*u.arcsec)

12
13 # obtém latitude 14 phi
= obs.lat

Nas expressões acima,u.degis equivalente a 1ÿ,u.arcminis 1 é 1 O , andu.arcsec


módulo de unidades
. cálculos da astropy
em sistemas implementa
de unidades regras
físicas para realizar Você aprenderá mais
e astronômicas.
sobre as unidades AstroPy em Sec. 3.1.1.

Em seguida, calculamos h com a ajuda de funções trigonométricas do módulo de


matemática :

15 importar matemática
16
17 h = math.acos(-math.tan(delta.radian) * math.tan(phi.radian))

É necessário converter os ângulos ÿ e ÿ para radianos antes de aplicar a função tangente


math.tan(). Com as coordenadas de Astropy, tudo o que precisamos fazer é usar o
atributo radiano de um ângulo.8 Para obter T em horas, é importante ter em mente

7ICRS significa Sistema Internacional de Referência Celestial.


8Você também pode trabalhar com o objeto SkyCoord definido na linha 3 e usar betelgeuse.dec.radian como
argumento de math.tan(). betelgeuse.dec é um objeto Angle . Portanto, há objetos dentro de objetos. No
entanto, a função math.radians() para converter de graus para radianos não é compatível com objetos Angle .
Machine Translated by Google

30 2 Computação e Exibição de Dados

que um ângulo de 360ÿ (uma rotação completa da Terra) corresponde a um dia sideral,
que é cerca de 4 minutos mais curto que um dia solar. Conforme explicado em [3, Sec.
2.13], isso é uma consequência do movimento orbital da Terra. A conversão é facilitada
pelo módulo de unidades (veja também o Exercício 2.5 para o cálculo de um pobre):

18 T = (math.degrees(2*h)/360)*u.sday 19 print("T =
{:.2f}".format(T.to(uh))))

O primeiro T é definido em dias siderais (u.sday), o que equivale a 24h ou 360ÿ.


Então convertemos para horas solares (uh) aplicando o método to() na linha 19. O resultado
é

T = 13,31h

Se não fosse o Sol, Betelgeuse poderia ser vista 13 h no Observatório. Obviamente, a


estrela será visível apenas durante a sobreposição entre esse período e a noite, o que
depende da data. Voltaremos a essa questão na seção seguinte.
O arco diurno do Sol desempenha um papel central em nossa vida diária, pois determina
o período da luz do dia. Na Sec. 2.1.1, introduzimos uma aproximação para a declinação ÿ
do Sol. Substituindo a expressão (2.1) por ÿ na Eq. (2.2), podemos calcular como a duração
do dia varia ao longo do ano. Primeiro precisamos calcular ÿ para N variando de 0 a 364.
Usando NumPy, isso é muito fácil. No exemplo a seguir, a expressão np.arange(365)
preenche um array com a sequência de inteiros começando de 0 até o maior número menor
que 365, que é 364.9 Além disso, o código funciona de forma análoga à computação
baseada em NumPy para equinócios e solstícios em Sect. 2.1.1. Como uma nova tarefa
começa aqui, a numeração da linha é redefinida para 1, embora façamos uso de atribuições
anteriores (um exemplo é a latitude phi). Em outras palavras, você precisaria adicionar
partes de cima para fazer o código a seguir funcionar como um programa autônomo (você
pode tentar isso).
1 importação numpy como
np 2
3 N = np.arange(365) # array com elementos 0,1,2,...,364 4 omega = 2*math.pi/
365.24 # velocidade angular da Terra em rad/dia 5 ecl = math.radians (23.44 ) # obliquidade da
eclíptica 6 7 # calcula a declinação do Sol para todos os dias do ano 8 delta =
-np.arcsin(math.sin(ecl) * np.cos(omega*(N+10)))

Agora podemos calcular a duração do dia T para todos os valores no array delta usando
funções do módulo numpy (compare com o exemplo de código para Betelgeuse e verifique
quais alterações foram feitas):

9Assim como range() em loops for , a forma geral é np.arange(start, stop, step), onde um valor
inicial diferente de 0 e um step diferente de 1 podem ser especificados como argumentos opcionais.
Machine Translated by Google

2.1 Astronomia Esférica 31

9 # calcular a duração do dia em horas solares 10 h = np.arccos(-


np.tan(delta) * math.tan(phi.radian))
11 T = (np.graus(2*h)/360) * u.sday.to(uh)

Aqui, phi ainda é a latitude do Observatório de Hamburgo definida acima. Claro, T


agora é uma matriz com 365 elementos. Como queremos a duração do dia em horas
solares, multiplicamos imediatamente por u.sday.to(uh), que é a duração de um dia
sideral em horas solares.
Ao lidar com grandes conjuntos de dados (ou seja, mais do que alguns valores), na
maioria das vezes é preferível extrair algumas estatísticas ou exibir os dados em forma
gráfica. Para mostrar a variação anual da duração do dia, produzir um gráfico de T
versus N é a coisa óbvia a fazer. A biblioteca Python matplotlib (veja matplotlib.org)
fornece um módulo chamado pyplot para plotar dados em arrays:
12 importar matplotlib.pyplot como plt 13 %matplotlib
inline
14
15 plt.plot(N, T) 16
plt.xlabel("Day") 17 plt.ylabel("
Duração do dia [hr]") 18 plt.savefig("day_length.pdf")

A função plt.plot(), onde plt é um alias comumente usado para matplotlib.pyplot, produz
um gráfico mostrando os pontos de dados (x, y) fornecidos pelas matrizes N ( eixo x) e T
(eixo y ). Por padrão, os pontos são unidos por linhas para produzir um gráfico contínuo.
Os rótulos dos eixos são adicionados nas linhas 16 e 17. A plotagem é então salva em
um arquivo chamado day_length.pdf em formato PDF. A localização do arquivo depende
do diretório no qual você iniciou sua sessão do Python. Você pode especificar o caminho
completo se quiser armazenar o gráfico em outro lugar). Você também pode usar outros
formatos gráficos, como PNG ou JPG, especificando a extensão correspondente no
nome do arquivo (por exemplo, day_length.png).10 Na linha 13, você pode ver um
chamado comando mágico (indicado por % no início da linha). Ele permite a visualização
em linha de gráficos em notebooks IPython e Jupyter.11 O gráfico pode ser visto como
uma linha sólida na Fig. 2.4 (a linha pontilhada será adicionada abaixo). Como
esperado, a duração do dia é curta em janeiro, atinge um máximo no primeiro solstício (N
= 171) e depois diminui até o segundo solstício ser alcançado em N = 355. A duração
mínima e máxima do dia pode ser inferida com a ajuda de métodos min() e max() para
arrays NumPy12:
19 print("Duração mínima do dia = {:5.2f} h".format(T.min())) 20 print("Duração máxima do dia
= {:5.2f} h".format(T.max()))

O 10PDF tem a vantagem de conter o gráfico como um gráfico vetorial: o número de pixels não é fixo e,
como resultado, as linhas e fontes aparecem suaves mesmo quando visualizadas em resolução gráfica mais alta.
11Dependendo do seu ambiente Python, pode ser necessário adicionar a linha plt.show() em
o fundo.

12Funções como np.arange() ou np.tan() são chamadas com um array como argumento, enquanto min() e
max() são métodos chamados em um objeto específico (aqui, o array T).
Machine Translated by Google

32 2 Computação e Exibição de Dados

Fig. 2.4 Variação anual da duração do dia em Hamburgo seguindo uma Eq. aproximada. (2.1) para a
declinação do Sol

Nós temos

Duração mínima do dia = 7,20 h Duração


máxima do dia = 16,73 h

A diferença entre a duração mínima e máxima do dia aumenta com a latitude.


Além dos círculos polares (ÿ = ±66ÿ 33 ), a duração do dia varia entre 0 e 24 h.
Um exemplo é Longyearbyen localizado em ÿ = +78ÿ 13 na ilha norueguesa Spitsbergen
no extremo norte. Como só precisamos saber ÿ dentro de um minuto de arco (a precisão é
limitada pela declinação aproximada de qualquer maneira), uma especificação completa da
posição geográfica usando EarthLocation seria um exagero. Em vez disso, simplesmente
usamos 1 = (1/60)ÿ e convertemos imediatamente em radianos:

21 phi = math.radians(78+13/60) # latitude de Longyearbyen 22

23 h = np.arccos(-np.tan(delta)*math.tan(phi))
24 T = (np.graus(2*h)/360) * u.sday.to(uh)

Ao executar este código, você obterá um

RuntimeWarning: valor inválido encontrado em arccos

Acontece que o Python é capaz de lidar com isso, mas devemos tentar entender o que
está errado aqui. Lembre-se que o alcance da declinação do Sol é ÿ 0 ÿ ÿ ÿ 0. Considerando
a Eq. (2.2), você pode se convencer de que o lado direito se torna menor que ÿ1 ou maior
que 1 se |ÿ| ÿ 90ÿ ÿ 0, ou seja, se a localização for nas regiões polares. Neste caso, a (2.2)
Eq.
não tem solução porque
Machine Translated by Google

2.1 Astronomia Esférica 33

o arcoseno é indefinido se o valor absoluto de seu argumento for maior que a unidade.
Isso corresponde à noite polar ou dia polar durante o qual o Sol nunca nasce ou se põe.
Isso pode ser corrigido definindo cos hset igual a ±1 sempre que o lado direito da Eq. (2.2)
está fora do intervalo [ÿ1, 1]. Usando Numpy, isso é facilmente alcançado por meio da
função np.clip() :

24 tmp = np.clip(-np.tan(delta)*math.tan(phi), -1,0, 1,0) 25 h = np.arccos(tmp)

26 T = (np.graus(2*h)/360) * u.sday.to(uh)

Atribuindo o lado direito recortado da Eq. (2.2) para uma matriz temporária destina-se apenas
a destacar esta etapa. Deixamos como um pequeno exercício para você combinar as linhas 24
e 25 em uma única linha de código e produzir e visualizar o gráfico resultante para a duração
do dia. Como esperado, você descobrirá que as pessoas em Longyearbyen têm que lidar com
uma noite polar (o dia todo escuro) durante o inverno e um dia polar com duração de 24 horas em
verão.

Tendo calculado a duração do dia para Hamburgo e Longyearbyen, seria instrutivo


comparar os gráficos em um único gráfico. Obviamente, precisamos dos dados para
ambos os locais ao mesmo tempo, mas no exemplo acima os dados de Hamburgo foram
substituídos pela computação de Longyearbyen. Uma maneira direta de resolver esse
problema seria usar um array com nome diferente, mas em Python existe uma alternativa
mais elegante e conveniente. Além dos arrays nos quais os itens são referenciados pelo
índice, os dados podem ser coletados em um dicionário Python. Semelhante a um
dicionário no sentido convencional, os itens de dados em um dicionário são referenciados
por palavras-chave em vez de um índice numérico. Os itens de dados do dicionário
podem ser qualquer coisa, incluindo arrays. Vamos montar um dicionário associando
locais com suas latitudes:

27 phi = { 'Hamburgo' : obs.lat.radian,


28 'Longyearbyen' : math.radians(78 + 13/60) }

Em Python, um dicionário é definido por pares de palavras-chave e itens entre chaves.


Cada palavra-chave, que deve ser uma string (por exemplo , 'Hamburg'), é separada por
dois pontos do item correspondente (a expressão obs.lat.radian no caso de Hamburgo)
seguida por uma vírgula. Como os itens individuais são acessados? Por exemplo,

29 print(phi['Hamburgo'])

imprime a latitude de Hamburgo em radianos. A sintaxe é semelhante ao acesso a


elementos de matriz, exceto pela palavra-chave em vez de um índice. Adicionar novos
itens a um dicionário é muito fácil. Por exemplo, as seguintes atribuições adicionam Nova
York e Bangkok ao nosso dicionário:

30 phi['New York'] = math.radians(40 + 43/60) 31 phi['Bangkok'] =


math.radians(13 + 45/60)

De fato, o dicionário agora tem quatro itens, que podem ser verificados imprimindo len(phi).
Machine Translated by Google

34 2 Computação e Exibição de Dados

O código a seguir imprime todos os itens, calcula a duração do dia para cada local,
e os combina em um único gráfico:
32 para chave em phi: 33
print(chave + ": {:.2f} grau".format(math.degrees(phi[chave]))))
34
35 h = np.arccos(np.clip(-np.tan(delta)*math.tan(phi[chave]),
36 -1,0, 1,0))
37 T = (np.graus(2*h)/360) * u.sday.to(uh)
38
39 plt.plot(N, T, rótulo=chave)
40
41 plt.xlabel("Dia") 42 plt.xlim(0,364)
43 plt.ylabel(" Duração do dia [hr]")
44 plt.ylim(0,24) 45 plt.legend(loc='canto superior direito
') 46 plt.savefig("daylength.pdf")

A saída gráfica para os lugares

Hamburgo: 53,48 graus


Longyearbyen: 78,22 graus Nova
York: 40,72 graus Bangkok: 13,75
graus

pode ser visto na Fig. 2.5. Como esperado, a duração do dia em Longyearbyen varia entre
0 e 24 h, enquanto as pessoas em Bangkok, que fica nos trópicos, experimentam uma
duração do dia em torno de 12 h durante todo o ano. A duração do dia nas zonas
temperadas aumenta várias horas do inverno ao verão.

Fig. 2.5 Variação anual da duração do dia em diferentes lugares do mundo


Machine Translated by Google

2.1 Astronomia Esférica 35

Para entender como essa saída é produzida, vamos percorrer o código passo a passo:

1. O código começa com um loop for iterando o dicionário phi. À primeira vista, isso se parece
exatamente com um loop através de uma matriz (consulte a Seção 2.1.1). No entanto, há
uma diferença importante. Ao iterar uma matriz, a variável de loop percorre os elementos da
matriz. Em contraste, a variável de loop key passa por palavras-chave, não pelos próprios
itens do dicionário. Como a palavra-chave é o análogo do índice, esse loop se assemelha
mais a uma enumeração. Os itens são referenciados por phi[key] no corpo do loop.

2. Na linha 33, o operador + concatena duas strings. A primeira string é uma palavra-chave, ou
seja, o nome de um local, a segunda string é uma latitude formatada.
3. As linhas 35 a 37 correspondem às linhas 24–26 com a notável diferença que
phi[chave] em vez de phi refere-se a uma latitude específica.
4. A última instrução no corpo do loop (linha 39) adiciona ao gráfico o gráfico da matriz T atual,
que muda a cada iteração. Isso significa que plt.plot() chamado dentro de um loop não
produz vários gráficos, mas acumula gráficos em um único gráfico. O argumento opcional
label=key define o rótulo do gráfico para a palavra-chave. Os rótulos são usados na legenda
do gráfico (veja abaixo).
5. Uma vez terminado o loop, o gráfico é configurado pelas instruções nas linhas 41–45: Os
eixos são rotulados, seu alcance é limitado por plt.xlim() e plt.ylim(), e os rótulos para os
diferentes gráficos são mostrados em uma legenda no canto superior direito do gráfico.

6. Finalmente, o gráfico é salvo em um arquivo PDF. Isto irá sobrescrever o salvo anteriormente
arquivo, a menos que você escolha um nome de arquivo diferente.

Se você não tiver certeza sobre qualquer uma das etapas explicadas acima, faça alterações no
código e veja por si mesmo o que acontece e se ele atende às suas expectativas.

2.1.3 Observação de objetos celestes

Embora seja importante poder especificar as posições dos objetos celestes em um sistema de
coordenadas independente do tempo e da localização do observador, no final do dia você quer
saber onde no céu você pode encontrar o objeto. Para tanto, utiliza-se o chamado sistema de
coordenadas horizontal, que se baseia em um plano imaginário que é orientado tangencialmente
à superfície da Terra no local do observador. A posição angular medida na direção normal do
horizonte é a altitude a, e a separação angular de alguma direção de referência (geralmente, a
direção Norte) paralela ao horizonte é o azimute do objeto.13 É por isso que o sistema horizontal
também vai sob o nome de sistema alt-azimute. O módulo astropy.coordinates oferece uma
estrutura poderosa para trabalhar com

13O azimute medido a partir do Norte corresponde à direção da bússola.


Machine Translated by Google

36 2 Computação e Exibição de Dados

coordenadas (para obter mais informações, consulte docs.astropy.org/en/stable/


coordinates). Semelhante ao SkyCoord para coordenadas no sistema equatorial, o sistema
alt-azimute é representado pela classe AltAz. Nesta seção, utilizaremos AltAz para inferir
o tempo de observabilidade da estrela Betelgeuse. Ao fazê-lo, abordaremos alguns
aspectos avançados do Python. Se você achar muito complicado neste ponto, você pode
pular esta seção e retornar mais tarde, se quiser.
Para começar, definimos mais uma vez a posição do observador (veja também
Seita 2.1.2). Você está convidado a ajustar todas as configurações para sua própria localização e hora.

1 importe astropy.units como u 2 de


astropy.coordinates import \ 3 SkyCoord,
EarthLocation, AltAz, get_sun

4 5 # posição geográfica do observador 6 obs =


EarthLocation(lat=53*u.deg+28*u.arcmin+49*u.arcsec, 7 lon=10*u.deg+14*u.arcmin+23*
u.arcsec) 8

9 # obtém latitude 10 phi


= obs.lat

O Astropy também possui um módulo para definir o horário em diferentes formatos.14 Por
padrão, Time() define o horário universal coordenado (UTC).15 Para definir, por exemplo, meio-
dia no fuso horário CEST (duas horas à frente do UTC) em julho 31, 2020, mudamos a hora por
um deslocamento de duas horas:

11 da hora de importação astropy.time


12
13 utc_shift = 2*u.hora # fuso horário CEST (+2h)
14
15 noon_cest = Time("2020-07-31 12:00:00") - utc_shift

A impressão noon_cest mostra a hora UTC correspondente às 12h CEST. A mudança


para UTC é necessária porque AltAz espera a hora UTC.
Com tempo e localização, podemos definir nosso sistema de coordenadas horizontal.
Queremos seguir a posição da estrela durante um período completo de 24 horas e determinar a
janela de tempo para observação durante a noite. Como a altitude e o azimute são dependentes
do tempo, precisamos criar uma sequência de quadros cobrindo um dia inteiro (quadro é sinônimo
de sistema de coordenadas):

16 importar numpy como np 17

18 # matriz de tempo cobrindo as próximas 24 horas em etapas de 5 min 19 decorrido =


np.arange(0, 24*60, 5)*u.min 20 tempo = noon_cest + decorrido

21

14Veja docs.astropy.org/en/stable/time.
15A hora universal coordenada (UTC) é um padrão internacional de hora. Está próximo (dentro de um
segundo) do tempo universal relacionado à rotação da Terra em relação a objetos celestes distantes.
Machine Translated by Google

2.1 Astronomia Esférica 37

22 # sequência de frames horizontais 23 frame_local_24h


= AltAz(obstime=time, location=obs)

Nas linhas 19 a 20, é criada uma sequência de tempo, a partir do meio-dia (CEST) em etapas
de cinco minutos cobrindo um intervalo de 24 h. Vejamos isso com mais detalhes. Primeiro
np.arange() cria um array de números (0, 5, 10,...). Ligando

type(np.arange(0, 24*60, 5))

nos informa que o tipo do objeto retornado por np.arange() é

numpy.ndarray

Qual é o tipo de um objeto? É apenas a classe à qual o objeto pertence.


Não confunda isso com o tipo de dados do array (ou seja, o tipo de seus elementos; veja
Seção 2.1.1). Como veremos, o array NumPy criado inicialmente sofre uma grande
metamorfose. Para definir o tempo decorrido desde o meio-dia em minutos, a matriz é
multiplicada por u.min. Enquanto a multiplicação com um número não afeta o tipo,

tipo (decorrido)

retorna

astropy.units.quantity.Quantity

Conforme mencionado no Sec. 1.4, quantidades com unidades são instâncias da classe
Quantity , que é definida no submódulo astropy.units.quantity. Por outro lado, quando a
impressão terminar , você provavelmente concluirá que ela se parece muito com um array.
Podemos confirmar isso? A função isinstance() informa se algo pertence a uma determinada
classe (é isso que significa instância). Enquanto um objeto é, obviamente, uma instância da
classe que define seu tipo,16 ele também pode pertencer a outras classes. De fato,

isinstance(decorrido, np.ndarray)

produz True, ou seja, decorrido é um array de tipos. Astropy suporta arrays com unidades, que
são uma subclasse de arrays NumPy. Uma subclasse pode estender atributos e métodos de
uma classe base existente, aqui numpy.ndarray. Isso é conhecido como herança.
Agora você pode adivinhar que o tempo também é uma matriz, criada pela adição de um valor fixo
aos elementos de decorridos (ver linha 20). Mas não,

isinstance(tempo, np.ndarray)

retorna

16Você pode verificar isso com isinstance(elapsed, u.quantity.Quantity). É importante referenciar


corretamente a classe em seu namespace. Como importamos astropy.units usando o alias u, precisamos
usar o nome u.quantity.Quantity. No entanto, a função type() sempre retorna a classe no namespace do
módulo genérico.
Machine Translated by Google

38 2 Computação e Exibição de Dados

Falso

Sem entrar em muitos detalhes, o tempo tem alguns recursos semelhantes a matrizes, mas
não é derivado do NumPy. E tem uma forma própria de tratar as unidades (basicamente,
substitui a noção de unidades por formatos de tempo). Em geral, ele não pode ser usado no
lugar de uma matriz, como decorrido. A razão pela qual precisamos é criar quadros por meio
de AltAz() (veja a linha 23).
Após este pequeno desvio para classes e herança, recuperamos as coordenadas de
Betelgeuse conforme mostrado na Seção. 2.1.2 e depois transformá-lo no quadro horizontal do
observador para os tempos listados no tempo.

28 # estrela que queremos observar 29


betelgeuse = SkyCoord.from_name('Betelgeuse') 30 31 betelgeuse_local
= betelgeuse.transform_to(frame_local_24h)

O método transform_to() transforma a declinação e a ascensão reta da estrela em altitudes


e azimutes para a seqüência de tempo dos quadros definidos na linha 23 acima. Os
telescópios modernos são controlados por software, tornando relativamente fácil para o
observador direcionar um telescópio para um objeto celeste específico. Basicamente, o
software usa algo como transform_to() do Astropy e move o telescópio de acordo.
Instrumentos históricos, como o refletor de 1 m mostrado na Fig. 2.6, são uma questão
diferente. Eles são operados manualmente e o observador precisa saber a posição de um
objeto no céu.
Para determinar as fases da luz do dia, precisamos determinar a posição do Sol nos
mesmos quadros. Como a posição do Sol muda não apenas na horizontal, mas também
no sistema de coordenadas equatorial, o Astropy oferece uma função especial para o Sol:

32 # coordenadas dependentes do tempo do Sol no sistema equatorial 33 sun = get_sun(time)


34

35 sun_local = sun.transform_to(frame_local_24h)

Isso completa a preparação dos dados.


Agora vamos traçar a altitude de Betelgeuse e do Sol para o intervalo de tempo e local
escolhidos:

36 importar matplotlib.pyplot como plt 37 %matplotlib


inline
38
39 elapsed_night = decorrido[np.where(sun_local.alt < 0)] 40 betelgeuse_night = \

41 betelgeuse_local.alt[np.where(sun_local.alt < 0)]


42
43 plt.plot(decorrido.para(uh), sun_local.alt,
44 color='orange', label='Sun') 45
plt.plot(elapsed.to(uh), betelgeuse_local.alt, 46 color='red', linestyle=':',
Machine Translated by Google

2.1 Astronomia Esférica 39

Fig. 2.6 Refletor de 1 m do Observatório de Hamburgo. Quando o instrumento foi comissionado em 1911,
era o quarto maior refletor do mundo. Na primeira metade do século 20, o astrônomo Walter Baade usou
o telescópio para observar um grande número de aglomerados de estrelas, nebulosas de gás e galáxias.
Para mais informações, consulte www.physik.uni-hamburg.de/en/hs/outreach/historical/instruments.html
(Crédito da imagem: Markus Tiemann, Martiem Fotografie)

47 label='Betelgeuse (daylight)') 48
plt.plot(elapsed_night.to(uh), betelgeuse_night, color='red', label='Betelgeuse
49 (night)')
50
51 plt.xlabel('Hora do meio-dia [h]') 52 plt.xlim(0, 24)
53 plt.xticks(np.arange(13)*2) 54 plt.ylim(0, 60) 55
plt.ylabel ('Altitude [graus]') 56 plt.legend(loc=' centro
superior') 57 plt.savefig("Betelgeuse_obs_window.pdf")

Vamos começar com a declaração do enredo nas linhas 43-44. Traçamos a altitude do
Sol (sun_local.alt) em função do tempo decorrido desde o meio-dia em horas. Em vez
de usar cores padrão, definimos a cor da linha como laranja (color='orange').
O gráfico para a altitude de Betelgeuse tem dois componentes. Usamos uma linha
pontilhada (linestyle=':') em vermelho para traçar a altitude em todo o intervalo de 24 horas
(linhas 45–47). Como a estrela só é observável durante a noite, a linha pontilhada é
sobreposta por uma linha sólida para aqueles momentos em que a altitude do Sol é
negativa, ou seja, abaixo do horizonte – essa é basicamente a definição de noite. Como
fazemos isso? Você encontra a resposta nas linhas 39–41, onde a expressão
Machine Translated by Google

40 2 Computação e Exibição de Dados

Fig. 2.7 Altitude do Sol e da estrela Betelgeuse vista do Observatório de Hamburgo em 31 de julho de 2020

np.where(sun_local.alt < 0)

aparece como um índice entre colchetes. A função np.where() identifica os elementos de


sun_local.alt que são menores que zero e retorna seus índices (lembre-se que os elementos do
array são identificados por seus índices). Esses índices, por sua vez, podem ser aplicados para
selecionar os elementos correspondentes em decorrido e betelgeuse_local.alt, produzindo
matrizes mascaradas . Isso é equivalente a percorrer os arrays, onde qualquer elemento
decorrido[i] e betelgeuse_local.alt[i] para o qual sun_local.alt[i] não é menor que zero (Sol acima
do horizonte) é removido. No Exercício 2.4, você aprenderá como np.where() pode ser utilizado
para escolher entre elementos de dois arrays dependendo de uma condição. Isso pode ser
considerado como a versão de matriz de ramificação.

O resultado pode ser visto na Fig. 2.7. Como os objetos com altitude negativa são invisíveis
para o observador, apenas valores positivos são mostrados (ver linha 54). Além disso, os rótulos
de marcação para o eixo do tempo são definidos explicitamente com plt.xticks() na linha 53. A
noite é aproximadamente entre 21h e 6h (18 h contadas a partir do meio-dia do dia anterior).17
Betelgeuse nasce por volta das 4h. pela manhã e restam apenas duas horas antes do nascer do sol.
Este é o intervalo para o qual a linha vermelha sólida plotada nas linhas 48–49 é visível no
gráfico. Na verdade, a janela de observação é ainda mais estreita. O amanhecer é bastante
longo a uma latitude de 53ÿ. O período de escuridão completa, a chamada noite astronômica, é
definido por ÿ ÿ ÿ18ÿ. Embora Betelgeuse seja uma estrela muito brilhante, Hamburgo
definitivamente não é o local ideal para observar a estrela no verão (veja o Exercício 2.7).

17Você pode se surpreender com o fato de o Sol não atingir sua altitude máxima ao meio-dia. Uma razão óbvia
é que o horário de verão muda o meio-dia (12h) em uma hora. Além disso, dependendo da longitude do
observador, os fusos horários não estão perfeitamente alinhados com o ponto culminante do Sol.
Machine Translated by Google

2.1 Astronomia Esférica 41

Exercícios

2.1 Calcule a declinação do Sol para os equinócios e solstícios usando apenas funções
trigonométricas do módulo matemático em um laço for explícito. Imprima os resultados e verifique
se eles concordam com os valores calculados com NumPy nesta seção.
Este exercício o ajudará a entender o que está por trás de um loop implícito.

2.2 A contagem de dias N na Eq. (2.1) pode ser calculado para uma determinada data com a
ajuda do módulo datetime. Por exemplo, o dia do equinócio vernal no ano de 2020 é dado por

vernal_equinox = datetime.date(2020, 3, 20) - \ datetime.date(2020, 1, 1)

Então vernal_equinox.days é avaliado como 79. Defina o array N (equinócios e solstícios) usando
datetime.

2.3 Uma fórmula mais precisa para a declinação do Sol leva em conta a excentricidade e = 0,0167
da órbita da Terra18:

360ÿ 360ÿ 360ÿ


ÿ = ÿ arcsin sen( 0) cos (N + 10) + e sen 365,24 (N - 2)
ÿ 365,24

Calcule a declinação assumindo uma órbita circular (Eq. 2.1), a declinação resultante da fórmula
acima, a diferença entre esses valores e o desvio relativo da aproximação circular em % para
equinócios e solstícios e liste seus resultados em uma tabela. Certifique-se de que um número
adequado de dígitos seja exibido para comparar as fórmulas.

2.4 A maior altitude amax (também conhecida como culminação superior) de uma estrela medida
a partir do plano horizontal19 de um observador na Terra é dada por

90ÿ ÿ ÿ + ÿ se ÿ ÿ ÿ, 90ÿ +
amax = (2.3)
ÿ ÿ ÿ se ÿ ÿ ÿ,

onde ÿ é a latitude do observador e ÿ a declinação da estrela. Calcule amax em sua localização


atual para as seguintes estrelas: Polaris (ÿ = +89ÿ 15 51 ), Betelgeuse (ÿ= + 07ÿ 24 25 ), Rigel (ÿ
= ÿ08ÿ 12 15 ), e Sirius A (ÿ= ÿ 16ÿ 42 58 ). Para distinguir os dois casos na Eq. (2.3), use a função
where() de numpy. Por exemplo, a expressão

np.where(phi <= delta, phi-delta, phi+delta)

18Veja en.wikipedia.org/wiki/Position_of_the_Sun#Calculations.
19O plano horizontal é tangencial à superfície da Terra no local do observador, supondo que a
Terra seja uma esfera perfeita.
Machine Translated by Google

42 2 Computação e Exibição de Dados

compara phi e delta elemento por elemento e retorna um array com elementos de phi-delta
onde a condição phi <= delta é verdadeira e elementos de phi+delta onde é falsa. Imprima
os resultados com o número apropriado de dígitos significativos junto com as declinações.

2.5 Um dia sideral é cerca de 3 min 56 s mais curto que um dia solar (24 h). Mostre que
isso implica 1h ÿ 0,9973 h. Como você precisaria modificar a definição de T na Sec. 2.1.2
fazer uso deste fator sem utilizar unidades Astropy?

2.6 Calcule e plote a variação anual da duração do dia em sua localização geográfica
usando a fórmula com correção de excentricidade do Exercício 2.3 e get_sun() do
SkyCoord. Qual o tamanho do desvio? Como seu resultado se compara com outros lugares
mostrados na Fig. 2.5?

2.7 Determine a janela de observação para Betelgeuse na véspera de Ano Novo. Comece
com a localização do Observatório de Hamburgo (ver Seção 2.1.3). Quantas horas a
estrela é observável durante a noite astronômica, ou seja, quando o Sol está pelo menos
18ÿ abaixo do horizonte? Mude para sua localização e calcule as altitudes de Polaris,
Betelgeuse e Sirius A para a próxima noite. Produza parcelas semelhantes à Fig. 2.4.
Desde que o céu esteja limpo, quais estrelas você seria capaz de ver?

2.2 Leis do Movimento Planetário de Kepler

As leis fundamentais do movimento planetário foram formuladas pela primeira vez pelo
astrônomo Johannes Kepler com base em dados empíricos no início do século XVII. Kepler
usou as medições mais precisas de posições planetárias disponíveis na época.
Particularmente para o planeta Marte, ele notou que seu movimento aparente no céu pode
ser explicado assumindo que o planeta segue uma órbita elíptica ao redor do Sol.
Esta foi uma proposta bastante revolucionária, pois o movimento dos planetas era
considerado circular (mais precisamente, uma combinação de movimentos circulares no
sistema ptolomaico), com a Terra residindo no centro do Universo. Embora as diferenças
fossem bastante diminutas, Kepler concluiu de sua análise que os planetas se movem em
órbitas elípticas, onde o Sol está localizado em um ponto focal (primeira lei) e, em
linguagem moderna, a área varrida pelo vetor radial do Sol ao um planeta é proporcional
ao tempo decorrido (segunda lei). Mais tarde, ele encontrou uma relação entre os semi-
eixos maiores (o segmento de linha do centro através do foco até o perímetro de uma
elipse) e os períodos orbitais, que hoje é conhecido como terceira lei de Kepler. Isaac
Newton encontrou uma explicação teórica para as leis do movimento planetário de Kepler
aplicando sua lei universal da gravidade e conservação do momento angular (veja [4, Cap.
2] para uma derivação e discussão detalhadas). Voltaremos à primeira e à segunda lei na
Sec. 4.3, quando a integração numérica é aplicada para resolver as equações de
movimento para o problema de dois corpos (Sol e planeta).
A formulação geral para o período P de um planeta movendo-se em uma órbita elíptica
em torno de uma estrela lê
Machine Translated by Google

2.2 Leis do Movimento Planetário de Kepler 43

4ÿ2
P2 = a3 , (2.4)
G(M + m)

onde a é o semi-eixo maior da órbita, G a constante gravitacional, M a


massa da estrela e m a massa do planeta. Na Sec. 1.2, usamos um valor aproximado
expressão (1.2), que é aplicável se a massa do planeta for desprezível, ou seja, m M,
e a órbita é circular (neste caso, a é igual ao raio r).
O programa a seguir calcula o período orbital dado pela Eq. (2.4) para o
oito planetas do sistema solar. Na verdade, isso também é uma aproximação porque o
influência mútua dos planetas é negligenciada. Em outras palavras, a terceira lei de Kepler assume um
sistema de dois corpos (o Sol e um único planeta). É mais preciso do que a massa-teste
aproximação (m = 0). O código compara os períodos resultantes da
fórmulas de dois corpos e massa-teste.

1 importação matemática
2 importar numpy como np
3 de scipy.constants importação ano, hora, au, G
4 de astropy.constants import M_sun
5
6 M = M_sun.value # massa do Sol em kg
7
8 # parâmetros orbitais dos planetas
9 # consulte https://nssdc.gsfc.nasa.gov/planetary/factsheet/
10 # massa em kg
11 m = 1e24 * np.array([0,33011, 4,8675, 5,9723, 0,64171,
12 1898,19, 568,34, 86,813, 102,413])
13 # semi-eixo maior em m
14 a = 1e9 * np.array([57,9, 108,21, 149,60, 227,92,
15 778,57, 1433,53, 2872,46, 4495,06])
16
17 # use a terceira lei de Kepler para calcular o período em s
18 T_test_mass = 2*math.pi * (G*M)**(-1/2) * a**(3/2)
19 T_two_body = 2*math.pi * (G*(M + m))**(-1/2) * a**(3/2)
20
21 print("T [ano] dev [hr] dev rel.")
22 para val1,val2 em zip(T_test_mass,T_two_body):
23 dev = val1 - val2
24 se dev > hora:
25 linha = "{0:6.2f} {1:<7.1f} {2:.1e}"
26 senão:
27 linha = "{0:6.2f} {1:7.4f} {2:.1e}"
28 print(line.format(val2/ano, dev/hora, dev/val1))

Usamos scipy.constants para a constante gravitacional G e a definição de


a massa do Sol de astropy.constants (ver Seção 1.4). As massas de
os planetas e o semi-eixo maior de suas órbitas ao redor do Sol são tomados de
Machine Translated by Google

44 2 Computação e Exibição de Dados

Site da NASA (ver comentário). Os cálculos no programa acima são baseados no sistema de
unidades SI. Para expressar os resultados em anos e unidades astronômicas, usamos fatores de
conversão de unidades de scipy.constants. Esses fatores são apenas números. Por exemplo, ano
é um ano em segundos e au é uma unidade astronômica em metros. Na Sec. 3.1, você aprenderá
como usar o módulo de unidades do Astropy para realizar conversões de unidades com a ajuda de
métodos (uma primeira amostra foi dada na seção anterior).
Os períodos orbitais definidos pela Eq. (2.4) e a aproximação de massa-teste, onde a massa do
planeta é desprezada, são calculadas nas linhas 18 e 19, respectivamente, usando operações de
arranjo. Os resultados são impressos no loop for nas linhas 22–28 (veja a Seção 2.1 para uma
explicação da função zip() ), onde a primeira coluna lista os períodos dados pela Eq. (2.4), a
segunda coluna o desvio da aproximação da massa de teste em h, e a terceira coluna o desvio
relativo:

T [ano] dev [hr] dev rel.


0,24 0,0002 8,3e-08
0,62 0,0066 1,2e-06
1,00 0,0132 1,5e-06
1,88 0,0027 1,6e-07
11,88 49,6 4.8e-04
29,68 37,2 1.4e-04
84,20 16,1 2.2e-05
164,82 37,2 2.6e-05

Enquanto Mercúrio gira em torno do Sol quatro vezes por ano, Netuno leva bem mais de um século
para completar sua órbita. Para imprimir o período em anos, precisamos dividir o valor calculado
em unidades SI (s) pelo fator de conversão ano (ver linha 28). O desvio da aproximação da massa
de teste é maior para os planetas externos (Júpiter, Saturno, Urano e Netuno), pois são muito mais
massivos do que os planetas internos (Mercúrio, Vênus, Terra e Marte). No entanto, o erro relativo
do período orbital é pequeno. Para alinhar os valores na segunda coluna no ponto decimal, uma
cláusula if-else é usada para definir o formato de uma linha dependendo se o desvio absoluto é
maior ou menor que uma hora (hora é uma hora em segundos).

A largura da coluna é de 7 dígitos em ambos os casos, mas os valores para os planetas externos,
mais massivos, são impressos com apenas um dígito após o ponto decimal e deslocados para a
esquerda inserindo o caractere < no especificador de formato na linha 25 (experimente com
diferentes formatos para entender como eles funcionam).
Leis de potência, como P ÿ a2/3, aparecem como linhas retas com inclinação igual ao expoente
em um diagrama logarítmico duplo:

2 log P = log a + const. (2.5)


3

Podemos plotar nossos resultados em escala log-log aplicando a função loglog() do módulo pyplot :
Machine Translated by Google

2.2 Leis do Movimento Planetário de Kepler 45

Fig. 2.8 Períodos orbitais dos planetas do sistema solar calculados com a terceira lei de Kepler

29 import matplotlib.pyplot as plt 30 %matplotlib


inline 31 32 plt.loglog(a/au, T_test_mass/year, 'blue',
linestyle='--',\ 33

label='test mass') 34
plt.loglog(a/au, T_two_body/year, 'ro', label='planets') 35 plt.legend(loc='inferior direito')
36 plt.xlabel("semi- eixo maior [AU]") 37 plt.ylabel(" período orbital [ano]") 38
plt.savefig("kepler_third_law.pdf")

Esta saída gráfica é mostrada na Fig. 2.8. Traçar o período em hr versus o semi-eixo maior
em AU é simplesmente uma questão de dividir as matrizes pelos fatores de conversão de
unidades scipy hr (s para hr) e au (m para AU), respectivamente. Os dados de massa de
teste, que obedecem exatamente à lei de potência, são exibidos como uma linha tracejada
azul, enquanto os elementos em T_two_body são plotados como pontos vermelhos ( 'ro' é
a notação curta para círculo vermelho). 2.1.3) pode ser omitido se for o terceiro argumento
após as duas matrizes de dados que especifica a cor do gráfico. Esse tipo de argumento é
chamado de argumento posicional, em oposição a um argumento identificado por uma
palavra-chave como estilo de linha. Diferentes tipos de argumentos serão abordados com
mais detalhes na Seção. 3.1.2, quando você aprender a definir funções em Python.
Exercícios

2.8 Além dos oito planetas do sistema solar, existem vários planetas anões. Exemplos são
Plutão (a = 39,48 UA), que anteriormente era considerado como

20Consulte https://matplotlib.org/stable/api/colors_api.html e
https://matplotlib.org/stable/api/markers_api.html para cores e marcadores disponíveis, respectivamente.
Machine Translated by Google

46 2 Computação e Exibição de Dados

nono planeta, 21 Ceres (a = 2,7675 UA) no cinturão de asteróides, e o objeto transnetuniano


Eris (a = 67,781 UA). Calcule os períodos orbitais correspondentes (a massa dos planetas anões
é insignificante) e trace os resultados junto com os dados orbitais dos planetas usando
marcadores diferentes e um rótulo adicional na legenda para os planetas anões.

2.9 Desde a descoberta dos primeiros exoplanetas (planetas extrasolares) em meados dos
anos noventa, muitos mais foram identificados. Uma classe importante são os chamados
Júpiteres quentes. Esses objetos têm alta massa, mas, ao contrário dos gigantes gasosos do
sistema solar, estão muito mais próximos de sua estrela-mãe. Normalmente, o período orbital de
um Júpiter quente é de apenas alguns dias (em comparação com quase doze anos para Júpiter
no sistema solar). A Tabela 2.1 lista uma amostra de Júpiteres quentes descobertos com o método transiente.
A massa do planeta é frequentemente um limite inferior, pois depende da inclinação desconhecida
da órbita em relação à linha de visão.

(a) Calcule o semi-eixo maior a em AU para esses exoplanetas usando a massa do planeta m e
a massa da estrela M como parâmetros e plote o período orbital P versus a e plote seus
resultados. (b) Você pode usar a função NumPy polyfit() para determinar um ajuste linear
aos dados logarítmicos. Chame polyfit() com o logaritmo de P em dias como primeiro argumento
(x-data), o logaritmo de a em AU como segundo argumento (y-data) e o grau da função
polinomial ajustada aos dados como terceiro argumento .

Aqui, o grau é 1 para uma função linear y = c1x + c0. polyfit() retorna os parâmetros de
ajuste c0 e c1. Compare com a formulação logarítmica (2.5) da terceira lei de Kepler. Por
que a inclinação não é exatamente reproduzida? Exiba o período orbital após o ajuste como
uma linha no gráfico de (a).

2.10 Imagine que uma nave espacial tripulada é enviada a Marte. Vamos supor que a
espaçonave siga uma trajetória de transferência de Hohmann (veja a Fig. 2.9). Esta é a maior
economia de energia (ou seja, requer a menor quantidade de propelente), embora não seja a
opção mais rápida para chegar a Marte. A trajetória é formada por metade de uma órbita elíptica
ao redor do Sol tocando as órbitas da Terra e de Marte em seu periélio e afélio, respectivamente.22
Em cálculos básicos, as órbitas planetárias são assumidas como circulares, com raios rÿ = 1 UA
(Terra) e rÿ = 1,524 UA (Marte). Neste caso, as distâncias radiais do periélio e do afélio são rp =
rÿ e rp = rÿ, respectivamente. Após o lançamento, os propulsores empurram a nave espacial da
órbita da Terra para a trajetória de transferência. Calcule o semi-eixo maior aH da órbita de
transferência elíptica e a diferença de velocidade v = vp ÿ vÿ, onde vp é a velocidade necessária
para entrar na órbita no periélio e vÿ é a velocidade orbital da Terra. (Aplicar vis-viva Eq. (4.46)
para calcular vp; veja também

21Plutão foi degradado a planeta anão em 2006, depois que novos critérios para a definição de planeta foram aceitos
pela União Astronômica Internacional. No entanto, o debate se Plutão é um planeta ou não ganhou força novamente,
principalmente após a missão espacial New Horizons entregou imagens fascinantes deste mundo gelado nos
arredores do sistema solar.
22O termo órbita geralmente se refere a um tipo especial de trajetória, ou seja, o caminho do movimento periódico
em torno de um centro gravitacional.
Machine Translated by Google

2.2 Leis do Movimento Planetário de Kepler 47

Tabela 2.1 Lista de parâmetros orbitais e estelares para uma amostra de Júpiteres quentes de exoplanets.org.
O nome do exoplaneta é derivado de um catálogo estelar ou do instrumento descobridor
(a letra 'b' sempre indica o primeiro exoplaneta no sistema da estrela-mãe), P é o orbital
período em dias, e m sua massa em unidades da massa de Júpiter, MJ = 1,898 × 1027 kg. A massa M de
a estrela-mãe é especificada em unidades da massa solar (M = 1,988 × 1030 kg)
Exoplaneta P/dia m/ MJ MILÍMETROS

CoRoT- 3ba 4.257 22 1,37

Kepler-14b 6.790 8.4 1,51

Kepler-412b 1.721 0,94 1,17


HD 285507b 6.088 0,92 0,73
WASP-10b 3.093 3.19 0,79
WASP-88b 4.954 0,56 1,45
WASP-114b 1.549 1,77 1,29

aCom uma massa maior que 13MJ, CoRoT-3 b é uma anã marrom

Fig. 2.9 Vista esquemática de v M´


uma

uma transferência de Hohmann

trajetória (preto sólido) de


a órbita da Terra (azul) para o
Órbita de Marte (vermelho). o
periélio e afélio
velocidade nos pontos do vértice
são vp e va, respectivamente.
As posições dos planetas
no momento do lançamento são indicados ÿÿ
por E e M, a posição final
por M O. ângulo ÿ é o ÿ
separação angular inicial de
Terra e Marte e ÿ é
o ângulo varrido por Marte sobre
o tempo de transferência tH M
E vp

[4, Cap. 2] para equações e relações importantes.) Qual é o tempo de trânsito tH para
a órbita de Marte? Qual condição para a separação angular ÿ da Terra e Marte
(ou seja, o ângulo entre os vetores de posição rÿ e rÿ) no momento do lançamento deve ser atendido
para a espaçonave realmente fazer um rondezvous com Marte no afélio (assumindo que Marte
se move em uma órbita circular)?

2.3 Forças de maré

O movimento orbital de dois corpos é governado pela lei da gravitação de Newton para
massas pontuais. No entanto, a dependência da força gravitacional da distância dá
Machine Translated by Google

48 2 Computação e Exibição de Dados

aumentar as forças de maré entre diferentes partes de um corpo estendido, como um planeta,
no campo gravitacional de outro corpo. Consideremos uma pequena massa de teste m no
campo gravitacional g = (GM/ r 2)er de um corpo distante de massa M (er = r/r é a unidade
vetor na direção radial a partir do centro desse corpo). A diferença entre o
forças gravitacionais exercidas sobre a massa de teste nos pontos vizinhos r e r + dr podem
ser expresso pelo gradiente de campo:

ÿ2GMm dr .
dF = mÿg · dr = 3
(2.6)
horas

Agora, se pensarmos em diferentes partes de um planeta em vez de uma massa de teste colocada em diferentes
posições, a força de maré é dada pela diferença de força em relação ao centro de
massa.
Praticamente todo mundo sabe sobre as marés devido à gravidade da Lua exercida
na terra. Considere um ponto P a uma distância R ÿ RE do centro C da Terra (veja
Fig. 2.10). A diferença de força aproximada é dada por

F ÿ ( Fx , Fy ) = FPM ÿ FCM
GMmR (2.7)
3
(2 cos ÿ , ÿ sen ÿ),
horas

onde r R é a distância da Terra à Lua (veja [4, Seção 19.2] para um


derivação). A componente de força Fx é direcionada ao longo da linha que liga o
centros de massa C e M (linha pontilhada na Fig. 2.10) e Fy é perpendicular a
aquela linha. A magnitude da força de maré aumenta com a distância da Terra
Centro. Tem um máximo tanto na direção da Lua (ÿ = 0) quanto na
direção oposta (ÿ = ÿ). Às vezes é concebido como contra-intuitivo que as marés
forças são mais fortes e direcionadas para fora e, assim, produzindo marés altas tanto no
lado mais próximo e o lado mais distante. No entanto, isso decorre do fato de que as forças de maré são
forças diferenciais.

P
MPF
r
R y R sin

ÿ FCM
C
x R cos M

Fig. 2.10 Ilustração das forças gravitacionais locais exercidas pela Lua (M) no centro da Terra
(C) e em algum ponto na superfície (P). A diferença entre as forças é a força de maré dada
pela Eq. (2.7)
Machine Translated by Google

2.3 Forças de maré 49

O programa a seguir calcula a força de maré por unidade de massa, maré = F/ m, para
uma grade de pontos com espaçamento igual ao longo dos eixos x e y dentro de um
círculo de raio R = RE:

1 import numpy as np 2 from


scipy.constants import g,G 3 from astropy.constants
import R_earth,M_earth 4 5 M = 0.07346e24 # massa da lua em kg 6 r
= 3.844e8 # semi-eixo maior da órbita da lua em m 7

8 coef = G*M/r**3 9
accel_scale = 2*coeff*R_earth.value 10 print("aceleração
das marés = {:.2e} m/s^2 = {:.2e} g".\ 11 format (accel_scale,accel_scale/g)) 12 13 h =
15*M*R_earth.value**4/(8*M_earth.value*r**3)
maré = {:.2f} m ".format(h)) 15 16 14#print("tamanho dade
array de pontos protuberância
grade de
uniformemente espaçados ao longo dos eixos x e y 17 X = np.linspace(-1.1, 1.1,
num=23, endpoint=True)

18 Y = np.linspace(-1.1, 1.1, num=23, endpoint=True) 19 print(X)

20
21 # cria uma grade de malha bidimensional dimensionada pelo raio da Terra 22 R_x, R_y
= np.meshgrid(R_earth.value*X, R_earth.value*Y) 23 print(R_x.shape) 24 print(R_x[11,21],
R_y[11,21]) 25 26 # distâncias radiais de pontos de malha de (0,0)

27 R = np.sqrt(R_x*R_x + R_y*R_y) 28 29 #
componentes do campo de aceleração de maré
dentro do raio da Terra 30 accel_x = np.ma.masked_where(R > R_earth.value, 2*coeff*R_x) 31
accel_y = np.ma.masked_where(R > R_earth.value, -coeff*R_y)

A magnitude da maré para R = RE ao longo do eixo que liga os centros da Terra e da Lua
3
(ou seja, para ÿ = 0) define a escala 2GMRE/ r da aceleração da maré. éSeu
calculado
valor numérico
nas
linhas 8 e 9 com constantes de astropy.constants e dados para a Lua23:

aceleração das marés = 1,10e-06 m/sˆ2 = 1,12e-07 g

Em relação à gravidade da Terra, g ÿ 9,81 m/s2 (usamos a constante g definida em


scipy.constants), a aceleração das marés é muito pequena. Caso contrário, as forças de
maré teriam efeitos muito mais drásticos na Terra. Na linha 13, calculamos a altura do
bojo de maré da Terra causado pela Lua, usando uma fórmula aproximada desprezando
a rigidez da Terra [5]:

23nssdc.gsfc.nasa.gov/planetary/factsheet.
Machine Translated by Google

50 2 Computação e Exibição de Dados

3M R4E
h= ÿ, onde ÿ 5/2. (2.8)
4MEr 3

O resultado é de fato comparável às marés altas nos oceanos24:

tamanho da protuberância de maré = 0,67 m

O próximo passo é a discretização das coordenadas xey introduzindo pontos de grade


xn = nx e yn = ny ao longo dos eixos de coordenadas. Nas linhas 17 e 18, matrizes NumPy
de pontos de grade são produzidas com np.linspace(). Essa função retorna um determinado
número de pontos uniformemente espaçados no intervalo especificado pelos dois primeiros
argumentos. Usamos coordenadas adimensionais normalizadas pelo raio da Terra, para
que não precisemos nos preocupar com distâncias reais. Como queremos cobrir uma região
um pouco maior que a Terra, que tem um diâmetro de 2,0 no sistema de coordenadas
normalizado, subdividimos o intervalo [ÿ1,1, 1,1] em 23 pontos, incluindo ambos os pontos finais.
Isso implica x = y = 2,2/(23 ÿ 1) = 0,1, correspondendo a um comprimento físico de 0,1RE.
A instrução print na linha 19 mostra que os elementos resultantes de X:

[-1.1 -1. -0,9 -0,8 -0,7 -0,6 -0,5 -0,4 -0,3 -0,2 -0,1 0.
0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1. 1.1]

Para uma representação do campo vetorial atidal(R), precisamos construir uma malha
bidimensional de vetores posição R = (Rx , Ry ) ÿ (x, y) no plano xy .
Devido à simetria de rotação do sistema Terra-Lua, podemos desconsiderar a componente
z . Uma malha de malha bidimensional de pontos pode ser construída a partir de todas as
combinações possíveis de xn e ym com índices independentes n e m. Este é o propósito
da função NumPy meshgrid() chamada na linha 22. Para obter distâncias físicas, as
coordenadas normalizadas são dimensionadas com o raio da Terra (importado de
astropy.constants). Como X e Y têm 23 elementos cada, np.meshgrid() retorna arrays
bidimensionais definindo os componentes Rx e Ry para uma grade de malha consistindo
de 23 × 23 = 529 pontos. Aqui, vários valores de retorno (neste caso, arrays) são atribuídos
a várias variáveis (R_x e R_y). Você pode pensar em uma matriz bidimensional como uma
matriz, neste caso com 23 linhas e 23 colunas.
Isso pode ser visto imprimindo a forma de R_x (veja a linha 23), que é

(23, 23)

Para obter um determinado elemento, você precisa especificar dois índices entre colchetes,
sendo o primeiro o índice da linha e o segundo o índice da coluna. Por exemplo, os valores
de R_x[11,21] e R_y[11,21] impressos na linha 24 são

6378100,0 0,0

24As marés ficam muito mais altas nas águas costeiras e as marés produzidas pelo Sol amplificam ou
compensam parcialmente as marés lunares dependendo do alinhamento com a Lua.
Machine Translated by Google

2.3 Forças de maré 51

x = [-3, -2, -1, 0, 1, 2, 3] y = [-3, -2, -1, 0, 1, 2, 3]

-3 -2 -1 0 1 2 3 -3 -3 -3 -3 -3 -3 -3

-3 -2 -1 0 1 2 3 -2 -2 -2 -2 -2 -2 -2

-3 -2 -1 0 1 2 3 -1 -1 -1 -1 -1 -1 -1

R_x -3 -2 -1 0 1 2 3 R_y 0000000

-3 -2 -1 0 1 2 3 1111111

-3 -2 -1 0 1 2 3 2222222

-3 -2 -1 0 1 2 3 3333333

3
2
1
0
-1
-2
-3
-3 -2 -1 0 1 2 3

Fig. 2.11 Ilustração da construção de uma grade de malha a partir de matrizes unidimensionais X e Y (topo).
As matrizes bidimensionais R_x e R_y (meio) representam as coordenadas de todos os pontos na malha (inferior). Como
exemplos, as coordenadas dos pontos vermelhos e verdes são destacadas nas matrizes R_x e R_y

ou seja, a posição é R = (RE, 0). Para entender como isso acontece, pode ser útil
considerar um exemplo mais simples com um número menor de pontos e sem escala.
A Figura 2.11 mostra como uma grade de malha consistindo de 7 × 7 pontos é construída
a partir de matrizes unidimensionais de tamanho 7. O ponto verde, por exemplo, tem
coordenadas (1, ÿ3), que são dadas por R_x[0,4] e R_y[0,4] (veja os quadrados verdes
nas duas matrizes no meio da figura). Como você pode ver, a coordenada x muda com
o índice da coluna e a coordenada y com o índice da linha. Você pode se perguntar por
que as matrizes bidimensionais R_x e R_y são necessárias. São apenas representações
redundantes, não são? Afinal, as linhas de R_x são idênticas e as colunas de R_y
também. No entanto, as matrizes bidimensionais nos permitem inferir imediatamente os
componentes do vetor posição (ou algum outro vetor) para todos os pontos da malha.
Com efeito, esta é uma representação discreta de um campo vetorial, onde um vetor é
anexado a cada ponto no espaço (o campo de vetores posição é apenas um caso especial).
Para uma dada posição (Rx , Ry ), a aceleração de maré atidal = F/m segue de
Eq. (2.7), onde R cos ÿ = Rx e R sen ÿ = Ry . Desta forma,
Machine Translated by Google

52 2 Computação e Exibição de Dados

GM
attidal(R) = (2Rx , ÿRy ).
3
(2.9)
horas

Isso é feito nas linhas 30 e 31 usando a aritmética NumPy. Para restringir o campo de
aceleração a uma área circular de raio RE, definimos matrizes mascaradas, uma máscara
sinaliza cada elemento de uma matriz com 0 ou 1. Se um elemento for sinalizado com 1, seu
valor se tornará inválido e não será usado em operações de matriz. Como os elementos
mascarados não são removidos de um array (eles podem ser desmascarados posteriormente),
todos os elementos não mascarados com sinalizador 0 são acessíveis pelos mesmos índices
do array original. Para fins mais práticos, arrays podem ser mascarados com a ajuda de funções
definidas no módulo numpy.ma (um método alternativo é explicado na Seção 2.1.3). Aqui,
usamos masked_where(). Essa função mascara todos os elementos de um array para os quais
uma condição lógica é avaliada como True. Como queremos excluir posições fora da Terra,
aplicamos a condição R > R_earth.value, onde a distância radial R é definida na linha 27, para
mascarar os arrays accel_x e accel_y.

Depois de computados os dados, o campo de aceleração pode ser visualizado por rep
reenviando vetores graficamente como setas:
32 import matplotlib.pyplot as plt 33 from
matplotlib.patches import Circle 34 %matplotlib inline 35 36
fig, ax = plt.subplots(figsize=(6,6)) 37 ax.set_aspect('equal') 38
39 # plot vector campo 40 setas = ax.quiver(X, Y, accel_x,
accel_y, color='blue') 41 ax.quiverkey(arrows, X=0.1, Y=0.95,
U=accel_scale, 42 label=r'$1.1\times 10 ^{-6}\;\mathrm{m/s}
^2$', 43 labelpos='E') 44 45 # adiciona um círculo 46 circle =
Circle((0, 0), 1, alpha=0.2, edgecolor =Nenhum) 47
ax.add_patch(círculo) 48 49 ax.set_xlabel(r'$x/R_{\mathrm{E}}$', fontsize=12) 50
ax.set_ylabel(r'$y/R_{\mathrm {E}}$', fontsize=12) 51 52 plt.show() 53
plt.savefig("tidal_accel_earth.pdf")

Um campo de setas pode ser produzido com o método quiver(), que é chamado em um objeto
axes na linha 40. Este objeto é criado invocando plt.subplot() (veja a linha 36).25 Na linha 37, a
proporção dos eixos x e y é definido como unidade para produzir um gráfico quadrático. A
chamada de quiver() requer os pontos de grade X e Y ao longo dos eixos de coordenadas e os
valores de malha de grade accel_x e accel_y da aceleração

25Geralmente a função plt.subplots() é aplicada para produzir vários gráficos em uma única figura,
consulte https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html e Seção. 4.2.
Machine Translated by Google

2.3 Forças de maré 53

Fig. 2.12 Campo de aceleração das marés dentro da Terra devido à gravidade da Lua

campo como argumentos. Enquanto X e Y determinam as posições das setas (a malha é construída
implicitamente), seu comprimento e orientação são dados por accel_x e accel_y. A cor da seta pode
ser especificada por um argumento opcional, semelhante à cor da linha em plt.plot(). O método
quiverkey() (linha 41) exibe uma seta rotulada com o valor correspondente ao comprimento da seta
nas coordenadas especificadas na lista de argumentos. Esta seta não faz parte do campo vetorial que
queremos visualizar; serve apenas para mostrar a escala do campo de aceleração. O interior da Terra
é destacado com a ajuda de Circle() de matplotlib.patches.

Em nosso exemplo, ele produz um círculo preenchido com raio unitário (lembre-se que as coordenadas
em X e Y são normalizadas pelo raio da Terra) centrado na posição (0, 0). Experimente os argumentos
desta função para ver como eles afetam a aparência do círculo. Para exibir o círculo, add_patch()
(linha 47) deve ser chamado em ax. Este método insere objetos geométricos planos em um gráfico
(tais objetos são chamados de patches no matplotlib). O gráfico resultante é mostrado na Fig. 2.12.
Ele mostra o padrão típico resultando em protuberâncias de maré em lados opostos ao longo da linha
entre a Terra e a Lua.
Como a Terra é aproximadamente um corpo rígido, as protuberâncias são induzidas apenas na água
dos oceanos, dando origem a enchentes e maré baixa.

Exercícios

2.11 Não só provoca as forças de maré da Lua na Terra, mas também vice-versa. Compare o efeito
de maré de Júpiter (massa e raio são definidos em astropy.constants
Machine Translated by Google

54 2 Computação e Exibição de Dados

em sua lua Io (M = 8,9319 × 1022 kg, R = 1822 km, raio orbital médio r = 4,217 × 105 km) para o
sistema Terra-Lua. Quão grandes são as protuberâncias de maré de Io e da Lua? Plote a razão
da magnitude da aceleração das marés definida por
26
Eq. (2.9) à gravidade local g na superfície em função de ÿ.

2.12 A força de tração experimentada por uma barra cilíndrica de comprimento l e massa m
direcionada na direção radial em direção a um corpo gravitante de massa M é encontrada
integrando a Eq. (2.7) usando l r.

(a) Estime a força de tração agindo sobre uma haste de comprimento l = 1 m na superfície da
Terra, a superfície de uma anã branca de uma massa solar e no horizonte de eventos de um
buraco negro com massa M = 10M, supondo que a fórmula baseada na gravidade newtoniana
pode ser usada (o raio do horizonte de eventos é dado pelo raio de Schwarzschild RS = 2GM/
c2, onde c é a velocidade da luz). (b) A que distância radial do todo preto ele será dilacerado
pelas forças de maré se a haste tiver um diâmetro de 5 cm e for feita de aço com densidade ÿ =
7,8 g cmÿ3 e limite de escoamento ÿ = 5 × 108 Pa (ou seja, a força máxima que a haste pode
resistir é ÿ vezes a área da seção transversal). Estime também o quão perto um ser humano
poderia se aproximar do todo preto até que ele experimentasse uma força de tração
comparável ao peso de uma massa de 100 kg na Terra (imagine tal peso sendo preso ao
seu corpo).

(c) Uma vez que qualquer objeto caindo em direção a um buraco negro e passando pelo horizonte
de eventos, mais cedo ou mais tarde, experimentará forças de maré extremas, o alongamento
radial e a compressão em direções transversais resultariam em “espaguetificação”. Corpos
sólidos, no entanto, serão rasgados em pedaços cada vez menores devido à sua
deformabilidade limitada. Produza um gráfico semelhante ao da Fig. 2.12, mostrando o
campo de aceleração de maré atuando na haste na distância crítica determinada em (b).
Use a função Rectangle() de matplotlib.patches para mostrar a seção transversal da haste
ao longo de seu eixo.

26 A gravidade superficial de um corpo esférico de massa M e raio R é dada por g = GM/r 2.

Você também pode gostar