본문 바로가기
파이썬으로 배우는 지구과학

파이썬을 이용해 지구과학2에서 다루는 단열선도 그리기

by 0대갈장군0 2022. 10. 10.
반응형

 

지구과학2에서 다루는 단열선도는 Skew T -Log P diagram이 아닙니다. 그걸 알 필요도 배울 필요도 없고, 과학적인 현상과 논리적 과정을 배우는게 더 중요하기 때문에, 학생들의 수준에 맞게 적절히 변형한 단열선도를 쓰는 것이라고 저는 생각합니다. Skew T -Log P Diagram은 파이썬으로도 그릴수는 있는것 같은데 굉장히 어려운 수학적 과정이 필요합니다. 실제 찾아보니 이미 똑똑이들이 다 그려놨더군요.ㅎㅎㅎ MetPy라는 대기과학용 라이브러리도 있구요(역시 갓 파이썬...) 근데 전 대기과학 전공도 아니고 MetPy는 한번도 사용해보지 않은 라이브러리라 저도 공부를 한 뒤 MetPy를 이용해 단열선도를 그리는 과정은 다음 파이썬 포스팅 때 작성해 볼 생각입니다. 어쨌든 여기서는 고등학교 교육과정을 위한 단열선도를 가지고 왔습니다.

 

고등학교에서 다루는 단열선도 정도는 그려놓으면 여러가지로 요긴하게 사용할 수 있을 것 같아 포스팅 하며 그려 보았고, 잘 활용하면 평가에도 써먹을 수 있을 것 같습니다.

  1. 필수 라이브러리 호출하기

그래프 그릴 때 필수인 matplotlib와 행렬연산에 필요한 numpy를 썼습니다.

import matplotlib.pyplot as plt
import numpy as np

  2. 등고도선과 등온선 그리기

학생들이 배우는 단열선도에는 처음에 등고도선과 등온선이 필요합니다. 등고도선은 수평 방향의 선, 등온선은 수직 방향의 선인데, 그냥 plt.grid()로 그리드 형태 보조선으로 해도 편하겠지만, 일부러 한번 그려보았습니다. 

 

그럼 수평방향의 등고도선을 먼저 그리면, 0~5km까지 0,1,2,3,4,5의 숫자 간격으로 수평선을 그릴겁니다. 총 6개의 수평선이 필요하기 때문에 아래와 같이 코드를 구현했습니다.

heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)

heightcontour라는 변수를 만들어 그릴 선의 종류를 np.linspace로 지정해 주었습니다. 

 

그리고 for문과 수평선을 그릴때 사용하는 코드 plt.axhline을 이용해 6개의 수평선이 그려지게 합니다.

그릴 고도를 더 높이까지 하려면, linspace의 숫자를 바꾸면 되겠죠? 만약 10km까지 하겠다면np.linspace(0,10,11)

 

plt.axhline은 처음 소개하는 것 같습니다. 그래프에서 수평선을 그릴 때 사용하는 것인데,

plt.axhline(그려질 수평선의 y축값, 수평선의 x 최소값, 수평선의 x 최대값, color=색깔, linestyle=선종류, linewidth=선두께)를 의미합니다.

 

여기까지 하고 그래프를 그리면

이렇게 등고도선이 그려졌습니다. 이제 같은 방법으로 등온선을 그릴건데, 등온선은 수직으로 그려야 합니다. 이 때는 axvline가 필요합니다. 수직방향 등온선은 0~20도까지 5도 간격으로 그려보겠습니다.

import matplotlib.pyplot as plt
import numpy as np
tempcontour=np.linspace(0,20,5)
heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)
for temp in tempcontour:
    plt.axvline(temp,0,20,color='gray', linestyle='--',linewidth=1)

이렇게 하여 나온 결과는 아래와 같습니다.

여기서 사용한 axvilne의 사용방법은 axhline과 거의 동일합니다.

plt.axvline(그려질 수직선의 x축값, 수직선의 y 최소값, 수직선의 y 최대값, color=색깔, linestyle=선종류, linewidth=선두께)

반응형

  3. 건조단열선 그리기

건조단열선을 그리는 과정은, 아주 간단한 수학적 스킬만 있으면 됩니다. 건조단열감률에 대한 기본적 지식을 잘 생각하면 어렵지 않습니다. 건조단열선은 1km당 기온이 10℃씩 감소하도록 그려지는 선입니다. 따라서 이렇게 되도록 1차 함수를 그리면 됩니다. 그러면

