BNU-FZH

fengzhenhua@outlook.com

在 neovim 中使用 Lua

本文本最初来源是nvim-lua-guide,由于这段时间一直在学习使用Lua配置Neovim, 但是没有系统的教材,而这篇文章却恰好给了一个大致的框架,所以本文最初借用此文,待时机成熟再正式开始写作。

nvim-lua-guide 中文版简易教程

译者:Neovim Core Developer

:arrow_upper_left: (感觉太多太杂乱?使用 Github TOC 来浏览大纲!)

简介

Lua 作为 Neovim 中的一等语言的集成正在成为它的杀手级特性之一。然而,学习如何用 Lua 编写插件的教程数量并不像用 Vimscript 编写插件那样多。这是一种尝试,试图提供一些基本信息,让人们可以使用 Lua 编写 Neovim 插件。

阅读全文 »

2023年06月18日星期日多云北京市北京师范大学, 由于日常工作中需要面对大量 LaTeX 资料的编写工作,当数量大到一定量的时候在不同电脑上写作就会有不同步的问题,同时即使在同一台电脑上也会有找不到文件的可能性。同时为了不受限于网络,在很多时候 Github 并不能正确访问,所以一些需要的软件就需要通过 Gitlab 来间接的获取 ,但是每次都通过网页版操作太过麻烦,于是产生了通过脚本命令实现自动化的需要。于是决定规划编写两个主要的软件:

  1. labmgr.sh 管理本地的目录树:
    • 对于普通 LaTeX 文件,自动组织好目录并及时同步到 Gitlab
    • 一键列出所有同步的文件,自动调用 nvim 来编辑对应文档,最后保存并及时上传到对应仓库。
    • 运行时自动联网,检测 GitLab 仓库并检测更新情况,自动完成文件的更新
  2. plgmgr.sh 管理 nvim 插件:
    • 对于一些无法访问 Github 的情况,调用 GitLab api 将 github 上的源文件 fork 到 GitLab ,然后增加到 packer.vim 的插件控制目录,从 GitLab 上安装。
    • 同时考虑到插件的更新,本脚本增加 GitLab api 自动更新仓库的功能,这样就可以实现自动更新功能。
    • 再增加脚本自动备份功能,将本机配置好的 nvim 的lua 脚本及目录树一并同步到 GitLab 对应仓库, 这样就可以实现快速部署 nvim 到新电脑的目的。
  3. 参考文献:

2023年06月16日星期五晴北京市北京师范大学, 为了更好的编程和写Hexo日志,决定重新配置一下我的Neovim 。 之前由于课程紧张所以直接使用了vim的配置文件和插件,但是后来发现科技在进步,软件在升级,而Neovim 也越来越好用。于是决定使用其更加统一的接口来配置好我的Neovim, 同时本博客会逐步更新教程,力求达到让读都跟着一步一步的操作就可以完成操作。

限于时间关系,在本文的初步形态,借用一些网上的现成的文章,之后会逐步完善。近三天主要参考的网站分别为

  1. 菜鸟教程|Lua教程

  2. 从零开始配置vim(导读)

  3. 你需要知道的使用 lua 配置 neovim 的一切

  4. Snippets in Visual Studio Code

  5. Neovim主题

  6. NeoVim Builtin LSP的基本配置

  7. 行云流水般的NeoVim Builtin LSP操作

  8. Neovim|Diagnostics

  9. Neovim|Main

阅读全文 »

2023年06月12日星期一阴北京市北京师范大学, 高阶英语最先出了成绩,今将此次作业展示于此,里面的诗都是本人原创,翻译的诗歌是谢柏松老师的诗歌。

2023年06月08日星期四晴北京市北京师范大学, 发现今天上网的速度很慢,估计是DNS的问题。于是决定收录那些稳定快速的DNS服务器,逐步完善。未列出的服务器,请参考:免费公共 DNS 服务器大全

厂家 IPV4 IPV6
北京科技大学
清华大学TUNA
北京邮电大学
北京邮电大学
百度 180.76.76.76 2400:da00::6666
阿里 223.5.5.5 2400:3200::1
阿里 223.6.6.6 2400:3200:baba::1
腾讯 119.29.29.29 2402:4e00::
CNNIC 1.2.4.8 2001:dc7:1000::1
CNNIC 210.2.4.8 2001:dc7:1000::1
上交 2001:da8:8000:1:202:120:2:100
上交 2001:da8:8000:1:202:120:2:101
Yeti 中科院网络信息中心 2001:cc0:2fff:1::6666
Yeti 北京交通大学 2001:da8:205:2060::188
Yeti 清华大学 2001:da8:ff:305:20c:29ff:fe1f:a92a
1.1.1.1 2606:4700:4700::1111
1.0.0.1 2606:4700:4700::1001
101.101.101.101 2001:de4::101
101.102.103.104 2001:de4::102
4.2.2.1 4.2.2.2
4.2.2.3 4.2.2.4
4.2.2.5 4.2.2.6
9.9.9.9

注意:表中标注为绿色的DNS是我的当前环境下ping时响应速度在1ms以内的DNS, 所以这几个是在北京使用时极力推荐的, 其他的地址请自行ping后做出选择。

2023年 06月 19日 星期一 11:35:15 CST, 查询到英语成绩,顺利通过考试,感谢林老师,感谢外教,感谢北师大。本网站本是我准备复习考试之用,现作为Gist 组英语纪念.

林敦来老师正在给我们上课

2022-2023春季学期,英语考试考试时间:2023-06-10 13:30-16:10 考试地点:2023春期末考试,考场安排17周查询,具体考试安排尚未公布,请及时关注:北师大公共外语研究部

考场安排已经公布:

  1. 我本人: 教九楼/104/50

  2. 其他人考场安排: 公布版.xlsx

  3. 2023年06月10日 顺利完成考试

  4. 预计7月2日公布成绩,愿我们都顺利通过考试!

  5. 2023年 06月 19日 星期一 公布成绩,我们顺利通过了考试。

阅读全文 »

Project 15.32 Overcoming critical slowing down

Many of the original applications of Monte Carlo methods were done for systems of approximately one hundred particles and lattices of order 322 spins. It would be instructive to redo many of these applications with much better statistics and with larger system sizes. In the following, we discuss some additional recent developments, but we have omitted other important topics such as Brownian dynamics and umbrella sampling. More ideas for projects can be found in the references.

Energy-Monte Carlo Step The Spin Configuration The Spin Configuration The Spin Configuration The Spin Configuration

ocsd4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Author: 冯振华
# StudentNumber: 202221140015
# Verdion: V4.0
# Copyright © 2023 feng <feng@arch>
#
# Distributed under terms of the MIT license.

import numpy as np
import matplotlib.pyplot as plt

# Define the parameters
N = 20 # number of spins in each direction
J = -1 # coupling constant
beta = 1 # inverse temperature
nsteps = 1000 # number of Monte Carlo steps

# Initialize the spins randomly
spins = np.random.choice([-1, 1], size=(N, N))

# Define the energy function
def energy(spins):
return -J * (np.sum(spins[:-1,:] * spins[1:,:]) + np.sum(spins[:,:-1] * spins[:,1:])) \
- J * (np.sum(spins[0,:] * spins[-1,:]) + np.sum(spins[:,0] * spins[:,-1]))

# Define the Metropolis algorithm
def metropolis(spins, beta):
for i in range(N):
for j in range(N):
# Choose a random spin to flip
x, y = np.random.randint(0, N), np.random.randint(0, N)
# Calculate the energy difference
delta_E = 2 * J * spins[x, y] * \
(spins[(x+1)%N, y] + spins[(x-1)%N, y] + spins[x, (y+1)%N] + spins[x, (y-1)%N])
# Flip the spin with probability according to the Boltzmann factor
if np.random.uniform(0, 1) < np.exp(-beta * delta_E):
spins[x, y] = -spins[x, y]
return spins

# Run the Monte Carlo simulation
energies = []
for i in range(nsteps):
spins = metropolis(spins, beta)
energies.append(energy(spins))

# Calculate the average energy
E = np.mean(energies)

# Print the result
print(f"Average energy: {E:.4f}")

# Plot the energy as a function of Monte Carlo steps
plt.plot(energies)
plt.xlabel("Monte Carlo step")
plt.ylabel("Energy")
plt.show()