y=지상기온-10km/℃*고도

처럼 간단하게 식을 생각할 수 있습니다. 지상기온이 10도이고, 1km당 10도씩 감소하는 선을 생각하면, 간단한 1차함수를 생각해 볼 수 있습니다.

 

그런데 단열선도처럼 건조단열선이 여러개 필요하다면, 지상 기온이 10도인 1개인 단열선도 뿐 아니라 지상 기온이 0도 5도 10도 15도 20도 등 여러개의 건조단열선이 필요합니다. 그래서 아래와 같은 코드를 생가해 볼 수 있습니다.

x=np.arange(0,51,5)
for rx in x:
    h=np.arange(0,5,0.1)
    y=rx-a*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color=bcor)

np.arange는 너무 많이 사용하는 코드입니다. 0부터 51까지 숫자를 5 간격으로 뽑아내라는 소리입니다.

 

그 다음에 for문을 사용하였는데, 지상 기온을 0부터 50까지 5간격으로 뽑아내라는 의미가 됩니다.

y=rx-a*h에서 그 의미를 충분히 이해하셨을 것이라 생각합니다.

 

여기서 plt.plot에 x축과 y축 값을 뒤집어 넣었습니다. 계산 식은 y값이 온도이고, x값(h)은 고도인데, 실제 그래프에서 x축은 온도, y축이 고도이기 때문에 거꾸로 달아 놓았으니 참고하세요. 어찌되었든 튀어나오는 그래프는

이렇게 건조단열선을 그렸습니다. 그런데 수평선은 0~20도까지만 그렸기 때문에 모양이 좀 이상합니다. 저건 나중에 x축의 값 범위를 제한해 버리면 해결되니 크게 문제되진 않습니다. 어쨌든 다음번에는 습윤단열선을 그릴 차례입니다.

  3. 습윤단열선과 포화혼합비선 그리기

습윤단열선은 기온이 1km당 5℃씩 감소하는 형태로 그려집니다. 따라서 위 과정에서

y=지상기온-10km/℃*고도

에서 10을 5로 바꾸어 해당 코드를 추가하면 됩니다.

import matplotlib.pyplot as plt
import numpy as np
tempcontour=np.linspace(0,20,5)
heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)
for temp in tempcontour:
    plt.axvline(temp,0,20,color='gray', linestyle='--',linewidth=1)
x=np.arange(0,51,5)
for rx in x:
    h=np.arange(0,5,0.1)
    y=rx-10*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='red')
for sx in x:
    h=np.arange(0,5,0.1)
    y=sx-5*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='blue')
plt.show()

이 결과는

건조단열선과 습윤단열선을 그렸으니, 포화혼합비선(이슬점감률선)을 그릴 차례입니다. 이슬점 감률은 2℃/1km입니다. 따라서 1km당 2℃씩 감소하도록 지상의 각 기온별로 기울기가 일정한 선을 그리면 됩니다.이제 또 단순반복입니다. 아래 코드를 추가하면 됩니다.

import matplotlib.pyplot as plt
import numpy as np
tempcontour=np.linspace(0,20,5)
heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)
for temp in tempcontour:
    plt.axvline(temp,0,20,color='gray', linestyle='--',linewidth=1)
x=np.arange(0,51,5)
for rx in x:
    h=np.arange(0,5,0.1)
    y=rx-10*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='red')
for sx in x:
    h=np.arange(0,5,0.1)
    y=sx-5*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='blue')
for dx in x:
    h=np.arange(0,5,0.1)
    y=dx-2*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='blue')

처음에 수직선을 그릴 때 0℃부터 20℃까지를 염두하여, -기온은 생각조차 하지 않았습니다. 잘라줍시다. 또한 y축 범위도 0~3km까지만 제한하겠습니다. 그러면

이런식으로 그릴 수 있습니다. 이제 그래프에 이름만 집어넣으면 됩니다. 그래프를 잘라내고, x축 y축 이름까지 붙인 코드는

import matplotlib.pyplot as plt
import numpy as np
tempcontour=np.linspace(0,20,5)
heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)
for temp in tempcontour:
    plt.axvline(temp,0,20,color='gray', linestyle='--',linewidth=1)
x=np.arange(0,51,5)
for rx in x:
    h=np.arange(0,5,0.1)
    y=rx-10*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='red')
for sx in x:
    h=np.arange(0,5,0.1)
    y=sx-5*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='blue')
for dx in x:
    h=np.arange(0,5,0.1)
    y=dx-2*h
    plt.plot(y,h,linestyle='-.',linewidth=0.6, color='blue')