# Plot the spin configuration
plt.imshow(spins, cmap='binary')
plt.show()
ocsd3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2023 feng <feng@archlinux>
#
# Distributed under terms of the MIT license.
"""
作者:冯振华
学号:202221140015
版本:V4.1
日期:2023年05月20日
项目:Monte Carlo methods for Overcoming critical slowing down
"""
import numpy as np
import matplotlib.pyplot as plt

def initialize_spins(N):
"""
Initializes the spin lattice with random spins of -1 or +1
"""
return np.random.choice([-1, 1], size=(N, N))

def bond_probability(beta):
"""
Calculates probability of forming a bond between two neighboring spins
"""
return 1 - np.exp(-2*beta)

def update_spins(spins, beta):
"""
a single update of the spins using the Wolff algorithm
"""
N = spins.shape[0]
visited = np.zeros((N, N), dtype=bool)
seed = (np.random.randint(N), np.random.randint(N))
cluster_spins = [seed]
cluster_perimeter = [(seed[0], (seed[1]+1)%N), (seed[0], (seed[1]-1)%N),
((seed[0]+1)%N, seed[1]), ((seed[0]-1)%N, seed[1])]
while len(cluster_perimeter) > 0:
i, j = cluster_perimeter.pop()
if not visited[i,j] and np.random.random() < bond_probability(beta):
cluster_spins.append((i, j))
visited[i, j] = True
cluster_perimeter += [(i, (j+1)%N), (i, (j-1)%N),
((i+1)%N, j), ((i-1)%N, j)]
spins[tuple(zip(*cluster_spins))] *= -1
return spins

def calculate_energy(spins,J):
"""
Calculates the energy of the spin configuration
"""
N = spins.shape[0]
energy = 0
for i in range(N):
for j in range(N):
spin = spins[i, j]
neighbors = spins[(i+1)%N, j] + spins[i, (j+1)%N] + spins[(i-1)%N, j] + spins[i, (j-1)%N]
energy += 2*J*spin * neighbors
return energy

def run_simulation(N=20, J=-1,beta=1.0, num_steps=2000, num_measurements=100):
"""
Performs a full simulation of the Wolff algorithm on the spin lattice
"""
spins = initialize_spins(N)
energies = []
mags = []
for step in range(num_steps):
spins = update_spins(spins, beta)
if step % (num_steps // num_measurements) == 0:
energy = calculate_energy(spins,J)
mag = np.sum(spins)
energies.append(energy)
mags.append(mag)
return energies, mags

energies, mags = run_simulation(N=20,J=-1,beta=1.0, num_steps=100000, num_measurements=100)
#
# Calculate the average energy
E = np.mean(energies)
# Print the result
print(f"Average energy: {E:.4f}")
# Plot the energy as a function of Monte Carlo steps
plt.plot(energies)
plt.xlabel("Monte Carlo step")
plt.ylabel("Energy")
plt.show()

# Plot the spin configuration
plt.plot(mags)
plt.xlabel("Monte Carlo step")
plt.ylabel("Spin")
plt.show()
"""
To run the simulation, simply the `run_simulation` function with the desired parameters, such as `energies, mags = run_simulation(N=30,=1.0, num_steps=100000, num_measurements=100)`. This will simulate 100,000 Wolff updates on a 30x30 lattice at a temperature of 1. and take measurements of the energy and magnetization every 1,000 steps. The output is two arrays, `energies` and `mags`, that record the energy and magnetization at each measurement step. These arrays can be used to averages and variances to analyze the system properties.
"""

Project 15.32 Overcoming critical slowing down

2023年05月31日星期三多云北京市北京师范大学,由于物理高等计算方法课需要做一个大作业,同时还需要弄一个幻灯片来展示作业,所以又开始准备一个Beamer文档,但是长时间不用了,所以决定在本文逐步来完善Beamer使用中的一些技巧。

CTeXBeamer 中的数学字体

ctexbeamer 文档类中,默认会使用中文环境,包括对字体的设置。如果你在 ctexbeamer 中写公式,尤其是英文变量名时发现字体不美观或不符合数学排版习惯(比如用了中文字体嵌套英文),可以通过以下方法让公式中的英文字母和符号使用标准的数学英文字体(如 Computer ModernTimes)。

使用

1
2
3
4
5
6
7
8
9
10
11
12
\documentclass{ctexbeamer}
\usefonttheme[onlymath]{serif} % 让公式使用英文字体
\begin{document}

\begin{frame}
\frametitle{示例公式}
在公式 $E = mc^2$ 中,字母应为斜体。

多变量例子:$$f(x) = \int_{0}^{x} e^{-t^2} dt$$
\end{frame}

\end{document}

常用数学字体

标准数学公式通常使用衬线字体(serif),尤其是在学术出版物和专业文档中。在 LaTeX 中,默认的数学字体是 Computer Modern,这是一种衬线字体,由 Donald Knuth 设计,专门用于数学排版以保证最佳的可读性和美观性。 虽然衬线字体是最常见的选择,但也有其他选项:

  • 无衬线字体(sans-serif):有时在演示文稿或网页上会使用无衬线字体,因为它们看起来更加现代、简洁。然而,无衬线字体在表达复杂的数学关系时可能不如衬线字体清晰。
  • 手写风格字体:如 mathrsfs 包提供的手写体,常用于表示特定类型的集合或其他特殊用途。
  • 其他专业字体:例如 newtxmath、fourier、kpfonts 等,它们提供了不同的视觉效果以及额外的功能特性。

说明:

  • 如果你不加任何设置,在 ctexbeamer 中,LaTeX 可能会使用与中文兼容的字体族来渲染公式中的字符,导致英文字母不够“数学化”
  • Beamer 官方推荐的做法之一,适合绝大多数场合。
  • 此设置会让 只有数学环境 使用 serif 字体(即默认 LaTeX 的 Computer Modern 数学字体)。
  • 正文仍然使用 ctexbeamer 默认的中文字体,不影响排版风格。

文字对齐

在完成Beamer后发现,文字默认左对齐,我们需要的是分散对齐,解决方案是在导言区加上语句

1
2
\usepackage{ragged2e}
\justifying\let\raggedright\justifying

注意: 使用时请在调用主题前的调用这个宏包。

幻灯片比例

2023年09月05日星期二晴北京市北京师范大学,将幻灯片比例改为16:9

修改幻灯片比例为16:9
1
\documentclass[aspectratio=16:9]{ctexbeamer}

幻灯片的比例主要有: 16:10, 14:9, 1.41:1,5:4, 4:3(default), 3:2

2023年05月28日星期日多云北京市北京师范大学,对于形如

\[f(z)=z^n+\frac{a}{z^n}+c\]

的有理分式,在不动点处我求出了它的各参数满足的关系,发现只要解出方程

\[ x^n-\alpha x-\beta=0\]

那么这一类有理分式的所有不动点处的参数关系就完全确定了。但是当n在5次及5次以上时已经无法用通常的加减乘除及开根号来表达方程的根,其原因是很复杂的。所以对于超5次的情况,等到我期末考完试后再做研究,暂时考虑需要计算机做一个近似计算。对于高次方程不可解的原因,请参考: 如何证明五次及以上方程无根式解?|解方程系列5

2023年05月18日星期四多云北京市北京师范大学,顺利完成Python之美作业,由我完成了Linux版本,程国栋负责完成Windows版本。

设计思路

  1. 据Ip获取本地城市名
  2. 根据城市由高德地图获取纬度
  3. 由纬度计算本地的g值
  4. 输入初速度大小
  5. 输入阻尼大小
  6. 绘制最大水平位移与夹角的关系
  7. 绘制海平面存在风阻时的模拟图像
  8. 绘制海平面上100米处存在风阻时的模拟图像
  9. 绘制海平面上200米处存在风阻时的模拟图像

代码实现

nspp_linux.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
# Author: 冯振华 & 程国栋
# StudentNumber: 202221140015 & 202221140011
# Version: v2.2 for linux
# Linux: 冯振华
# Windows: 程国栋
# Date: 2023年05月18日星期四多云北京市北京师范大学
# Copyright © 2023 feng <feng@archlinux>
#
# !!注意:本脚本在linux编写,vim编辑器下
# :set ff #查看文件格式
# :set ff=dos #设置为dos格式
# :set ff=unix #设置为unix格式
# 如果不设置正确的格式地,运行程序会报错
#
import math
import matplotlib.pyplot as plt
import os
import requests
import json
# 输入初速度大小和空气阻力系数
v_0 = input("请输入初速度大小: ")
v_0 = float(v_0)
k = input("请输入空气阻力系数: ")
k = float(k)
# 获取本机Ip对应的地理位置
Ip_data=os.popen('curl -s cip.cc').readlines()
Ip_local=Ip_data[1].split(' ')
city=Ip_local[-1].strip()
# 从高德地图获取纬度
GaoDeKey = '79e3576b80e0b544d0d17dd643e4654e'
url = 'https://restapi.amap.com/v3/geocode/geo'
params = {'key': GaoDeKey,
'address': city}
res = requests.get(url,params)
jd = json.loads(res.text)
coords = jd['geocodes'][0]['location']
jd_value = coords.split(',')
latitude=float(jd_value[1])
latitude = latitude/180*math.pi
# 根据纬度计算本地的重力加速度g
g=9.7803*(1+0.005324*((math.sin(latitude))**2)-0.000005*((math.sin(2*latitude))**2))
# 计算最大水平位移和初速度与水平方向夹角的关系
def x_max(theta):
rad = math.radians(theta)
return (v_0**2* math.sin(2*rad)/ g)
angles = range(0, 91, 1)
x = [x_max(angle) for angle in angles]
#with the drag force
def simulate(v_1, theta,y_height):
theta = math.radians(theta)
v_x = v_1 * math.cos(theta)
v_y = v_1 * math.sin(theta)
x = 0
y = float(y_height)
t = 0
delta_t = 0.01
traj = [(x, y)]
while y >= 0:
a_x = -k * v_x ** 2 / (2 * v_1)
a_y = -g - k * v_y ** 2 / (2 * v_1)
v_x += a_x * delta_t
v_y += a_y * delta_t
x += v_x * delta_t
y += v_y * delta_t
t += delta_t
traj.append((x, y))
return traj
# 将各种情况集中于一张图上
plt.figure(figsize=(200,200),dpi=100)
plt.subplots_adjust(left=None,bottom=None,right=None,top=None,wspace=None,hspace=0.5)
plt.figure(1)
ax1 = plt.subplot(221)
ax1.margins(0.15)
ax1.plot(angles, x)
ax1.set_title("$\\theta$ with $x_{max}$ Free")
ax1.set_xlabel("$\\theta$(degrees)")
ax1.set_ylabel("$x_{max}$(meters)")
ax2 = plt.subplot(222)
ax2.margins(0.15)
angles = range(0, 91, 10)
for theta in angles:
traj = simulate(v_0, theta,0) # 地表
x_s = [t[0] for t in traj]
y_s = [t[1] for t in traj]
ax2.plot(x_s, y_s, label=f"${theta}^\circ$")
ax2.legend(loc="upper left")
ax2.set_title(f"Projectile Motion with Air Resistance ($v_0={v_0} m/s$)")
ax2.set_xlabel("Distance (meters)")
ax2.set_ylabel("Height (meters)")
ax3 = plt.subplot(223)
ax3.margins(0.15)
angles = range(0, 91, 10)
for theta in angles:
traj = simulate(v_0, theta,1) # 100m高塔
x_s = [t[0] for t in traj]
y_s = [t[1] for t in traj]
ax3.plot(x_s, y_s, label=f"${theta}^\circ$")
ax3.legend(loc="upper left")
ax3.set_title(f"Projectile Motion with Air Resistance ($v_0={v_0} m/s$)")
ax3.set_xlabel("Distance (meters)")
ax3.set_ylabel("Height (meters)")
ax4 = plt.subplot(224)
ax4.margins(0.15)
angles = range(0, 91, 10)
for theta in angles:
traj = simulate(v_0, theta,2) # 200m高塔
x_s = [t[0] for t in traj]
y_s = [t[1] for t in traj]
ax4.plot(x_s, y_s, label=f"${theta}^\circ$")
ax4.legend(loc="upper left")
ax4.set_title(f"Projectile Motion with Air Resistance ($v_0={v_0} m/s$)")
ax4.set_xlabel("Distance (meters)")
ax4.set_ylabel("Height (meters)")
plt.show()
nspp_windows.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
# Author: 冯振华 & 程国栋
# StudentNumber: 202221140015 & 202221140011
# Version: v2.2 for windows
# Linux: 冯振华
# Windows: 程国栋
# Date: 2023年05月18日星期四多云北京市北京师范大学
# Copyright © 2023 feng <feng@archlinux>
#
# !!注意:本脚本在linux编写,vim编辑器下
# :set ff #查看文件格式
# :set ff=dos #设置为dos格式
# :set ff=unix #设置为unix格式
# 如果不设置正确的格式地,运行程序会报错
#
import math
import numpy as np
import matplotlib.pyplot as plt
import requests
import json
from bs4 import BeautifulSoup
from scipy.integrate import odeint


# 输入初速度大小和空气阻力系数
v_0 = float(input("请输入初速度大小: "))
k = float(input("请输入空气阻力系数: "))


# 获取本机Ip对应的地理位置
url = 'http://www.cip.cc/'
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0'}
html = requests.get(url, headers=header) # 访问网址
bsObj = BeautifulSoup(html.content, 'lxml') # 使用lxml解析器
msg = bsObj.find('div', class_="data kq-well")
msg = [i for i in msg]
city = msg[1]


# 从高德地图获取纬度
GaoDeKey = '79e3576b80e0b544d0d17dd643e4654e'
url = 'https://restapi.amap.com/v3/geocode/geo'
params = {'key': GaoDeKey,
'address': city}
res = requests.get(url, params)
jd = json.loads(res.text)
coords = jd['geocodes'][0]['location']
jd_value = coords.split(',')
latitude = float(jd_value[1])
latitude = latitude/180*math.pi # 转换成弧度


# 根据纬度计算本地的重力加速度g
g = 9.7803*(1+0.005324*((math.sin(latitude))**2)-0.000005*((math.sin(2*latitude))**2))


def simulate(v_1, theta, y_height):
# 轨迹图
theta = math.radians(theta)
v_x0 = v_1 * math.cos(theta)
v_y0 = v_1 * math.sin(theta)

def motion1(w, t, k):
v_x, v_y = w
return[-k * v_x ** 2, -g - k * v_y ** 2]
t = np.linspace(0, 20, 300000)
track1 = odeint(motion1, (v_x0, v_y0), t, args=(k, ))
v_x1 = [i for i in track1[:, 0]]
v_y1 = [j for j in track1[:, 1] if j > 0]
v_x1 = v_x1[:len(v_y1)]
delta_t = (20 - 0) / 300000
i = 1
x = 0
y = y_height
y_list1 = [y]
x_list1 = [0]
while i < len(v_y1) - 1:
x += ((v_x1[i] + v_x1[i-1]) / 2) * delta_t
y += ((v_y1[i] + v_y1[i-1]) / 2) * delta_t
if y < 0:
break
x_list1.append(x)
y_list1.append(y)
i += 1

def motion2(w, t, k):
v_x, v_y = w
return[-k * v_x ** 2, -g + k * v_y ** 2]

track2 = odeint(motion2, (v_x1[-1], 0), t, args=(k, ))
v_x2 = [i for i in track2[:, 0]]
v_y2 = [j for j in track2[:, 1] if j < 0]
j = 1
x = x_list1[-1]
y = y_list1[-1]
y_list2 = [y]
x_list2 = [x]
while j < len(v_y2) - 1:
x += ((v_x2[j] + v_x2[j-1]) / 2) * delta_t
y += ((v_y2[j] + v_y2[j-1]) / 2) * delta_t
if y < 0:
break
x_list2.append(x)
y_list2.append(y)
j += 1
x_list = x_list1 + x_list2
y_list = y_list1 + y_list2
return x_list, y_list


def x_MaxTheta(v, height):
x_max = []
for angle in range(1, 91, 1):
x_list, y_list = simulate(v_1=v, theta=angle, y_height=height)
x_max.append(x_list[-1])
return x_max


heght = float(input('输入初始高度:'))
x_max = x_MaxTheta(v=v_0, height=heght)
plt.plot(range(1, 91, 1), x_max, 'g-')
plt.show()
x = 0
j = 1
for i in x_max:
j += 1
if i > x:
x = i
num = j - 1
print('当前初始条件下抛得最远的角度是{},最远距离是{}'.format(num, x))
print('输入要模拟的轨迹的抛出角度:')
a = float(input())
x, y = simulate(v_1=v_0, theta=a, y_height=heght)
plt.plot(x, y, 'r-')
plt.show()