plt.ylim(0,3)
plt.xlim(0,20)
plt.xlabel('temp.(℃)')
plt.ylabel('height(km)')
plt.savefig("C:\\111\\tpdiagram.jpg",dpi=300)
plt.show()

  4. def를 이용해 반복되는 코드 제거하기

사실 이렇게만 해서 완성해도 되기는 합니다만, 굉장히 단순한 형태로 반복되는 코드는 보기좋지 않으며 비효율 적입니다. 실제 단열선도 그림을 그릴때 이렇게 코드 짜지 않았는데, 일부러 def라는 것을 소개하기 위해 이렇게 무식한 방법을 사용했습니다.

 

def라는 것은 일종의 함수를 정의하는 코드인데, 위 코드처럼 똑같은 코드가 계속 반복될 때 사용하면 매우 유용합니다. def의 기본적인 구조는 아래와 같습니다.

def function(a,b):
    return a+b
function(1,2)

function(a,b)라는 함수를 a+b를 계산하는 것으로 정의하였습니다. 그럼 앞으로 function(a,b)라고만 쓰면 무조건 a와 b를 더하게 됩니다. def는 기본적으로 return이라는 반환 코드와 함께 사용하고, 저렇게 해 두면 1,2가 계산되어 나옵니다.

 

def 다음에 for나 if같은 다른 명령어를 쓰면, return, 반환값은 돌아가고 있는 코드를 종료하고 빠져나가는 역할도 하게 됩니다. 이해는 어렵지 않습니다. return이라는 것 자체가 이제 결과를 토해내라 이런 의미이니 if나 for같은 반복 루프가 사용되는 경우 return에 의해 코드가 종료되고 반환값을 토해내게 됩니다.

 

여기서는 for rx, sx, dx와 같이 3개가 똑같은 구조로 반복되고 있습니다. 이걸 def를 이용해 함수로 정의하여 좀 더 간단하게 해 보겠습니다. 우선 반복되는 구조가 뭔지 잘 살펴보면

     for rx in x:
        h=np.arange(0,5,0.1)
        y=rx-a*h
        plt.plot(y,h,linestyle='-.',linewidth=0.6, color=cor)

 

요 형태가 반복됩니다. 변수 a가 있을 자리에 10,5,2 숫자만 다를 뿐 모두 같습니다. 또한 color='red' 또는 'green'과 같이 그래프 색깔만 빼고 모두 동일한 형태가 반복됩니다. 그럼 함수를 짜서 a와 color만 집어넣으면, 저 함수가 되도록 코드를 짜면 됩니다. 아래처럼요

def drawing(a,cor):
     for rx in x:
        h=np.arange(0,5,0.1)
        y=rx-a*h
        plt.plot(y,h,linestyle='-.',linewidth=0.6, color=cor)

그럼 이제 앞으로 drawing(10,'red')라고 치면 a 대신에 10이, cor 대신에 'red'가 들어가게 됩니다. 이렇게 코드를 다시 짜면

import matplotlib.pyplot as plt
import numpy as np
tempcontour=np.linspace(0,20,5)
heightcontour=np.linspace(0,5,6)
for height in heightcontour:
    plt.axhline(height,0,5,color='gray',linestyle='--',linewidth=1)
for temp in tempcontour:
    plt.axvline(temp,0,20,color='gray', linestyle='--',linewidth=1)
x=np.arange(0,51,5)
def drawing(a,cor):
     for rx in x:
        h=np.arange(0,5,0.1)
        y=rx-a*h
        plt.plot(y,h,linestyle='-.',linewidth=0.6, color=cor)
drawing(10,'red')
drawing(5,'blue')
drawing(2,'green')
plt.ylim(0,3)
plt.xlim(0,20)
plt.xlabel('temp.(℃)')
plt.ylabel('height(km)')
plt.savefig("C:\\111\\tpdiagram.jpg",dpi=300)
plt.show()

결과는 당연히 동일합니다.

 

만약 그래프의 x축과 y축 범위를 바꾸고 싶다면, 숫자를 조금만 바꾸면 됩니다.

여기까지 코드를 그냥 사용하실 수 있게, 올려 두겠습니다. 그래프만 필요하신 분들도 계실 것 같아 함께 올려두니 필요하신 분들은 다운로드하여 사용하세요.

tpdiagram.jpg
0.53MB
단열선도그리기2.ipynb
0.07MB

 

반응형

댓글