├── .gitignore ├── LICENSE ├── PDF_OCR.py ├── README.md ├── TRANSLATE.py ├── TYPESET.py ├── carton ├── cmdshow.jpg ├── image-1.png ├── mathpix.jpg ├── show.jpg ├── 公式编号错误例.jpg └── 脚注错误例.jpg ├── doubao_AItalk.py ├── glossaries ├── HTS_glossary.csv ├── fusion_glossary.csv ├── fusion_glossary_distill.csv └── void.csv ├── main.py ├── requirements.txt ├── template.tex ├── translate_func2.py ├── translator_keys_void ├── baidu_keys.yaml ├── deepl_keys.yaml ├── doubao_keys.yaml ├── mathpix_keys.yaml ├── openai_keys.yaml └── tencent_keys.yaml ├── translators ├── __init__.py ├── baidu_translator.py ├── count_num_translator.py ├── deepl_translator.py ├── doubao_async_translator.py ├── doubao_translator.py ├── openai_translator.py ├── qwen_translator.py ├── tencent_translator.py └── test_translator.py ├── typeset_func2.py ├── 样例202502 ├── 471-1993-Ward.pdf ├── 471-1993-Ward.tex ├── [排版]471-1993-Ward.pdf ├── [排版]471-1993-Ward.tex ├── [翻译@deepL]471-1993-Ward - 副本.pdf ├── [翻译@deepL]471-1993-Ward - 副本.tex ├── [翻译@doubao]471-1993-Ward.pdf ├── [翻译@doubao]471-1993-Ward.tex ├── images │ ├── 2025_01_10_a0135324997886412d98g-3.jpg │ ├── 2025_01_10_a0135324997886412d98g-4.jpg │ ├── 2025_01_10_a0135324997886412d98g-5.jpg │ ├── 2025_01_10_a0135324997886412d98g-6(1).jpg │ ├── 2025_01_10_a0135324997886412d98g-6.jpg │ ├── 2025_01_10_a0135324997886412d98g-7.jpg │ ├── 2025_01_10_a0135324997886412d98g-8(1).jpg │ └── 2025_01_10_a0135324997886412d98g-8.jpg └── suffix.txt └── 设置.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | /translator_keys 2 | log*.txt 3 | pbar.txt 4 | doubao-contextid.yaml 5 | temp.py 6 | compilecmd.txt 7 | __pycache__ 8 | .vscode 9 | filepath.txt 10 | template.* 11 | !template.tex 12 | coverprocess.py -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Humphrey1997, DertahSama 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PDF_OCR.py: -------------------------------------------------------------------------------- 1 | import requests,logging 2 | import json,time,os,sys,yaml,datetime 3 | from tkinter import filedialog 4 | 5 | def ProgressBar1(prgss:float): 6 | progress=int(prgss*50) 7 | print("\r进度: %.1f %%: "%(prgss*100), "▋"*progress + "-"*(50-progress), end="") 8 | if prgss==1: 9 | print("done!") #100%了换个行 10 | sys.stdout.flush() 11 | time.sleep(0.001) 12 | 13 | def ProgressBar(now : int, alls : int): 14 | ''' 15 | 根据输入的当前值和总数值打印一个进度条。100%前不换行,下一次打印时将覆盖本行;100%后换行。 16 | :param now: 当前值 17 | :param alls: 总数值 18 | ''' 19 | progress=int(now/alls*50) 20 | print("\r进度: % 3d/% 3d: "%(now,alls), "▋"*progress + "-"*(50-progress), end="") 21 | if now==alls: 22 | print("done!") #100%了换个行 23 | sys.stdout.flush() 24 | time.sleep(0.001) 25 | 26 | 27 | def pdf_download(mypdfid,fname="sth"): 28 | # 因为任何原因,需要用pdf_id手动下载zip的情形 29 | # 2025-03-12 12-33-14 30 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 31 | for apidir in config["翻译设置"]["翻译APIkeys文件夹"]: 32 | if os.path.exists(apidir): 33 | print("[**] 读取API:"+apidir+'/mathpix_keys.yaml') 34 | break 35 | with open(apidir+'/mathpix_keys.yaml', 'r',encoding="utf8") as file: keys=yaml.load(file,Loader=yaml.Loader) 36 | myheader={ 37 | "app_id": keys["app_id"], 38 | "app_key": keys["app_key"] 39 | } 40 | 41 | while 1: 42 | r = requests.get("https://api.mathpix.com/v3/pdf/"+mypdfid,headers=myheader) 43 | rtext=json.loads(r.text) 44 | if "num_pages_completed" in rtext: 45 | ProgressBar(rtext["num_pages_completed"],rtext["num_pages"]) 46 | else: 47 | print("别急…",end="") 48 | 49 | if rtext["status"]=="completed": 50 | break 51 | time.sleep(0.5) 52 | 53 | toshow=f"耗费页数:{rtext['num_pages']},计费{rtext['num_pages']*0.005*7.2:,.3f}元" 54 | print(toshow+" 下载中……") 55 | logging.warning(toshow) 56 | 57 | # get LaTeX zip file 58 | savepath = os.path.abspath(config["PDF识别设置"]["保存路径"]) 59 | if not os.path.exists(savepath): 60 | os.makedirs(savepath) 61 | zipname:str = fname + ".zip" 62 | zipname =savepath + "\\" +zipname 63 | zipname1=zipname 64 | i=1 65 | while os.path.exists(zipname1): 66 | zipname1=zipname.replace(".zip",f"({i}).zip") 67 | i+=1 68 | zipname=zipname1 69 | 70 | url = "https://api.mathpix.com/v3/pdf/" + mypdfid + ".tex" 71 | response = requests.get(url, headers=myheader) 72 | 73 | with open(zipname, "wb") as f: 74 | f.write(response.content) 75 | 76 | print("已保存到:"+ zipname) 77 | return zipname 78 | 79 | 80 | 81 | 82 | def PDF_OCR(): 83 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 84 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 85 | logging.warning(".") 86 | logging.warning(".") 87 | 88 | 89 | 90 | print(">> 请打开一个PDF(点取消来处理本地的Mathpix zip)……") 91 | f_path = filedialog.askopenfilename(initialdir='./',filetypes=(('pdf files','*.pdf'),)) 92 | if not f_path: 93 | return None 94 | (fdir,fname)=os.path.split(f_path) 95 | fname,ext=os.path.splitext(fname) 96 | 97 | for apidir in config["翻译设置"]["翻译APIkeys文件夹"]: 98 | if os.path.exists(apidir): 99 | print("[**] 读取API于:"+os.path.abspath(apidir)+'/mathpix_keys.yaml') 100 | break 101 | with open(apidir+'/mathpix_keys.yaml', 'r',encoding="utf8") as file: keys=yaml.load(file,Loader=yaml.Loader) 102 | if not keys["app_id"]: 103 | print(f"[error] 你还没用填写Mathpix API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 104 | logging.error("[error]未找到Mathpix API keys") 105 | input("按回车退出……") 106 | exit() 107 | 108 | myheader={ 109 | "app_id": keys["app_id"], 110 | "app_key": keys["app_key"] 111 | } 112 | 113 | print(f_path) 114 | logging.warning(f"正在处理:{f_path}") 115 | 116 | prange=input(">> 请输入需要识别的页码范围,例如「1-3」or「3-」or「1,3,5」or「1-3,5」,不输入则全部上传: ") 117 | if not prange: 118 | prange="1-" 119 | 120 | tic=time.time() 121 | 122 | options = { 123 | "conversion_formats": {"tex.zip": True}, 124 | "math_inline_delimiters": ["$", "$"], 125 | # "math_display_delimiters": [r"\begin{align*}", r"\end{align*}"], 126 | "include_equation_tags": True, 127 | "rm_spaces": True, 128 | "page_ranges": prange, 129 | } 130 | 131 | 132 | 133 | print("正在上传……") 134 | r = requests.post("https://api.mathpix.com/v3/pdf", 135 | headers=myheader, 136 | data={ 137 | "options_json": json.dumps(options) 138 | }, 139 | files={ 140 | "file": open(f_path,"rb") 141 | } 142 | ) 143 | 144 | mypdfid=json.loads(r.text)["pdf_id"] 145 | 146 | print("上传成功,pdfid = " +mypdfid+ ",正在识别……") 147 | logging.warning("pdfid = "+mypdfid) 148 | 149 | 150 | while 1: 151 | r = requests.get("https://api.mathpix.com/v3/pdf/"+mypdfid,headers=myheader) 152 | rtext=json.loads(r.text) 153 | if "num_pages" in rtext: 154 | if "num_pages_completed" in rtext: 155 | ProgressBar(rtext["num_pages_completed"],rtext["num_pages"]) 156 | else: 157 | ProgressBar(0,rtext["num_pages"]) 158 | else: 159 | # ProgressBar1(rtext["percent_done"]/100) 160 | print("别急…",end="") 161 | sys.stdout.flush() 162 | 163 | if rtext["status"]=="completed": 164 | break 165 | time.sleep(0.5) 166 | 167 | toshow=f"耗费页数:{rtext['num_pages']},计费{rtext['num_pages']*0.005*7.2:,.3f}元" 168 | print(toshow+" 下载中……") 169 | logging.warning(toshow) 170 | 171 | # get LaTeX zip file 172 | savepath = os.path.abspath(config["PDF识别设置"]["保存路径"]) 173 | if not os.path.exists(savepath): 174 | os.makedirs(savepath) 175 | zipname:str = fname + ".zip" 176 | zipname =savepath + "\\" +zipname 177 | zipname1=zipname 178 | i=1 179 | while os.path.exists(zipname1): 180 | zipname1=zipname.replace(".zip",f"({i}).zip") 181 | i+=1 182 | zipname=zipname1 183 | 184 | url = "https://api.mathpix.com/v3/pdf/" + mypdfid + ".tex" 185 | response = requests.get(url, headers=myheader) 186 | 187 | with open(zipname, "wb") as f: 188 | f.write(response.content) 189 | 190 | toc=time.time() 191 | print(f"[*] 识别耗时 {toc-tic:.4f} s") 192 | logging.warning(f"识别耗时 {toc-tic:.4f} s") 193 | 194 | print("已保存到:"+ zipname) 195 | return zipname 196 | 197 | if __name__ == "__main__": 198 | if 1: 199 | PDF_OCR() 200 | else: 201 | # 手动下载已经识别完的latex zip 202 | pdf_id="2025_03_11_8a702bc870bdecdc07b3g" 203 | fname="(Jardin,S,2010)Computational Methods in Plasma Physics" 204 | pdf_download(pdf_id,fname) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paper_translator 2 | 这是一个利用服务商API自动全文翻译科技论文的python脚本,需借助Mathpix识别服务。 3 | 4 | 流程:英文PDF论文→Mathpix识别→翻译(腾讯百度deepL等)→中文PDF 5 | 6 | 改编自,这里稍加扩展改编后,打包成了exe,便于使用。 7 | 8 | ## 更新记录 9 | 2025-03-10 15-20-41 v5.0.2:bug修复 10 | 11 | 2025-03-08 15-09-55 v5.0:终于接入了Mathpix API,现在终于实现了**英文PDF进去、中文PDF出来**的效果,一条龙服务,不再需要自己手动处理PDF了。此外增加了日志功能、查询论文信息(形如 张三 (2021). 某某期刊. doi: 10.123456)的功能。 12 | 13 | 2025-03-03 13-04-54 v4.6.1:修复了列表环境(itemize,enumerate)翻译后异常的bug。 14 | 15 | 2025-02-28 09-22-15 v4.6:新增异步并行翻译器"doubao_async",并相应重写整个翻译流程为异步函数,翻译速度提升10倍以上。同时支持术语表。推荐使用5.1:"doubao_async"! 16 | 17 | 2025-02-24 18-08-41 v4.5.1:新增翻译器"doubao",这是字节自家的AI,相比字节部署的deepseek还支持缓存上下文,因此支持了术语表、AI总结全文和问答环节。推荐使用5:"doubao"! 18 | 19 | 2025-02-17 17-19-35 v4.5:翻译器"openai"改用了deepseek-v3。用的字节部署的版本,暂用我的试用API。 20 | 21 | 22 | ## 功能 23 | 还在硬啃英文文章吗?是时候全文翻译了!(该样例见`/样例`) 24 | 25 | ![show.jpg](carton/show.jpg) 26 | 27 | - 全自动:英文pdf进,中文pdf出 28 | - 全文翻译,中英对照 29 | - 术语表 30 | - 公式、图片、表格正确处理 31 | - 可自定义模板 32 | - 4.5.1 new! 支持AI问答(在`设置.yaml`中开启) 33 | 34 | ## 用法 35 | **准备工作**:获取mathpix和翻译器的API,放入`translator_keys/`中,详见下文;安装Latex。 36 | 37 | **准备工作**:获取mathpix和翻译器的API,放入`translator_keys/`中,详见下文;安装Latex。 38 | 39 | **准备工作**:获取mathpix和翻译器的API,放入`translator_keys/`中,详见下文;安装Latex。 40 | 41 | > 因重三! 42 | 43 | 运行`main.py`来运行本脚本。输入一个英文PDF,输出一个中文pdf。 44 | 45 | ![cmdshow.jpg](carton/cmdshow.jpg) 46 | 47 | 说明: 48 | - 输入的PDF最好是论文类的,排版复杂的图书效果大抵不好; 49 | - 如果想处理已下载到本地的Mathpix zip文件,在导入pdf时按取消即可 50 | 51 | ![alt text](carton/image-1.png) 52 | 53 | - 要识别的页码范围是指:应排除网站自动生成的头页、书籍目录、长篇无需翻译的东西(像博士论文的符号表、参考文献)等; 54 | - 强烈建议翻译前进行排版检查! 55 | - 默认选择的翻译器可在`设置.yaml`中调整; 56 | - 如自动编译PDF不成功,可手动打开`[翻译]*.tex`文件来自行检查编译 57 | 58 | ### 排版检查 59 | 60 | 为什么要停顿?因为**排版后的文档应该经过人工检查后,再运行翻译脚本进行翻译!** 61 | 62 | 这是因为mathpix机能所限,有些地方识别得不准确。**需要着重检查的地方已在程序中标出(标注 CHECK HERE)**。比如: 63 | 1. **跨页断段**。默认一页底部的文字会和下一页开头直接衔接,有时却没有衔接,导致错误。 64 | 2. **脚注**。本翻译器对脚注`\footnote`的兼容性较差,往往会出错,删去所有脚注,或以括号合并到正文中去。 65 | ![脚注错](carton/脚注错误例.jpg) 66 | 3. **行间公式被误认为行内公式**。行间公式如果顶到一行开头,会被mathpix误认为是一行正文,被识别成行内公式。需要手动改过来。 67 | 68 | **tips:** 69 | 1. 翻译API大都是付费的,如你想在正式翻译前试验一下,可在翻译器选择时选择`9:test`,你试一下就知道是怎么回事了。 70 | 2. 裹在latex命令里的文本(例如加粗、脚注等)一律保持原文不翻译,请在排版时注意。 71 | 72 | ### 配置 73 | 有两个东西可以配置: 74 | 75 | 1. 排版模板`template.tex`,特别是其中可以自定义中文对照的模式: 76 | - 重中文的四六开排版, 77 | - 中英文同重的五五开排版, 78 | - 仅中文或仅英文的排版。 79 | 2. 处理设置`设置.yaml`, 80 | - 设置存放着API keys的目录, 81 | - 将`"立即编译所得tex"`设为`1`,来自动将排版/翻译所得的tex文件编译成pdf,注意需要安装了Latex, 82 | - 某几个翻译器可以设置术语表 83 | - 其它杂项 84 | 85 | 86 | 87 | 默认模板中用思源宋体作为正文字体,因为latex自带宋体字库太小了。下载:[思源宋体 CN](https://github.com/adobe-fonts/source-han-serif/releases/download/2.002R/14_SourceHanSerifCN.zip)。 88 | 89 | #### 术语表 90 | 91 | 在`glossaries\`目录中。每个文件就是一个术语表。 92 | 93 | 术语表是csv文本文件,逗号前是英文,逗号后是中文。英文不能有重复。 94 | 95 | 目前只有`4:deepl`和`5:doubao`、`5.1:doubao_async`翻译器支持术语表,在`设置.yaml`中设置使用哪个术语表,一次只能用一个术语表。不用术语表的话指定为`void`即可。 96 | 97 | #### AI总结 98 | 99 | 选择翻译器`5:doubao`,且`设置.yaml`中设置`doubao-AI总结: 1`时,AI将完整理解整篇文章,并给出AI总结放在译文PDF的开头,并且你还以可以问AI问题。 100 | 101 | 受限于AI的上下文长度限制,不可用于长度超过20页的文章。 102 | 103 | ## 准备工作 104 | ### Mathpix服务 105 | 你需要开通Mathpix API来识别pdf 106 | - 网址: 107 | - 价格(2025.3):0.005美元/页PDF ,开通API付费20美元得30美元(6000页) 108 | - 将获取到的app_id与app_key填入`translator_keys/mathpix_keys.yaml`。 109 | 110 | 如果你暂时不想开通API,可以手动将pdf上传到 ,上传pdf,导出latex zip到本地,然后用本程序来处理。 111 | 112 | ![mathpix](carton/mathpix.jpg) 113 | 114 | ### 翻译服务 115 | 本脚本依靠公开的翻译服务API来工作,这里写好了几个服务的接口,这些API服务有付费的有免费的。 116 | 117 | 申请API方法参考这里,写得很详细: 118 | 119 | 申请到密钥后,在`translator_keys`文件夹中对应的文件加入自己的密钥即可: 120 | 121 | - 填入`doubao_keys.yaml`: 122 | - doubao (推荐doubao-1.5-pro,价格便宜效果好,还支持术语表(前缀缓存)) 123 | - 填入`openai_keys.yaml`: 124 | - deepseek(效果也好,但贵,v3价格是doubao1.5pro的4倍) 125 | - chatGPT (需付费和外国信用卡,甚贵,4o价格是doubao1.5pro的35倍) 126 | - 其它任何支持`OpenAI`接口调用的大模型API 127 | - 填入`deepl_keys.yaml`: 128 | - deepL (每月免费额度,但需外国信用卡,可某宝购买) 129 | - 填入`tencent_keys.yaml`: 130 | - 腾讯 (每月免费额度) 131 | - 填入`baidu_keys.yaml`: 132 | - 百度 (每月免费额度) 133 | 134 | 135 | >大模型(doubao、deepseek等)的翻译效果是最好的,推荐使用字节的火山方舟平台,服务稳定价格实惠。用doubao翻译一篇10页的论文,带术语表约0.05元。 136 | > 137 | >"openai"翻译器是通用API接口,各AI API平台都支持,字节的火山方舟也支持,可在该接口下使用deepseek、ChatGPT等。但是不支持术语表(前缀缓存)。 138 | > 139 | >deepL的翻译质量尚可,其免费API:DeepL API Free(每月50万字符)虽然国内不能正常开通,但可以在某宝黄牛买到,一般价10元/个。可以一次买多个,本脚本特地针对此开发了自动换弹夹的功能~ 140 | 141 | ### Latex编译pdf 142 | 这一点请自寻教程。对初学者来说,推荐texLive + TexStudio的组合: 143 | - texlive下载:https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/Images/ 144 | - texstudio下载:https://mirrors.tuna.tsinghua.edu.cn/github-release/texstudio-org/texstudio/LatestRelease/ 145 | 146 | > `设置.yaml`里`"立即编译所得tex"`的功能必须装了latex编译器(比如texlive)才能用 147 | 148 | 149 | 150 | ## 依赖与流程 151 | 需要安装的包: 152 | ``` 153 | pip install --upgrade requests pyyaml deepl openai volcengine-python-sdk[ark] 154 | ``` 155 | 156 | > **特别注意**:在安装字节跳动的volcengine-python-sdk[ark]前必须解除windows系统路径名长度的限制,否则会安装失败!打开一个有管理员权限的命令行窗口,运行: 157 | >``` 158 | >reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v "LongPathsEnabled" /t reg_dword /d 1 /f 159 | >``` 160 | 161 | 本脚本的运行原理分为三步: 162 | - 识别,运行`PDF_OCR.py`,上传pdf到mathpix来识别成latex文件。 163 | - 排版,运行`TYPESET.py`,用来将mathpix导出的latex文件初步处理。 164 | - 翻译,运行`TRANSLATE.py`,用来进行翻译并生成中英对照的latex文档。 165 | 166 | `main.py`就是顺序运行这三个脚本,并自动在中间停顿。日志记录于`log*.txt`。 167 | 168 | 脚本的主要流程是:疯狂地正则替换 169 | 1. 运行`TYPESET.py`, 170 | - 打开一个从mathpix上下载的tex文件,逐行读取; 171 | - 调用`typeset_func2.py`中的一系列函数,完成对标题作者摘要、正文、公式、图表的排版工作; 172 | - 在原文件同目录保存,并加前缀`[排版]`。 173 | 2. 运行`TRANSLATE.py`, 174 | - 打开上述前缀`[排版]`的文件,逐行读取; 175 | - 调用`translate_func2.py`中的一系列函数,让用户选择这次用哪个翻译器进行翻译,并读取`translators`文件夹里的对应翻译器; 176 | - 加载对应的API key和术语表,逐行对文档进行翻译; 177 | - 翻译完成后再做一些小装饰后, 在原文件同目录保存,并加前缀`[翻译]`。 178 | 179 | 额外小功能: 180 | - 可以直接运行`translate_func2.py`文件,是一个实时翻译器,你输入一句,它翻译一句。可用于测试或翻译检查时查漏补缺。 -------------------------------------------------------------------------------- /TRANSLATE.py: -------------------------------------------------------------------------------- 1 | import os,json,yaml,datetime,asyncio,logging 2 | from tkinter import filedialog 3 | from time import time 4 | 5 | def open_file(): 6 | # ========打开文件========= 7 | # with open('config.json',encoding='utf8') as f: 8 | # config=json.load(f) 9 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 10 | 11 | if config["翻译设置"]["处理filepath里储存的文件名"]: 12 | with open('filepath.txt', encoding='utf-8') as f: 13 | file=json.load(f) 14 | basedir=file["basedir"] 15 | filename=file["filename"] 16 | print("[*] 正在处理: "+basedir+r'/'+filename) 17 | else: 18 | print(">> 请打开从Mathpix导出的tex文档...") 19 | f_path = filedialog.askopenfilename(initialdir='./',filetypes=(('tex files','*.tex'),)) 20 | if not f_path: 21 | exit() 22 | (basedir,filename)=os.path.split(f_path) 23 | print("[*] 正在处理: "+basedir+r'/'+filename) 24 | 25 | with open('filepath.txt', 'w', encoding='utf-8') as f: 26 | json.dump({'basedir':basedir,'filename':filename},f,indent=4, ensure_ascii=False) 27 | 28 | return basedir,filename 29 | 30 | def TRANSLATE(basedir,filename): 31 | # with open('config.json',encoding='utf8') as f: config=json.load(f) 32 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 33 | 34 | input_file_path = basedir+'/[排版]'+filename 35 | output_file_path = basedir+'/[翻译]'+filename 36 | 37 | with open(input_file_path, 'r',encoding='utf-8') as file_2: 38 | tex_2 = file_2.readlines() 39 | with open(basedir+"/suffix.txt",'r',encoding='utf-8') as f: 40 | suffix=f.read() 41 | 42 | # ================== 加载翻译器 ================= 43 | import translate_func2 as tf 44 | from importlib import import_module 45 | 46 | translatorsdict={"1":"baidu","2":"tencent","3":"openai","4":"deepl","5":"doubao","5.1":"doubao_async","9":"test","0":"count_num"} 47 | if config["翻译设置"]["默认翻译器"] in ("1","2","3","4","5","5.1","9","0"): 48 | s=config["翻译设置"]["默认翻译器"] 49 | print(f"[**] 已默认选择 {s}:{translatorsdict[s]} 进行翻译……") 50 | else: 51 | s=input(">> 选择翻译器"+str(translatorsdict)+":") 52 | 53 | 54 | # s="4" 55 | # print("使用DeepL进行翻译……") 56 | 57 | # exec("import translators."+translatorsdict[s]+"_translator as tt ") # 感觉不太优雅,但是就这样吧! 58 | tt=import_module("translators."+translatorsdict[s]+"_translator") 59 | 60 | client=tt.create_client() 61 | 62 | 63 | # ================== 进行翻译 =================== 64 | tic=time() 65 | tex_3 = tex_2.copy() 66 | tex_3 = tf.translate_title(client,tex_3) 67 | # tex_3 = tf.translate_body(client,tex_3,suffix) 68 | tex_3 = asyncio.run( tf.translate_body1(client,tex_3,suffix) ) # 2025-02-27 20-28-43 升级为异步并发 2025-02-27 22-40-17 将list的翻译整合其中 69 | 70 | # tex_3 = tf.translate_list(client,tex_3) # 翻译itemize和enumerate环境 @231110新增 71 | # tex_3 = asyncio.run( tf.translate_list1(client,tex_3) ) # 2025-02-27 22-05-24 升级为异步并发 72 | 73 | # if client.translator_name in ("doubao",): 74 | # print(client.check_usage()) 75 | # print(f"[*] 消耗总token数:输入{client.tokenup-client.tokencache}(外加缓存{client.tokencache}),输出{client.tokendown},计费{round((client.tokenup-client.tokencache)*1e-6*0.8+client.tokendown*1e-6*2+client.tokencache*1e-6*0.16,3)}元") 76 | 77 | 78 | if client.translator_name == "doubao" and config["翻译设置"]["doubao-AI总结"] : 79 | import typeset_func2 as lf 80 | with open('template.tex', 'r',encoding='utf-8') as file_1: 81 | tex_template = file_1.readlines() 82 | format_AIsum = lf.get_format_AIsummary(tex_template) 83 | 84 | tex_3 = tf.AIsummary(client,tex_3,format_AIsum) 85 | 86 | # 用量检查 87 | if client.translator_name in ("deepl",): 88 | client.check_usage() 89 | if client.translator_name in ("doubao","doubao_async",): 90 | print(client.check_usage()) 91 | if client.translator_name == "count_num" : 92 | print(f"\n[*] 总字符数:{client.charnum},总token数(供参考):{client.tokennum}") 93 | 94 | 95 | tex_3=tf.post_decoration(tex_3) 96 | 97 | # ====== 保存 ====== 98 | basedir=basedir.replace("\\","/") 99 | output_file_path=output_file_path.replace("\\","/") 100 | 101 | if not client.translator_name == "count_char_num" : 102 | with open(output_file_path, 'w',encoding='utf-8') as file_3: 103 | file_3.write(' '.join(tex_3)) 104 | 105 | if config['翻译设置']['立即编译所得tex']: 106 | print("\n[*] 编译排版后的tex文件中……") 107 | 108 | cmd=f'cd /d \"{basedir}\" '\ 109 | '&& '\ 110 | f'xelatex.exe -synctex=1 -interaction=batchmode -halt-on-error '\ 111 | f'\"{output_file_path}\"' 112 | # ' > /dev/null' 113 | os.system(cmd) 114 | print("[*] 已编译为PDF文件\n") 115 | logging.warning("[翻译]已编译为PDF文件") 116 | os.startfile(output_file_path.replace(r'\\','/').replace('.tex','.pdf')) 117 | 118 | 119 | toc=time() 120 | print(f"[*] 翻译耗时 {toc-tic:.4f} s") 121 | logging.warning(f"翻译耗时 {toc-tic:.4f} s") 122 | 123 | print(">> 已保存到:"+output_file_path) 124 | # path1=output_file_path.replace('/','\\') 125 | # os.system(f'C:/Windows/explorer.exe /select, "{path1}"') 126 | 127 | # ====== doubao-AI问答 ====== 128 | if config["翻译设置"]["doubao-AI总结"] and client.translator_name == "doubao": 129 | a=input(">> 要就这篇文章展开AI问答吗?(y开始/回车退出):") 130 | print("[**] 退出后你仍可以运行「doubao_AItalk.py」来继续对话哦!") 131 | if a=="y": 132 | from doubao_AItalk import AItalk 133 | AItalk() 134 | 135 | # while 1: 136 | # print("") 137 | # askkk=input("(输入xxx来退出)>>") 138 | # if askkk=="xxx": break 139 | # with open(basedir+r"\AI问答.md","a+",encoding="utf8") as f: 140 | # f.writelines("\n\n.\n-------\n# "+datetime.datetime.now().strftime("%Y.%m.%d %H:%M:%S")+"\n") 141 | # f.writelines("> "+askkk+"\n\n") 142 | # rsp=client.asksth(askkk) 143 | # f.writelines(rsp) 144 | # print(rsp) 145 | 146 | 147 | 148 | # os.remove('filepath.txt') 149 | # os.remove('suffix.txt') 150 | 151 | if __name__=="__main__": 152 | basedir,filename=open_file() 153 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 154 | logging.warning(".") 155 | logging.warning(".") 156 | TRANSLATE(basedir,filename) 157 | -------------------------------------------------------------------------------- /TYPESET.py: -------------------------------------------------------------------------------- 1 | import typeset_func2 as lf 2 | from tkinter import filedialog 3 | import os,json,zipfile,yaml,logging,datetime 4 | 5 | def UnZIP(zip_name, realname=None, savedir=None): 6 | # 解压 7 | (pname,fname)=os.path.split(zip_name) 8 | if not savedir: savedir=pname 9 | if not realname: realname=os.path.splitext(fname)[0] 10 | 11 | with zipfile.ZipFile(zip_name) as f: 12 | given_name=f.namelist()[0].replace('/','') # mathpix给这个转换任务起的名字 13 | # print(given_name) 14 | f.extractall(savedir) 15 | 16 | realname1=realname 17 | i=1 18 | while os.path.exists(f'{savedir}/{realname1}'): 19 | realname1=realname+f"({i})" 20 | i+=1 21 | os.rename(f'{savedir}/{given_name}',f'{savedir}/{realname1}') 22 | os.rename(f'{savedir}/{realname1}/{given_name}.tex',f'{savedir}/{realname1}/{realname}.tex') 23 | 24 | # with open('filepath.txt', 'w', encoding='utf-8') as f: 25 | # json.dump({'basedir':f'{savedir}/{realname}','filename':f'{realname}.tex'},f,indent=4, ensure_ascii=False) 26 | 27 | return f'{savedir}/{realname1}',f'{realname}.tex' 28 | 29 | 30 | def open_file(): 31 | # ========打开文件========= 32 | # with open('config.json',encoding='utf8') as f: config=json.load(f) 33 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 34 | 35 | if config["排版设置"]["处理filepath里储存的文件名"]: 36 | print("[*] 正在处理filepath.txt里储存的文件名") 37 | with open('filepath.txt', 'r',encoding='utf-8') as f: 38 | file=json.load(f) 39 | basedir=file["basedir"] 40 | filename=file["filename"] 41 | print(basedir+r'/'+filename) 42 | else: 43 | # print("<< 请打开从Mathpix导出的tex文档...") 44 | # f_path = filedialog.askopenfilename(initialdir='./',filetypes=(('tex files','*.tex'),)) 45 | # if not f_path: 46 | # exit() 47 | # (basedir,filename)=os.path.split(f_path) 48 | 49 | 50 | print(">> 请打开从Mathpix导出的zip文档...") 51 | f_path = filedialog.askopenfilename(initialdir='./',filetypes=(('zip files','*.zip'),)) 52 | print(f_path) 53 | if not f_path: 54 | exit() 55 | 56 | basedir,filename=UnZIP(f_path) 57 | with open('filepath.txt', 'w', encoding='utf-8') as f: 58 | json.dump({'basedir':basedir,'filename':filename},f,indent=4, ensure_ascii=False) 59 | 60 | return basedir,filename 61 | 62 | def TYPESET(basedir,filename): 63 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 64 | with open('filepath.txt', 'w', encoding='utf-8') as f: 65 | json.dump({'basedir':basedir,'filename':filename},f,indent=4, ensure_ascii=False) 66 | # with open('config.json',encoding='utf8') as f: config=json.load(f) 67 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 68 | 69 | input_file_path = basedir+'/'+filename 70 | template_file_path = 'template.tex' 71 | typeset_file_path = basedir+'/[排版]'+filename 72 | 73 | # =======处理文件=========== 74 | print("[*] 开始排版预处理...") 75 | with open(input_file_path, 'r',encoding='utf-8') as file_0: 76 | tex_0 = file_0.readlines() 77 | with open(template_file_path, 'r',encoding='utf-8') as file_1: 78 | tex_template = file_1.readlines() 79 | 80 | format_figure = lf.get_format_figure(tex_template) 81 | format_equation = lf.get_format_equation(tex_template) 82 | format_table = lf.get_format_table(tex_template) 83 | tex_1 = lf.create_new_tex(tex_template) 84 | 85 | 86 | tex_1 = lf.modify_title(tex_0,tex_1) 87 | tex_1 = lf.modify_author(tex_0,tex_1) 88 | tex_1 = lf.modify_abstract(tex_0,tex_1) 89 | tex_1 = lf.modify_body(tex_0,tex_1) 90 | 91 | tex_1 = lf.modify_pre(tex_1) 92 | 93 | tex_1 = lf.modify_equation1(tex_1,format_equation) 94 | tex_1 = lf.modify_figure(tex_1,format_figure) 95 | tex_1 = lf.modify_table1(tex_1,format_table) 96 | 97 | 98 | if config['排版设置']['这是一本书']: 99 | tex_1 = lf.ItIsABook(tex_1) 100 | suffix='' 101 | else: 102 | tex_1, suffix=lf.get_suffix(tex_1) # 抽离参考文献 103 | with open(basedir+"/suffix.txt",'w',encoding='utf-8') as f: 104 | f.write(suffix) 105 | 106 | tex_1 = lf.modify_stitch(tex_1) # 检查并拼接浮动体前后的段落 107 | 108 | tex_1 = lf.modify_sectiontitle(tex_1) 109 | 110 | with open(typeset_file_path, 'w',encoding='utf-8') as file_2: 111 | file_2.write(' '.join(tex_1)) 112 | 113 | 114 | 115 | if config['排版设置']['立即编译所得tex']: 116 | print("\n[*] 编译排版后的tex文件中……\n") 117 | cmd=f'cd /d \"{basedir}\" '\ 118 | '&& '\ 119 | f'xelatex.exe -synctex=1 -interaction=batchmode -halt-on-error '\ 120 | f'\"{typeset_file_path}\"' 121 | os.system(cmd) 122 | logging.warning("[排版]已编译为PDF文件") 123 | 124 | 125 | print('\n>> 已保存到:'+typeset_file_path) 126 | path1=typeset_file_path.replace('/','\\') 127 | os.system(f'C:/Windows/explorer.exe /select, "{path1}"') 128 | print("\n>> 请编译排版后的tex进行检查,特别是:\n1. 公式是否正确,例如编号、多行;\n2. 跨页处是否错误地分了段;\n3. 脚注是否被混进了正文段落。") 129 | 130 | if __name__=="__main__": 131 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 132 | basedir,filename=open_file() 133 | logging.warning(".") 134 | logging.warning(".") 135 | TYPESET(basedir,filename) 136 | -------------------------------------------------------------------------------- /carton/cmdshow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/cmdshow.jpg -------------------------------------------------------------------------------- /carton/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/image-1.png -------------------------------------------------------------------------------- /carton/mathpix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/mathpix.jpg -------------------------------------------------------------------------------- /carton/show.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/show.jpg -------------------------------------------------------------------------------- /carton/公式编号错误例.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/公式编号错误例.jpg -------------------------------------------------------------------------------- /carton/脚注错误例.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/carton/脚注错误例.jpg -------------------------------------------------------------------------------- /doubao_AItalk.py: -------------------------------------------------------------------------------- 1 | # ===== 使用方法 ===== 2 | # 在用doubao翻译完一篇文章之后,直接运行本脚本即可。 3 | # - 拥有当前文章信息的会话的id保存在「doubao-contextid.yaml」中。 4 | # - 注意,会话是会超时过期的!超时时间在「设置.yaml」中,需要在翻译之前更改。 5 | 6 | from volcenginesdkarkruntime import Ark 7 | import yaml,datetime,json,sys 8 | 9 | 10 | def AItalk(): 11 | with open("doubao-contextid.yaml","r",encoding="utf8") as f: 12 | tt=yaml.load(f,Loader=yaml.Loader) 13 | with open('translator_keys/doubao_keys.yaml', 'r',encoding="utf8") as file: 14 | keys=yaml.load(file,Loader=yaml.Loader) 15 | with open('filepath.txt', encoding='utf-8') as f: 16 | file=json.load(f) 17 | basedir=file["basedir"] 18 | 19 | if tt["cachemode"] == "common_prefix": 20 | print("[*] 当前对话的缓存模式不支持上下文问答!") 21 | exit() 22 | 23 | print("[*] 当前会话将过期于:"+tt["expiretime"]+",每次对话会重置过期计时,请自行把握。") 24 | print("[*] 问答将保存到:"+basedir+r"\AI问答.md") 25 | 26 | myclient = Ark(api_key=keys["api_key"]) 27 | 28 | while 1: 29 | print("") 30 | askkk=input("(输入xxx来退出)>>") 31 | if askkk=="xxx": break 32 | rsp="" 33 | chat_stream = myclient.context.completions.create( 34 | # 指定上下文ID 35 | context_id=tt["contextid"], 36 | # 指定模型 37 | model=keys["model"], 38 | # 设置消息列表,包含一个用户角色的消息 39 | messages=[ 40 | {"role": "user", "content": askkk}, 41 | ], 42 | # 设置为流式 43 | stream=True, 44 | ) 45 | for chunk in chat_stream: 46 | if not chunk.choices: 47 | continue 48 | rsp += chunk.choices[0].delta.content 49 | print(chunk.choices[0].delta.content,end="") 50 | sys.stdout.flush() 51 | 52 | with open(basedir+r"\AI问答.md","a+",encoding="utf8") as f: 53 | f.writelines("\n\n.\n-------\n# "+datetime.datetime.now().strftime("%Y.%m.%d %H:%M:%S")+"\n") 54 | f.writelines("> "+askkk+"\n\n") 55 | f.writelines(rsp) 56 | 57 | print("") 58 | 59 | if __name__ == "__main__": 60 | AItalk() -------------------------------------------------------------------------------- /glossaries/HTS_glossary.csv: -------------------------------------------------------------------------------- 1 | tape,带材 2 | no-insulation,无绝缘 3 | noinsulator,无绝缘 4 | pancake,饼 5 | stack,堆 6 | azimuthal,绕制方向 7 | azimuthal current,绕制方向电流 8 | fidelity,精度 9 | copper cap,铜盖 10 | cowind,并绕带 11 | quench,失超 12 | joint,接头 13 | smeared,均一化 14 | voltage tapes,电压测量引线 15 | bus current,总线电流 16 | current ramp,电流爬升 17 | TFMC case,TFMC外壳 18 | teslameters,磁感应强度计 19 | campaign,实验活动 20 | pancake-to-pancake,饼间 21 | incubation,发展阶段 22 | open-circuit,断路 23 | programmed open-circuit test,受调控断路测试 24 | TFMC,TFMC 25 | thermal trajectory,热传导路径 26 | radial cut,"径向截断" 27 | radial-cut,"径向截断" 28 | tight-turn,小半径匝 29 | tight-turn high-B corner, 小半径匝高B转角处 -------------------------------------------------------------------------------- /glossaries/fusion_glossary.csv: -------------------------------------------------------------------------------- 1 | absolute magnetic well,绝对磁阱 2 | activation probes,活化探针 3 | adiabatic invariant,绝热不变量 4 | Alfvén instability,阿尔芬不稳定性 5 | Alfvén velocity,阿尔芬速度 6 | Alfvén wave,阿尔芬波 7 | Alfvén,阿尔芬 8 | ambipolar diffusion,双极性扩散 9 | ampereturn,安匝数 10 | analytic continuation,解析延拓 11 | aspect-ratio,环径比 12 | aspect ratio,环径比 13 | backscattering parametric instabilities,反向散射的参量不稳定性 14 | ballooning instability,气球模不稳定性 15 | ballooning mode,气球模 16 | BBGKY,BBGKY 17 | beam-plasma instability,束等离子体不稳定性 18 | beam-plasma interactions,束等离子体相互作用 19 | Bennett pinch,贝内特箍缩 20 | binary collision,二体碰撞 21 | binary mixtures,二元混合物 22 | blanket,包层 23 | Bohm shealh criterion,玻姆鞘层判据 24 | Bohm time,玻姆时间 25 | Bohm-Gross waves,玻姆格罗斯波 26 | Boltzmann,玻尔兹曼 27 | bootstrap current,自举电流 28 | bow shock,弓形激波 29 | Braginsky equations,布拉金斯基方程 30 | Brillouin scattering,布里渊散射 31 | Brownian motion,布朗运动 32 | bump-on-the-tail,尾巴有包 33 | canonical,正则 34 | charge exchange,电荷交换 35 | child-langmuir law,蔡尔德朗缪尔定律 - 36 | circulating particle,通行粒子 37 | collisional damping,碰撞阻尼 38 | collisionless damping,无碰撞阻尼 39 | complex argument,复宗量 40 | configuration,位形 41 | confinement scaling relations,约束定标关系 42 | confinement scaling,约束定标率 43 | confinement,约束 44 | contravariant,反变 45 | contravariant component,反变坐标分量 46 | contravariant form,反变形式 47 | contravariant vector,反变向量 48 | contravariant basis vector,反变基向量 49 | collision term,碰撞项 50 | collision integral,碰撞积分 51 | contour integral,环路积分 52 | convective cells,对流单元 53 | convective derivative,运流微商 54 | core plasma,芯部等离子体 55 | Cotton-Mouton effect,科顿–穆顿效应 56 | coulomb barrier,库仑势垒 57 | covariant,协变 58 | covariant component,协变坐标分量 59 | covariant form,协变形式 60 | covariant vector,协变向量 61 | covariant basis vector,协变基向量 62 | criteria,判据 63 | current penetration,电流穿透 64 | current-driven instability,电流驱动的不稳定性 65 | curvature drift,曲率漂移 66 | cutoff,截止 67 | cyclotron frequency,回旋频率 68 | cyclotron radiation,回旋辐射 69 | damping,阻尼 70 | debye length,德拜长度 71 | debye shielding,德拜屏蔽 72 | decay instability,衰变不稳定性 73 | decay of plasma,等离子体衰变 74 | delta function,delta函数 75 | density pedestal,密度台基 76 | destabilization,失稳 77 | device,装置 78 | diamagnetic current,抗磁性电流 79 | diamagnetic drift,抗磁性漂移 80 | diamagnetic loop,抗磁环 81 | diamagnetic,抗磁性 82 | displacement,位移 83 | differential operators,差分算子 84 | dispersion relation,色散关系 85 | dispersion surface,色散关系面 86 | disruption,破裂 87 | dissipative instability,耗散不稳定性 88 | dissipative trapped electron mode,耗散俘获电子模 89 | dissipative trapped particle instability,耗散俘获电子不稳定性 90 | divertor,偏滤器 91 | diverted plasma,偏滤器位形等离子体 92 | diverted shape,偏滤器位形形态 93 | double-plasma device,双等离子体(DP)装置 94 | double null,双零 95 | DP device,双等离子体(DP)装置 96 | Dreicer field,德雷瑟电场 97 | drift wave instability,漂移波不稳定性 98 | dynamic form factor,动力学形状因子 99 | edge localized mode,边缘局域模 100 | edge transport barrier,边缘输运垒 101 | eigenmode,本征模 102 | eigen value,本征值 103 | eigenvalue,本征值 104 | electron drift mode,电子漂移波模 105 | electron temperature gradient mode,电子温度梯度模 106 | electrostatic probe,静电探针 107 | equation of state,状态方程 108 | ergodicity,遍历性 109 | error field,误差场 110 | existence proofs,存在性证明 111 | external kink mode,外扭曲模 112 | extraordinary wave,非寻常波 113 | extraordinary mode,非寻常模 114 | Faraday rotation,法拉第旋转 115 | far-infrared laser,远红外激光器 116 | fast ignition,快点火 117 | Ficks law,菲克定律 118 | field null,零场 119 | field reversed configuration,场反位形 120 | figure of merit,性能指标 121 | finite-larmor-radius effect,有限拉莫尔半径效应 122 | finite conductivity,有限导电率 123 | first-wall,第一壁 124 | first moment,一阶矩 125 | fishbone instability,鱼骨模不稳定性 126 | fishbone mode,鱼骨模 127 | fishbone,鱼骨模 128 | fission-fusion reactors,裂变聚变反应堆 129 | FLR effect,有限拉莫尔半径效应 130 | fluctuation,涨落 131 | flux coordinates,磁面坐标 132 | flute instability,槽纹不稳定性 133 | flux function,磁面函数 134 | flux surface,磁面 135 | flux swing,最大伏秒数 136 | Fokker-Planck equation,福克-普朗克方程 137 | free energy,自由能 138 | Fried-Conte,弗里德-康特等离子体色散函数 139 | fuel injection,燃料注入 140 | Galilean invariance,伽利略不变性 141 | gas discharge,气体放电 142 | gas puffing,喷气 143 | geodesic acoustic mode,测地声模 144 | global,全域 145 | glow discharge,辉光放电 146 | grad-b drift,梯度B漂移 147 | Grad-Shafranov,Grad-Shafranov 148 | grazing collision,擦边碰撞 149 | Green's function,格林函数 150 | guiding center,导向中心 151 | gyro,回旋 152 | gyrofrequency,回旋频率 153 | gyrophase,回旋相位 154 | gyrokinetics,回旋动理学 155 | gyro-averaged kinetic equations,回旋平均动理学方程 156 | gyro-kinetic equation,回旋动理学方程 157 | gyroperiod,回旋周期 158 | halo current,晕电流 159 | H mode,H模 160 | H-mode,H模 161 | H function,H函数 162 | H theorem,H定理 163 | Hamiltonian,哈密顿量 164 | harris instability,哈里斯不稳定性 165 | heat flow equation,热流方程 166 | hermite,厄米 167 | higher moment,高阶矩 168 | hohlraum,黑腔 169 | hybrid frequency,杂化频率 170 | hydromagnetic equilibrium,磁流体力学平衡 171 | hydromagnetic wave,磁流体波 172 | impact parameter,碰撞参量 173 | impurity,杂质 174 | infernal mode,诡模 175 | inner-wall-limited,内壁限制器位形 176 | integrand,被积函数 177 | inter-molecular potential,分子间势 178 | interchange instability,交换不稳定性 179 | internal energy,内能 180 | internal transport barrier,内部输运垒 181 | internal kink,内扭曲模 182 | inverse bremsstrahlung,逆轫致吸收 183 | in-vessel,腔室内的 184 | ioffe bars,约飞棒 185 | ion temperature gradient mode,离子温度梯度模 186 | Kadomtsev model,Kadomtsev模型 187 | Kadomtsev-Nedospasov instability,Kadomtsev-Nedospasov不稳定性 188 | kinetic instability,动力不稳定性 189 | kinetic diagnostics,动力诊断 190 | kinetic equilibrium,动力平衡 191 | kineitc measurements,动力诊断 192 | kinetic profile,动力剖面 193 | kinetic,动理学 194 | Kinetic energy,动能 195 | kink,扭曲模 196 | kink mode,扭曲模 197 | kink instability,扭曲模不稳定性 198 | krook collision term,克罗克碰撞项 199 | Kruskal-Shafranov limit,Kruskal-Shafranov极限 200 | L mode,L模 201 | L-mode,L模 202 | Landau damping,朗道阻尼 203 | Langmuir waves,朗缪尔波 204 | Langmuirs paradox,朗缪尔佯谬 205 | Larmor gyration,拉莫尔回转 206 | Larmor radius,拉莫尔半径 207 | last closed flux surface,最外闭合磁面 208 | LCFS,最外闭合磁面 209 | Lawson criterion,劳逊判据 210 | left-hand cutoff,左旋截止 211 | lemniscoid,双扭形 212 | levitated dipole,悬浮偶极场 213 | Liouville,刘维尔 214 | local,局域 215 | Loschmidt number,洛施密特常数 216 | loss cone instability,损失锥不稳定性 217 | loss cone,损失锥 218 | lower hybrid,下杂化 219 | lower hybrid frequency,下杂化频率 220 | lower hybrid heating,低杂波加热 221 | lower hybrid wave,低杂波 222 | lumped parameter,集总参数 223 | magnetic beach,磁滩 224 | magnetic configuration,磁场位形 225 | magnetic island,磁岛 226 | magnetic mirror,磁镜 227 | magnetic moment,磁矩 228 | magnetic reconnection,磁重联 229 | magnetic surface,磁面 230 | magnetic trap,磁阱 231 | magnetic well,磁阱 232 | magnetoacoustic waves,磁声波 233 | magnetohydrodynamic,磁流体力学 234 | major disruption,大破裂 235 | major radius,大半径 236 | marginally,临界 237 | maxwellian distribution,麦克斯韦分布 238 | mean free path,平均自由程 239 | merging-compression,融合压缩 240 | mergingcompression,融合压缩 241 | microtearing mode,微撕裂模 242 | micro-instability,微观不稳定性 243 | micro instability,微观不稳定性 244 | microinstability,微观不稳定性 245 | microturbulence,微湍流 246 | micro turbulence,微湍流 247 | minor disruption,小破裂 248 | minor radius,小半径 249 | Mirnov instability,米尔诺夫不稳定性 250 | mirror effect,磁镜效应 251 | mirror instability,磁镜不稳定性 252 | modulational instability,调制不稳定性 253 | moment equation,矩方程 254 | navier-stokes equation,纳维-斯托克斯方程 255 | negative triangularity,反三角形变 256 | neoclassical diffusion,新经典扩散 257 | neoclassical,新经典 258 | nonlinear landau damping,非线性朗道阻尼 259 | nonlocal,非局域 260 | number density,数密度 261 | transport,输运 262 | transportation,输运 263 | object,对象 264 | ordinary wave,寻常波 265 | ordinary mode,寻常模 266 | overdense,过临界密度 267 | oscillating two-stream parametric instabilities,振荡双流的参量不稳定性 268 | parametric decay instability,参量衰变不稳定性 269 | parametric decay parametric instabilities,参量衰变的参量不稳定性 270 | parametric instabilities,参量不稳定性 271 | parametric instability,参量不稳定性 272 | partial integration,分部积分 273 | partition function,配分函数 274 | partial derivative,偏导数 275 | partial time derivative,时间偏导数 276 | passing particle,通行粒子 277 | pedestal,台基 278 | pellet,弹丸 279 | perturbation,扰动 280 | peaked pressure profile,峰化压强剖面 281 | peaked current profile,峰化电流剖面 282 | Pfirsch-Schlüter,Pfirsch-Schlüter 283 | phase-space trajectories,相空间轨迹 284 | pinch,箍缩 285 | phase velocity,相速度 286 | physical picture,物理图像 287 | plasma dispersion function,等离子体色散函数 288 | plasma parameter,等离子体参量 289 | plasma,等离子体 290 | polarization drift,极化漂移 291 | poloidal,极向 292 | poloidal field,极向场 293 | ponderomotive,有质动力 294 | ponderomotive force,有质动力 295 | ponderomotive effect,有质动力效应 296 | positive triangularity,正三角形变 297 | poynting's theorem,坡印廷定理 298 | power series,幂级数 299 | presheath,预鞘 300 | pressure pedestal,压强台基 301 | profile,剖面 302 | puff,吹气 303 | q-profile,q剖面 304 | quasi-interchange model,准交换模 305 | quasilinear,准线性 306 | quench,猝灭 307 | ramp phase stability,上升相稳定性 308 | ramps up,电流爬升 309 | rate of strain tensor,应变率张量 310 | ray tracing,光线追踪 311 | Rayleigh-Taylor instability,瑞利-泰勒不稳定性 312 | reactive instability,正反馈不稳定性 313 | recombination,复合 314 | reconnection,重联 315 | relaxation time,弛豫时间 316 | relaxation,弛豫 317 | resistive wall mode,电阻壁模 318 | resistive ballooning mode,电阻性气球模 319 | resistive instability,电阻性不稳定性 320 | reversed field pinch,反场箍缩 321 | right-hand cutoff,右旋截止 322 | ripple transport,纹波输运 323 | rotational transform angle,旋转变换角 324 | robust,稳健 325 | robustness,稳健性 326 | runaway electrons,逃逸电子 327 | runaway,逃逸 328 | safety factor,安全因子 329 | Sagdeev potential,Sagdeev势 330 | sawtooth,锯齿模 331 | scenario,运行模式 332 | scrape-off,刮削 333 | scrape-off layer,刮削层 334 | screw pinch,螺旋箍缩 335 | Scyllac,赛拉克装置 336 | second moment,二阶矩 337 | second regime,第二稳定区 338 | separatrix,分界点 339 | Shafranov shift,Shafranov位移 340 | shear Alfvén wave,剪切阿尔芬波 341 | shear,剪切 342 | sheared flow,剪切流 343 | shock waves,激波 344 | shot,炮 345 | shperomak,球马克 346 | single null,单零 347 | skin depth,趋肤深度 348 | skin current,趋肤电流 349 | slab model,平板位形 350 | soliton,孤波子 351 | species,组份 352 | spherical tokamak,球形托卡马克 353 | spheromak,球马克 354 | spheroid,球形 355 | Spitzer resistivity,斯必泽电阻率 356 | stability limit,稳定性极限 357 | stray field,杂散场 358 | position stabilisation,位置致稳 359 | stellarator,仿星器 360 | stimulated Brillouin scattering parametric instabilities,受激布里渊散射的参量不稳定性 361 | stimulated Brillouin scattering,受激布里渊散射 362 | stimulated Raman scattering,受激拉曼散射 363 | streaming instability,川流不稳定性 364 | stress tensor,应力张量 365 | Stringer diagrams,斯特林格图 366 | surface quantity,磁面量 367 | synchrotron radiation,同步辐射 368 | Taylor relaxation,泰勒弛豫 369 | tearing mode,撕裂模 370 | tensor,张量 371 | threshold of parametric instabilities,参量不稳定性的阈值 372 | tomography,层析成像 373 | toroidal alfvén eigenmode,环向阿尔芬本征模 374 | toroidal electron drift mode,环向电子漂移模 375 | toroidal field,环向场 376 | toroidal pinch,环形箍缩 377 | torsional alfvén wave,扭曲阿尔芬波 378 | trapped electrons,俘获电子 379 | trapped particle instability,俘获粒子不稳定性 380 | trapped,俘获 381 | trapped-particle instabilities,俘获粒子不稳定性 382 | triangularity,三角形变 383 | tritium inventory,氚滞留 384 | Trivelpiece-Gould curves,特里维尔皮斯-古尔德曲线 385 | Troyon scaling,Troyon定标率 386 | Troyon,Troyon 387 | truncate,截断 388 | tunneling,隧穿 389 | two-component torus,双组分环 390 | two-stream instability,双流不稳定性 391 | underdense,次临界密度 392 | untrapped particle,通行粒子 393 | upper hybrid,上杂化 394 | upper hybrid frequency,上杂化频率 395 | upper hybrid oscillations,上杂化振荡 396 | upper hybrid wave,上杂波 397 | vacuum vessel current,真空室壁电流 398 | Van Allen belts,范艾伦带 399 | Van Kampen mode,范坎彭模 400 | vertical instability,垂直不稳定性 401 | vessel,腔体 402 | virial theorem,位力定理 403 | Vlasov equation,弗拉索夫方程 404 | wakefield accelaration,尾场加速 405 | Ware pinch,韦尔箍缩 406 | water-bag model,水袋模型 407 | whistler,哨声 408 | whistler wave,哨声波 409 | yin-yang coil,阴阳线圈 410 | zonal flow,带状流 411 | z-pinch,Z箍缩 412 | zeroth moment,零阶矩 -------------------------------------------------------------------------------- /glossaries/fusion_glossary_distill.csv: -------------------------------------------------------------------------------- 1 | activation probes,活化探针 2 | adiabatic invariant,绝热不变量 3 | Alfvén,阿尔芬 4 | ambipolar diffusion,双极性扩散 5 | ampereturn,安匝数 6 | aspect-ratio,环径比 7 | aspect ratio,环径比 8 | backscattering parametric instabilities,反向散射的参量不稳定性 9 | ballooning instability,气球模不稳定性 10 | ballooning mode,气球模 11 | binary collision,二体碰撞 12 | binary mixtures,二元混合物 13 | blanket,包层 14 | Bohm shealh criterion,玻姆鞘层判据 15 | Bohm time,玻姆时间 16 | bootstrap current,自举电流 17 | bow shock,弓形激波 18 | bump-on-the-tail,尾巴有包 19 | canonical,正则 20 | charge exchange,电荷交换 21 | child-langmuir law,蔡尔德朗缪尔定律 - 22 | circulating particle,通行粒子 23 | complex argument,复宗量 24 | configuration,位形 25 | confinement scaling relations,约束定标关系 26 | confinement scaling,约束定标率 27 | confinement,约束 28 | collision term,碰撞项 29 | collision integral,碰撞积分 30 | convective cells,对流单元 31 | convective derivative,运流微商 32 | core plasma,芯部等离子体 33 | criteria,判据 34 | current penetration,电流穿透 35 | curvature drift,曲率漂移 36 | debye length,德拜长度 37 | debye shielding,德拜屏蔽 38 | decay instability,衰变不稳定性 39 | density pedestal,密度台基 40 | destabilization,失稳 41 | device,装置 42 | diamagnetic,抗磁 43 | dispersion surface,色散关系面 44 | disruption,破裂 45 | divertor,偏滤器 46 | diverted plasma,偏滤器位形等离子体 47 | diverted shape,偏滤器位形形态 48 | double-plasma device,双等离子体(DP)装置 49 | double null,双零 50 | DP device,双等离子体(DP)装置 51 | Dreicer field,德雷瑟电场 52 | drift wave instability,漂移波不稳定性 53 | dynamic form factor,动力学形状因子 54 | edge localized mode,边缘局域模 55 | edge transport barrier,边缘输运垒 56 | electron drift mode,电子漂移波模 57 | electron temperature gradient mode,电子温度梯度模 58 | electrostatic probe,静电探针 59 | equation of state,状态方程 60 | ergodicity,遍历性 61 | error field,误差场 62 | external kink mode,外扭曲模 63 | extraordinary wave,非寻常波 64 | extraordinary mode,非寻常模 65 | far-infrared laser,远红外激光器 66 | fast ignition,快点火 67 | Ficks law,菲克定律 68 | field null,零场 69 | field reversed configuration,场反位形 70 | figure of merit,性能指标 71 | finite-larmor-radius effect,有限拉莫尔半径效应 72 | finite conductivity,有限导电率 73 | first-wall,第一壁 74 | first moment,一阶矩 75 | fishbone,鱼骨模 76 | fission-fusion reactors,裂变聚变反应堆 77 | FLR effect,有限拉莫尔半径效应 78 | fluctuation,涨落 79 | flux coordinates,磁面坐标 80 | flute instability,槽纹不稳定性 81 | flux function,磁面函数 82 | flux surface,磁面 83 | flux swing,最大伏秒数 84 | Fried-Conte,弗里德-康特等离子体色散函数 85 | fuel injection,燃料注入 86 | Galilean invariance,伽利略不变性 87 | gas discharge,气体放电 88 | gas puffing,喷气 89 | geodesic acoustic mode,测地声模 90 | global,全域 91 | glow discharge,辉光放电 92 | grad-b drift,梯度B漂移 93 | Grad-Shafranov,Grad-Shafranov 94 | grazing collision,擦边碰撞 95 | guiding center,导向中心 96 | gyro,回旋 97 | gyrofrequency,回旋频率 98 | gyrophase,回旋相位 99 | gyrokinetics,回旋动理学 100 | gyro-averaged kinetic equations,回旋平均动理学方程 101 | gyroperiod,回旋周期 102 | halo current,晕电流 103 | H mode,H模 104 | H-mode,H模 105 | H function,H函数 106 | H theorem,H定理 107 | Hamiltonian,哈密顿量 108 | heat flow equation,热流方程 109 | hermite,厄米 110 | higher moment,高阶矩 111 | hohlraum,黑腔 112 | hybrid frequency,杂化频率 113 | hydromagnetic equilibrium,磁流体力学平衡 114 | hydromagnetic wave,磁流体波 115 | impact parameter,碰撞参量 116 | impurity,杂质 117 | infernal mode,诡模 118 | inner-wall-limited,内壁限制器位形 119 | interchange instability,交换不稳定性 120 | internal transport barrier,内部输运垒 121 | internal kink,内扭曲模 122 | inverse bremsstrahlung,逆轫致吸收 123 | in-vessel,腔室内的 124 | ioffe bars,约飞棒 125 | ion temperature gradient mode,离子温度梯度模 126 | kinetic instability,动力不稳定性 127 | kinetic diagnostics,动力诊断 128 | kinetic equilibrium,动力平衡 129 | kineitc measurements,动力诊断 130 | kinetic profile,动力剖面 131 | kinetic,动理学 132 | kinetic energy,动能 133 | kink,扭曲模 134 | kink mode,扭曲模 135 | Kruskal-Shafranov limit,Kruskal-Shafranov极限 136 | L mode,L模 137 | L-mode,L模 138 | Landau,朗道 139 | Langmuir waves,朗缪尔波 140 | Langmuirs paradox,朗缪尔佯谬 141 | Larmor gyration,拉莫尔回转 142 | Larmor radius,拉莫尔半径 143 | last closed flux surface,最外闭合磁面 144 | LCFS,最外闭合磁面 145 | Lawson criterion,劳逊判据 146 | left-hand cutoff,左旋截止 147 | lemniscoid,双扭形 148 | levitated dipole,悬浮偶极场 149 | local,局域 150 | loss cone,损失锥 151 | lower hybrid,下杂化 152 | lower hybrid frequency,下杂化频率 153 | lower hybrid heating,低杂波加热 154 | lower hybrid wave,低杂波 155 | lumped parameter,集总参数 156 | magnetic beach,磁滩 157 | magnetic configuration,磁场位形 158 | magnetic island,磁岛 159 | magnetic mirror,磁镜 160 | magnetic moment,磁矩 161 | magnetic surface,磁面 162 | magnetic trap,磁阱 163 | magnetic well,磁阱 164 | magnetoacoustic waves,磁声波 165 | magnetohydrodynamic,磁流体力学 166 | major disruption,大破裂 167 | major radius,大半径 168 | merging compression,融合压缩 169 | microtearing mode,微撕裂模 170 | micro instability,微观不稳定性 171 | micro turbulence,微湍流 172 | minor disruption,小破裂 173 | minor radius,小半径 174 | mirror effect,磁镜效应 175 | mirror instability,磁镜不稳定性 176 | modulational instability,调制不稳定性 177 | moment equation,矩方程 178 | navier-stokes equation,纳维-斯托克斯方程 179 | negative triangularity,反三角形变 180 | neoclassical diffusion,新经典扩散 181 | neoclassical,新经典 182 | nonlocal,非局域 183 | number density,数密度 184 | transport,输运 185 | transportation,输运 186 | ordinary wave,寻常波 187 | ordinary mode,寻常模 188 | overdense,过临界密度 189 | oscillating two-stream parametric instabilities,振荡双流的参量不稳定性 190 | parametric decay instability,参量衰变不稳定性 191 | parametric decay parametric instabilities,参量衰变的参量不稳定性 192 | parametric instability,参量不稳定性 193 | partition function,配分函数 194 | passing particle,通行粒子 195 | pedestal,台基 196 | pellet,弹丸 197 | perturbation,扰动 198 | peaked pressure profile,峰化压强剖面 199 | peaked current profile,峰化电流剖面 200 | Pfirsch-Schlüter,Pfirsch-Schlüter 201 | phase-space trajectories,相空间轨迹 202 | pinch,箍缩 203 | phase velocity,相速度 204 | physical picture,物理图像 205 | plasma dispersion function,等离子体色散函数 206 | plasma parameter,等离子体参量 207 | plasma,等离子体 208 | polarization drift,极化漂移 209 | poloidal,极向 210 | poloidal field,极向场 211 | ponderomotive,有质动力 212 | ponderomotive force,有质动力 213 | ponderomotive effect,有质动力效应 214 | positive triangularity,正三角形变 215 | power series,幂级数 216 | presheath,预鞘 217 | pressure pedestal,压强台基 218 | profile,剖面 219 | puff,吹气 220 | quasi-interchange model,准交换模 221 | quasilinear,准线性 222 | quench,猝灭 223 | ramp phase stability,上升阶段稳定性 224 | ramps up,电流爬升 225 | rate of strain tensor,应变率张量 226 | reactive instability,正反馈不稳定性 227 | reconnection,重联 228 | relaxation,弛豫 229 | resistive wall mode,电阻壁模 230 | resistive ballooning mode,电阻性气球模 231 | resistive instability,电阻性不稳定性 232 | reversed field pinch,反场箍缩 233 | right-hand cutoff,右旋截止 234 | ripple transport,纹波输运 235 | rotational transform angle,旋转变换角 236 | robust,稳健 237 | runaway,逃逸 238 | safety factor,安全因子 239 | Sagdeev potential,Sagdeev势 240 | sawtooth,锯齿模 241 | scenario,运行模式 242 | scrape-off,刮削 243 | scrape-off layer,刮削层 244 | screw pinch,螺旋箍缩 245 | Scyllac,赛拉克装置 246 | second moment,二阶矩 247 | second regime,第二稳定区 248 | separatrix,分界点 249 | Shafranov shift,Shafranov位移 250 | shear,剪切 251 | shock waves,激波 252 | shot,炮 253 | shperomak,球马克 254 | single null,单零 255 | skin depth,趋肤深度 256 | skin current,趋肤电流 257 | slab model,平板位形 258 | soliton,孤波子 259 | species,组份 260 | spherical tokamak,球形托卡马克 261 | spheromak,球马克 262 | spheroid,球形 263 | Spitzer resistivity,斯必泽电阻率 264 | stability limit,稳定性极限 265 | stray field,杂散场 266 | position stabilisation,位置致稳 267 | stellarator,仿星器 268 | streaming instability,川流不稳定性 269 | stress tensor,应力张量 270 | Stringer diagrams,斯特林格图 271 | surface quantity,磁面量 272 | synchrotron radiation,同步辐射 273 | Taylor relaxation,泰勒弛豫 274 | tearing mode,撕裂模 275 | tensor,张量 276 | tomography,层析成像 277 | toroidal alfvén eigenmode,环向阿尔芬本征模 278 | toroidal electron drift mode,环向电子漂移模 279 | toroidal field,环向场 280 | toroidal pinch,环形箍缩 281 | torsional alfvén wave,扭曲阿尔芬波 282 | trapped,俘获 283 | triangularity,三角形变 284 | tritium inventory,氚滞留 285 | Troyon scaling,Troyon定标率 286 | Troyon,Troyon 287 | two-component torus,双组分环 288 | two-stream instability,双流不稳定性 289 | underdense,次临界密度 290 | untrapped particle,通行粒子 291 | upper hybrid,上杂化 292 | vacuum vessel current,真空室壁电流 293 | Van Allen belts,范艾伦带 294 | Van Kampen mode,范坎彭模 295 | vessel,腔体 296 | virial theorem,位力定理 297 | wakefield accelaration,尾场加速 298 | Ware pinch,韦尔箍缩 299 | whistler,哨声 300 | whistler wave,哨声波 301 | yin-yang coil,阴阳线圈 302 | zonal flow,带状流 303 | z-pinch,Z箍缩 304 | zeroth moment,零阶矩 -------------------------------------------------------------------------------- /glossaries/void.csv: -------------------------------------------------------------------------------- 1 | void,空 -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from PDF_OCR import PDF_OCR 2 | from TYPESET import TYPESET,open_file,UnZIP 3 | from TRANSLATE import TRANSLATE 4 | 5 | # =====子包需要的依赖,pyinstaller需要 6 | import json,requests,random,openai,deepl,os 7 | from hashlib import md5 8 | from time import sleep,time 9 | 10 | # 2025-02-26 16-55-36 腾讯,不需要了 11 | # from tencentcloud.common import credential 12 | # from tencentcloud.common.profile.client_profile import ClientProfile 13 | # from tencentcloud.common.profile.http_profile import HttpProfile 14 | # from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException 15 | # from tencentcloud.tmt.v20180321 import tmt_client, models 16 | 17 | # ============================= 18 | print("这是一个利用服务商API自动全文翻译科技论文的python脚本。") 19 | print("输入一个英文论文PDF,输出一个译文PDF(需安装有Latex)。详见README。") 20 | print("——2025\n\n") 21 | 22 | # 2025-03-07 15-49-31 直接上传PDF 23 | texzipfile = PDF_OCR() 24 | 25 | if texzipfile: 26 | basedir,filename=UnZIP(texzipfile) 27 | else: # 打开本地zip文档 28 | print("未选择PDF……" ,end="") 29 | basedir,filename=open_file() 30 | 31 | TYPESET(basedir,filename) 32 | 33 | input("\n>> 检查无误后,按回车继续翻译...") 34 | 35 | TRANSLATE(basedir,filename) 36 | 37 | input("\n>> 按回车退出...") -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | deepl 2 | openai 3 | PyYAML 4 | Requests 5 | tencentcloud_sdk_python 6 | volcengine-python-sdk[ark] -------------------------------------------------------------------------------- /template.tex: -------------------------------------------------------------------------------- 1 | %---------------------------------------------------------------------------------------- 2 | % PACKAGES AND OTHER DOCUMENT CONFIGURATIONS 3 | %---------------------------------------------------------------------------------------- 4 | % \RequirePackage{silence} 5 | % \WarningsOff* 6 | % \batchmode 7 | % \documentclass[twoside,twocolumn]{article} 8 | \documentclass[utf8]{ctexart} 9 | \raggedbottom 10 | \usepackage{ctex} 11 | 12 | % ======== 通用设置 ======== 13 | 14 | % 页面布局 15 | \usepackage{geometry} 16 | \geometry{a4paper,top=3cm,bottom=3cm,inner=2cm,outer=2cm,marginparwidth=1.8cm} 17 | 18 | % 兼容utf8的字体设置 19 | %\setmainfont{CMU Serif} 20 | % \setCJKmainfont[ItalicFont={华文楷体}]{思源宋体 CN} 21 | % 思源宋体CN下载:https://github.com/adobe-fonts/source-han-serif/releases/download/2.002R/14_SourceHanSerifCN.zip 22 | 23 | % 必备数学套件 24 | \usepackage{amsmath,amsthm,amsfonts,amssymb} 25 | \usepackage{bm,bbm,upgreek} 26 | 27 | % 图片导入配置 28 | \usepackage{graphicx} 29 | \usepackage[export]{adjustbox} 30 | % 搜寻图片的路径 31 | \graphicspath{ {./images/} } 32 | 33 | % 图注设置 34 | \usepackage[small,labelfont=bf,up,up,margin=2em]{caption} % Custom captions under/above floats in tables or figures 35 | 36 | % 公式、图等的编号设置 37 | \usepackage{chngcntr} 38 | % \counterwithout{figure}{chapter} 39 | % \counterwithin{equation}{section} 40 | 41 | % 列表设置 42 | \usepackage{enumitem} % Customized lists 43 | \setlist[itemize]{itemsep=0pt} % Make itemize lists more compact 44 | \setlist[enumerate]{itemsep=0pt,parsep=0pt,label={[\arabic*]}} 45 | 46 | % 页眉页脚 47 | \usepackage{fancyhdr} 48 | \pagestyle{fancy} 49 | \fancyfoot[EL,OR]{\bfseries· \thepage ·} 50 | \fancyfoot[C]{} 51 | \renewcommand{\headrulewidth}{0pt} 52 | 53 | % 标题设置 54 | \usepackage{titling} % Customizing the title section 55 | % 摘要环境设置(book模板中无效) 56 | \usepackage{abstract} % Allows abstract customization 57 | \renewcommand{\abstractnamefont}{\normalfont\bfseries} % Set the "Abstract" text to bold 58 | \renewcommand{\abstracttextfont}{\normalfont\small\itshape} % Set the abstract itself to small italic text 59 | 60 | % 色彩 61 | \usepackage[svgnames]{xcolor} % added by Wenyin for color 62 | 63 | % 超链接设置 64 | \usepackage[ 65 | colorlinks, 66 | linkcolor=blue, 67 | bookmarksnumbered=true, 68 | bookmarksopen=true 69 | ]{hyperref} 70 | % unicode支持:pdf目录可以正确显示公式 71 | \hypersetup{unicode, psdextra} 72 | % PDF目录自定义 73 | \usepackage{bookmark} 74 | \bookmarksetup{ 75 | open, 76 | numbered, 77 | addtohook={% 78 | \ifnum\bookmarkget{level}=0 % chapter 79 | \bookmarksetup{bold,color=orange}% 80 | \fi 81 | } 82 | } 83 | 84 | 85 | 86 | 87 | % ======== 可选设置 ======== 88 | 89 | % for multiple references with dash 90 | \usepackage[noadjust]{cite} 91 | \renewcommand{\citedash}{--} % when \usepackage{cite} 92 | 93 | % 额外数学包 94 | \usepackage{mathrsfs} % for \mathscr 95 | \usepackage{mathtools} % for $\intertext{text}$ 96 | \usepackage{breqn} % 一个可以自动公式断行的公式环境,效果一般 97 | \usepackage{mhchem} %化学式 98 | \usepackage{esint} 99 | 100 | % 表格类 101 | \usepackage{booktabs} % Horizontal rules in tables 102 | %\usepackage{longtable} % 长表格 103 | %\usepackage{tabu} % 强大的表格包 104 | %\usepackage{supertabular} 105 | 106 | % 杂技 107 | \usepackage{multirow} % 多栏布局 108 | \usepackage{ulem} % 下划线 109 | \usepackage{tikz} % 绘图工具 110 | \usepackage{framed} % 文字加框 111 | \usepackage{setspace} % 设置行间距等 112 | \usepackage{minitoc} % 小目录 113 | %\usepackage{tcolorbox} % 多彩盒子工具,巨复杂 114 | %\tcbuselibrary{skins,breakable,raster} 115 | \usepackage{float} % 图片位置:H 116 | \usepackage{multicol} % 普通多栏布局 117 | \usepackage{changepage} % 页面布局调整 118 | 119 | % 多文件 120 | \usepackage{subfiles} 121 | 122 | %代码抄录 123 | \usepackage{shortvrb} 124 | % \MakeShortVerb|* %|*·|*可以直接原文抄录为texttt 125 | %\usepackage{listings} 126 | %\lstset{ 127 | % language=[LaTeX]TeX, %语言 128 | % backgroundcolor=\color{yellow!10}, %背景颜色 129 | % basicstyle=\small\ttfamily, %基本字格式 130 | % keywordstyle=\bfseries\color{purple}, %关键字格式 131 | % commentstyle=\color{gray}, %注释格式 132 | % numbers=left, %行号 133 | % numberstyle=\ttfamily\small, %行号格式 134 | % breaklines, %允许断行 135 | % frame=shadowbox, %外框线 136 | % escapeinside={<@}{@>}, %逃逸部分,还给Latex编码 137 | % lineskip=0pt, %行距 138 | % xleftmargin=0.05\linewidth, 139 | % xrightmargin=0.05\linewidth, %盒子宽度 140 | % morekeywords={rowfont} %更多自定义关键词 141 | % } 142 | 143 | 144 | 145 | % 段落分栏包,实现中英对照排版的核心工具 146 | \usepackage{paracol} 147 | \setlength{\columnseprule}{0.5pt} 148 | \setlength{\columnsep}{2em} 149 | \columnratio{0.4} 150 | 151 | 152 | % ======== 自定义命令 ======== 153 | 154 | % 数学自定义 155 | \newcommand{\vect}[1]{\mathbf{\boldsymbol{#1}}} % works for both English and Greek letters, but it does not work with mathtime pro lite fonts, see https://tex.stackexchange.com/questions/3535/bold-math-automatic-choice-between-mathbf-and-boldsymbol-for-latin-and-greek 156 | % \newcommand{\matr}[1]{\boldsymbol{\mathrm{#1}}} % \matrix is defined in LaTeX2e kernel 157 | \newcommand{\tens}[1]{\boldsymbol{\mathrm{#1}}} 158 | \newcommand\ii{\symup{i}} 159 | \newcommand\ee{\symup{e}} 160 | \newcommand\dd{\symup{d}} 161 | \newcommand\ppi{\symup{\pi}} %常用的正体字符:i,e,d,\pi 162 | 163 | \renewcommand{\paragraph}[1]{\textbf{#1}} 164 | % ====== 对照排版的设置 ====== 165 | 166 | % ===中英文对照排版,四六开=== 167 | \columnratio{0.4} 168 | \newcommand\mainskip{-5pt} 169 | \newcommand\enzhbox[2]{ 170 | \quad\par \begin{paracol}{2} \colseprulecolor{black} 171 | \begin{spacing}{1.0} 172 | \footnotesize #1 173 | \end{spacing} 174 | \switchcolumn[1] 175 | #2 176 | \end{paracol} \quad\par 177 | } 178 | 179 | % ===中英文对照排版,五五开=== 180 | %\columnratio{0.48} 181 | %\newcommand\mainskip{-5pt} 182 | %\newcommand\enzhbox[2]{ 183 | % \quad\par \begin{paracol}{2} \colseprulecolor{black} 184 | % \begin{spacing}{1.0} 185 | % \small #1 186 | % \end{spacing} 187 | % \switchcolumn[1] 188 | % #2 189 | % \end{paracol} \quad\par 190 | %} 191 | 192 | % === 仅英文(#1)/仅中文(#2) === 193 | % \newcommand\mainskip{5pt} 194 | % \newcommand\enzhbox[2]{#1} 195 | %\newcommand\enzhbox[2]{#2} 196 | 197 | %%编号层级表 198 | %%-1 part 199 | %%0 chapter 200 | %%1 section 201 | %%2 subsection 202 | %%3 subsubsection 203 | %%4 paragraph 204 | %%5 subparagraph 205 | % % 章节标题编号深度 206 | % \setcounter{secnumdepth}{3} 207 | % % 目录深度 208 | % \setcounter{tocdepth}{2} 209 | % % 小目录深度 210 | % \setcounter{minitocdepth}{3} 211 | % \renewcommand\mtctitle{本章目录} 212 | 213 | %---------------------------------------------------------------------------------------- 214 | % TITLE SECTION 215 | %---------------------------------------------------------------------------------------- 216 | 217 | % \setlength{\droptitle}{-4\baselineskip} % Move the title up 218 | 219 | % \pretitle{\begin{center}\Huge\bfseries} % Article title formatting 220 | % \posttitle{\end{center}} % Article title closing formatting 221 | \title{} 222 | \author{Author1, Author2} 223 | 224 | \newcommand\paperref{ == paperref here == } 225 | 226 | \date{\paperref} 227 | \fancyhead[C]{\small \paperref} 228 | \fancyhead[L,R]{} 229 | \renewcommand\headrulewidth{0.6pt} 230 | \renewcommand{\maketitlehookd}{% 231 | \begin{abstract} 232 | % ==abstract here 233 | \end{abstract} 234 | } 235 | 236 | %---------------------------------------------------------------------------------------- 237 | 238 | \begin{document} 239 | \begin{sloppypar} 240 | % \nonstopmode 241 | % \WarningsOff[latex] 242 | % 公式环境的一些设置 243 | \allowdisplaybreaks[3] 244 | \setlength{\abovedisplayskip}{-6pt} 245 | \setlength{\belowdisplayskip}{10pt} 246 | \setlength{\abovedisplayshortskip}{0pt} 247 | \setlength{\belowdisplayshortskip}{0pt} 248 | \setlength{\parskip}{\mainskip} 249 | 250 | % \setcounter{chapter}{3} 251 | \maketitle 252 | 253 | % ==document boby begins 254 | 255 | % ==document body here 256 | 257 | \setlength{\parskip}{0pt} \small % ==document body ends 258 | 259 | 260 | %---------------------------------------------------------------------------------------- 261 | \end{sloppypar} 262 | \begin{flushright} 263 | \vfill \footnotesize 264 | ——本翻译PDF由Paper_translator生成, \url{https://github.com/DertahSama/Paper_translator} 265 | \end{flushright} 266 | \end{document} 267 | 268 | 269 | 270 | 271 | % =========环境格式区=========== 272 | 273 | % ==figure format begins 274 | \begin{figure}[H] 275 | \centering 276 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{} 277 | \caption{} 278 | \label{} 279 | \end{figure} 280 | % ==figure format ends 281 | 282 | % ==equation format begins 283 | \begin{align} 284 | % ==here 285 | \end{align} 286 | % ==equation format ends 287 | 288 | 289 | % ==table format begins 290 | \begin{table}[H] 291 | \centering 292 | \caption{} 293 | \label{} 294 | \adjustbox{max width=\linewidth}{ 295 | 296 | % ==tabular here 297 | 298 | } 299 | \end{table} 300 | % ==table format ends 301 | 302 | % == AIsummary format begins 303 | 304 | {\centering \textbf{AI总结} \par} 305 | \begin{adjustwidth}{0.1\linewidth}{0.1\linewidth} \small \setlength{\parskip}{2pt} 306 | % == insert here 307 | \end{adjustwidth} \setlength{\parskip}{\mainskip} 308 | 309 | % == AIsummary format ends -------------------------------------------------------------------------------- /translate_func2.py: -------------------------------------------------------------------------------- 1 | """ 2 | 翻译器在translators文件夹中,通过修改下面import哪个文件来决定用那个翻译库。 3 | 这些翻译库都需要自备api。 4 | 支持的服务商: 5 | openai(chatGPT3.5),deepl,baidu,tencent 6 | """ 7 | 8 | # translatorsdict={"1":"baidu","2":"tencent","3":"openai","4":"deepl","5":"test","0":"count_char_num"} 9 | # s=input("<< 选择翻译器"+str(translatorsdict)+":") 10 | 11 | # # tt=__import__(translatorsdict[s]+"_translator") 12 | # exec("import translators."+translatorsdict[s]+"_translator as tt ") # 感觉不太优雅,但是就这样吧! 13 | # # from baidu_translator import * 14 | 15 | 16 | import re,sys,asyncio 17 | from time import sleep 18 | 19 | def FindFirst(pat: str, lst: list[str], flg: str=0) -> int: #找到字符串数组lst中第一次正则匹配到pat的索引位置 20 | ''' 21 | 找到字符串数组lst中第一次正则匹配到pat的序号。若未找到则返回None。 22 | :param pat: 正则匹配表达式 23 | :param lst: 元素为字符串的数组 24 | :param flg: 是`re.search()`的`flags`参数。默认为0,常用的是忽略大小写的`re.I` 25 | :return: 若找到,返回索引号;若未找到,返回None 26 | ''' 27 | try: 28 | return lst.index(next(filter(re.compile(pat,flags=flg).search,lst))) 29 | except StopIteration: # 一次也next不出来,说明没有 30 | return None 31 | 32 | 33 | def ProgressBar(now : int, alls : int): 34 | ''' 35 | 根据输入的当前值和总数值打印一个进度条。100%前不换行,下一次打印时将覆盖本行;100%后换行。 36 | :param now: 当前值 37 | :param alls: 总数值 38 | ''' 39 | progress=int(now/alls*50) 40 | print("\r进度: %d/%d: "%(now,alls), "▋"*progress + "-"*(50-progress), end="") 41 | if now==alls: 42 | print("done!") #100%了换个行 43 | sys.stdout.flush() 44 | sleep(0.001) 45 | 46 | def ProgressBar_par(N=[]): 47 | # 适用于各种并发的进度条 48 | if isinstance(N,int): 49 | with open("pbar.txt","w") as f: 50 | f.write(f"{N}\n") 51 | elif N==[]: 52 | with open("pbar.txt","r+") as f: 53 | c=f.readline() 54 | alls=int(c) 55 | 56 | now=f.readlines() 57 | f.write("1\n") 58 | now=len(now)+1 59 | 60 | progress=int(now/alls*50) 61 | print("\r并行进度: %d/%d: "%(now,alls), "▋"*progress + "-"*(50-progress), end="") 62 | if now==alls: 63 | print("done!") #100%了换个行 64 | sys.stdout.flush() 65 | sleep(0.001) 66 | else: 67 | raise Exception("要么输入总数N来初始化,要么什么都不输入来显示进度!") 68 | 69 | def translate_text(client, text: str) -> str: 70 | 71 | 72 | if not (client.translator_name in ("openai","doubao","doubao_aysnc")): # 用大模型的不用替换 73 | # 设置原文中要强制保持原样的部分 74 | to_reserve=[r'(?:\$.*?\$)', # 行内公式 75 | r'(?:\\cverb\|.*?\|)', 76 | r'\\\w+(?:\{.*?\})*', # 任意latex命令 77 | ] 78 | reserved_results = re.findall(r'(?:(?:' + '|'.join(to_reserve) + r') *)+' ,text) 79 | # print(inline_eqn_results) 80 | marker=lambda i: ' [x'+'%02d'%i+'] ' # 替换为保留符marker,例如[#03] 81 | # marker=lambda i: '【'+chr(0x4E00+i)+'】' # 替换为保留符marker,例如[#03] 82 | for i in range(len(reserved_results)): 83 | # inline_eqn=reserved_results[i] 84 | # marker='xx'+'%02d'%i # 把行内公式替换成标记,防止翻译时丢符号 85 | # marker='[#'+'%02d'%i+']' # 把行内公式替换成标记,防止翻译时丢符号 86 | text = text.replace(reserved_results[i],marker(i)) 87 | 88 | to_convert=[[r'\&',r'&'], 89 | [r'\%',r'%'], 90 | [r'\#',r'#']] 91 | for apair in to_convert: 92 | text = text.replace(apair[0],apair[1]) 93 | 94 | text = re.sub(r'(Chaps?|Secs?|Eqn?s?|Refs?|Figs?)\. ?(\(?\d+\)?)',r'\1\2',text,flags=re.IGNORECASE) # 把诸如「Sec. 3」变成「Sec3」,防止这个点被认成句号导致错误断句。 95 | 96 | if client.translator_name in ("doubao_async",): 97 | text_zh:str = asyncio.run(client.trans_text(text.strip())) 98 | else: 99 | text_zh:str = client.trans_text(text.strip()) 100 | 101 | 102 | 103 | text_zh = text_zh.replace('#','#').replace('{',r'{').replace('}',r'}') # 谁能想到deepl会随机把半角#替换成全角#??? 104 | 105 | for apair in to_convert: 106 | text_zh = text_zh.replace(apair[1],apair[0]) 107 | 108 | if not (client.translator_name in ("openai","doubao","doubao_aysnc")): # 用大模型的不用替换 109 | for i in range(len(reserved_results)): 110 | # inline_eqn=reserved_results[i] 111 | # marker='xx'+'%02d'%i 112 | text_zh = text_zh.replace(marker(i).strip(),reserved_results[i]) # 替换回来 113 | 114 | 115 | return client, text_zh 116 | 117 | 118 | 119 | 120 | def translate_title(client,tex_file): 121 | st = r'\\begin{abstract}' 122 | st1 = r'\\title\{(.*?)\}' 123 | print('[**] 翻译标题……') 124 | 125 | # client=tt.create_client() 126 | 127 | title_idx=FindFirst(st1,tex_file) 128 | if title_idx: 129 | title_en=re.search(st1,tex_file[title_idx]).group(1) 130 | client, title_zh=translate_text(client,title_en) 131 | tex_file[title_idx]=r'\title{'+title_zh+r'\\ \Large{'+title_en+'}}' 132 | print("标题:",title_zh) 133 | else: 134 | print("no title found!") 135 | 136 | # abstract_idx=FindFirst(st,tex_file) 137 | # if abstract_idx: 138 | # abstract_idx+=1 139 | # abstract_en = tex_file[abstract_idx] 140 | # client, abstract_zh = translate_text(client,abstract_en) 141 | # abstract_zh += '\n' 142 | # tex_file[abstract_idx] = r'{'+abstract_zh+r'}\\ \indent '+abstract_en 143 | # else: 144 | # print("no abstract found!") 145 | 146 | return tex_file 147 | 148 | 149 | async def taowa(client,line,sema): 150 | async with sema: 151 | 152 | to_convert=[[r'\&',r'&'], 153 | [r'\%',r'%'], 154 | [r'\#',r'#']] 155 | for apair in to_convert: 156 | line = line.replace(apair[0],apair[1]) 157 | 158 | rline = await client.trans_text(line) 159 | 160 | for apair in to_convert: 161 | rline = rline.replace(apair[1],apair[0]) 162 | 163 | ProgressBar_par() 164 | return rline 165 | 166 | 167 | async def translate_body1(client, tex_file :list[str], suffix:list[str]) -> list[str]: 168 | # 2025-02-27 19-39-55 改造为适应异步并发 169 | print('[**] 翻译正文……') 170 | start_idx=FindFirst("==document boby begins",tex_file) 171 | if not start_idx: 172 | start_idx=FindFirst(r"\\begin{document}",tex_file) 173 | end_idx=FindFirst("==document body ends",tex_file) 174 | if not end_idx: 175 | end_idx=FindFirst(r"\\end{document}",tex_file) 176 | tex_file[end_idx]='\n' 177 | tex_file.extend(['\n','\\end{document}\n']) 178 | 179 | flag = 0 180 | L = end_idx-start_idx+1 181 | 182 | # 把需要翻译的东西提取出来 183 | data_abst=[] # 摘要 184 | data_bulk=[] # 正文 185 | data_titl=[] # 章节标题 186 | data_capt=[] # 图注 187 | 188 | # ==== 摘要部分 ==== 189 | 190 | st = r'\\begin{abstract}' 191 | 192 | abstract_idx=FindFirst(st,tex_file) 193 | if abstract_idx: 194 | abstract_idx+=1 195 | abstract_en = tex_file[abstract_idx] 196 | data_abst.append([abstract_idx, abstract_en]) 197 | else: 198 | print("no abstract found!") 199 | 200 | 201 | # ==== 正文部分 ==== 202 | for line_idx in range(start_idx+1,end_idx): 203 | line = tex_file[line_idx].strip() 204 | if re.search(r"^ *%.*",line): # 注释行直接跳过 205 | continue 206 | 207 | flag += len(re.findall(r'\\begin{.*?}',line)) #子环境层数 208 | 209 | if flag==0 and len(line)>2: # 非子环境内 210 | searchobj=re.search(r'\\(part|chapter|section|subsection|subsubsection|paragraph)\*?\{(.*)\}',line) # 搜寻章节标题 211 | if searchobj: # 章节标题的处理 212 | titl_en=searchobj.group(2).strip() 213 | if len(titl_en)>2: # 长度达到最小限制3个字母,才翻译 214 | data_titl.append([line_idx, titl_en]) 215 | else: 216 | print(f"[**]警告:第{line_idx+start_idx-1}行的标题过短,可能有误,请检查。") 217 | 218 | elif re.search(r'^%',line.strip()): # 注释行,什么也不做 219 | pass 220 | else: # 普通正文的处理 221 | data_bulk.append([line_idx,line]) 222 | 223 | if not flag==0: # 子环境内 224 | mo = re.search(r'\\caption{(.*)}',line) # 翻译图注 225 | if mo: 226 | caption_en=mo.group(1).strip() 227 | if len(caption_en)>2: 228 | data_capt.append([line_idx,caption_en]) 229 | else: 230 | print(f"[**]警告:第{line_idx+start_idx-1}行的题注过短,可能有误,请检查。") 231 | 232 | flag -= len(re.findall(r'\\end{.*?}',line)) 233 | 234 | N0=len(data_abst) 235 | N1=len(data_bulk) 236 | N2=len(data_capt) 237 | N3=len(data_titl) 238 | 239 | # 合一 240 | data = data_abst + data_bulk + data_capt + data_titl 241 | all_en = [item[1] for item in data] 242 | 243 | # ===== 列表部分也放在这里一齐干了吧! ===== 244 | 245 | total_num=len(re.findall(r'\\begin\{(?:itemize|enumerate)\}',' '.join(tex_file))) 246 | if total_num == 0: 247 | data_list=[] # [list_start_idx,list_end_idx,a_list_en] 248 | data_listline=[] # [list_start_idx, list_idx, text_en, r' \item '] 249 | all_en_list=[] 250 | else: 251 | data_list=[] # [list_start_idx,list_end_idx,a_list_en] 252 | data_listline=[] # [list_start_idx, list_idx, text_en, r' \item '] 253 | 254 | # ==== 找到所有列表 ==== 255 | line_idx=start_idx 256 | while not ("==document body ends" in tex_file[line_idx] or r"\end{document}" in tex_file[line_idx]): 257 | line=tex_file[line_idx] 258 | if ("== DO NOT TRANSLATE" in line): 259 | pass 260 | if re.search(r'\\begin\{(?:itemize|enumerate)\}',line) and not ("== DO NOT TRANSLATE" in line): 261 | list_start_idx=line_idx 262 | list_end_idx=FindFirst(r'\\end\{(?:itemize|enumerate)\}',tex_file[list_start_idx:])+list_start_idx 263 | 264 | a_list_en=tex_file[list_start_idx:list_end_idx+1].copy() 265 | data_list.append([list_start_idx,list_end_idx,a_list_en]) 266 | 267 | # a_list_zh=a_list_en.copy() 268 | flag=0 269 | 270 | for list_idx,list_line in enumerate(a_list_en): 271 | if list_idx==0 or list_idx==len(a_list_en)-1: 272 | continue # 首行和尾行是列表环境定义,不处理 273 | searchobj=re.search(r'\\item (.*)',list_line) # 找个item 274 | if searchobj: # 确保item行格式正确 275 | text_en=searchobj.group(1) 276 | data_listline.append([list_start_idx, list_idx, text_en, r' \item ']) 277 | # client, text_zh = translate_text(client, text_en) 278 | # a_list_zh[list_idx]=r' \item '+text_zh+'\n' 279 | else: # 其它行就随缘吧 280 | flag+=len(re.findall(r'\\begin{.*}',list_line)) #子环境层数 281 | if not flag: 282 | text_en=list_line 283 | data_listline.append([list_start_idx, list_idx, text_en, r'']) 284 | # client, text_zh = translate_text(client, text_en) 285 | # a_list_zh[list_idx]=text_zh+'\n' 286 | flag-=len(re.findall(r'\\end{.*}',list_line)) 287 | 288 | 289 | together=['\\enzhbox{\n',] + a_list_en + ['\n}{\n',] + a_list_en + ['\n}\n',] 290 | # tex_file=tex_file[:list_start_idx] + together + tex_file[list_end_idx+1:] 291 | line_idx=list_end_idx+1 292 | else: 293 | line_idx+=1 294 | 295 | Nlist=len(data_listline) 296 | all_en_list=[item[2] for item in data_listline] 297 | 298 | 299 | 300 | 301 | 302 | all_en = all_en + all_en_list 303 | 304 | 305 | NN=len(all_en) 306 | 307 | # ====== 一齐翻译 ====== 308 | if client.translator_name == "doubao_async": 309 | ProgressBar_par(NN) 310 | # 控制同时进行的异步任务的数量,原理不明 311 | sema = asyncio.Semaphore(100) 312 | 313 | tasks = [ asyncio.create_task( taowa(client,en,sema) ) for en in all_en ] 314 | zhdata = await asyncio.gather(*tasks) 315 | else: 316 | # tasks = [ client.trans_text(item[1]) for item in data ] 317 | # zhdata = list(tasks) 318 | zhdata=[] 319 | for i in range(NN): 320 | client, line_zh = translate_text(client, all_en[i]) 321 | zhdata.append(line_zh) 322 | ProgressBar(i+1,NN) 323 | 324 | # 切分 325 | zhdata_abst=zhdata[:N0] 326 | zhdata_bulk=zhdata[N0:N0+N1] 327 | zhdata_capt=zhdata[(N0+N1):(N0+N1+N2)] 328 | zhdata_titl=zhdata[(N0+N1+N2):(N0+N1+N2+N3)] 329 | zhdata_list=zhdata[(N0+N1+N2+N3):] 330 | 331 | # ==== 把翻译好的东西放回去 ==== 332 | for i,abstzh in enumerate(zhdata_abst): # 摘要 333 | line_idx = data_abst[i][0] 334 | absten = data_abst[i][1] 335 | tex_file[abstract_idx] = r'{'+abstzh+r'}\\ \indent '+absten 336 | 337 | for i,linezh in enumerate(zhdata_bulk): # 正文 338 | line_idx = data_bulk[i][0] 339 | line = data_bulk[i][1] 340 | head =r'\noindent ' if re.search(r'^ ?[a-z]',line) else '' 341 | tex_file[line_idx] = "\n"+r"\enzhbox{ "+head+line+"}{\n"+head+linezh+"}\n" 342 | 343 | for i,captzh in enumerate(zhdata_capt): # 图注 344 | line_idx = data_capt[i][0] 345 | capt = data_capt[i][1] 346 | tex_file[line_idx]=r"\caption{\uline{"+capt+ r"}\\" + captzh + "}\n" 347 | 348 | for i,titlzh in enumerate(zhdata_titl): # 章节标题 349 | line_idx = data_titl[i][0] 350 | titl = data_titl[i][1] 351 | line = tex_file[line_idx].strip() 352 | tex_file[line_idx] = line.replace(titl,titlzh)+'\n { \\small '+titl+' \\par }\n' 353 | 354 | bias=0 355 | for thislist in data_list: # 列表 356 | list_start_idx = thislist[0] 357 | list_end_idx = thislist[1] 358 | list_en = thislist[2] 359 | 360 | idx4thislist = [ i for i,item in enumerate(data_listline) if item[0]==list_start_idx ] # 挑出data_listline中属于thislist的lines 361 | listidx4thislist =[ data_listline[j][1] for j in idx4thislist ] # thislist中的行号 362 | linezh4thislist = [ zhdata_list[j] for j in idx4thislist ] # 对应thislist行号的译文 363 | linepfx4thislist =[ data_listline[j][3] for j in idx4thislist ] # 前缀(「\item」或者空) 364 | 365 | list_zh=list_en.copy() 366 | for k,list_idx in enumerate(listidx4thislist): 367 | list_zh[list_idx] = linepfx4thislist[k] + linezh4thislist[k] + "\n" # list_zh中对应行号的文本改成译文 368 | 369 | together=['\\enzhbox{\n',] + list_en + ['\n}{\n',] + list_zh + ['\n}\n',] 370 | tex_file=tex_file[: list_start_idx+bias ] + together + tex_file[ list_end_idx+bias+1 :] 371 | 372 | bias += len(together)-(list_end_idx-list_start_idx+1) 373 | 374 | 375 | 376 | 377 | 378 | end_idx=FindFirst("==document body ends",tex_file) 379 | tex_file[end_idx+1]=suffix # 接回尾巴 380 | 381 | # print('[*] 更新API状态……') 382 | # client=tt.create_client() 383 | return tex_file 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | def translate_body(client, tex_file :list[str], suffix:list[str]) -> list[str]: 395 | 396 | print('[**] 翻译正文……') 397 | 398 | # client=tt.create_client() 399 | # def doit(mo): # 图注翻译替换函数 400 | # text_en=mo.group(1) 401 | # client, text_ch=translate_text(client,text_en) 402 | # text_ch="\\caption{\\uline{"+text_en+ "}\\\\" + text_ch + "}" 403 | # return text_ch 404 | 405 | start_idx=FindFirst("==document boby begins",tex_file) 406 | if not start_idx: 407 | start_idx=FindFirst(r"\\begin{document}",tex_file) 408 | end_idx=FindFirst("==document body ends",tex_file) 409 | if not end_idx: 410 | end_idx=FindFirst(r"\\end{document}",tex_file) 411 | tex_file[end_idx]='\n' 412 | tex_file.extend(['\n','\\end{document}\n']) 413 | 414 | flag = 0 415 | L = end_idx-start_idx+1 416 | for line_idx in range(start_idx+1,end_idx): 417 | line = tex_file[line_idx].strip() 418 | if re.search(r"^ *%.*",line): # 注释行直接跳过 419 | continue 420 | if not (client.translator_name == "count_char_num"): 421 | ProgressBar(line_idx-start_idx+1,L-1) 422 | # print(line_idx-start_idx+1,'/',L) 423 | 424 | flag += len(re.findall(r'\\begin{.*?}',line)) #子环境层数 425 | 426 | if flag==0 and len(line)>2: # 非子环境内 427 | searchobj=re.search(r'\\(part|chapter|section|subsection|subsubsection|paragraph)\*?\{(.*)\}',line) # 搜寻章节标题 428 | if searchobj: # 章节标题的处理 429 | titl_en=searchobj.group(2).strip() 430 | if len(titl_en)>2: # 长度达到最小限制3个字母,才翻译 431 | client, name_ch=translate_text(client, titl_en) 432 | line_ch=line.replace(titl_en,name_ch)+'\n { \\small '+titl_en+' \\par }\n' 433 | else: 434 | print(f"[**]警告:第{line_idx+start_idx-1}行的标题过短,可能有误,请检查。") 435 | line_ch=line 436 | tex_file[line_idx] = line_ch 437 | elif re.search(r'^%',line.strip()): # 注释行,什么也不做 438 | pass 439 | else: # 普通正文的处理 440 | head =r'\noindent ' if re.search(r'^ ?[a-z]',line) else '' #如果是小写字母开头,即不缩进 441 | client, line_ch = translate_text(client, line) 442 | # line_ch=line_ch.replace("%","\\%") 443 | # tex_file[line_idx] = r"\begin{leftbar} \small "+line+r"\end{leftbar}"+line_ch # 翻译后,在前面放上原文 444 | # tex_file[line_idx] = "\n"+r"\begin{supertabu} to 1\linewidth [t]{|X[l]|X[l]} \small "+line+r"&"+line_ch+r"\end{tabu} \medskip" # 翻译后,在前面放上原文 445 | tex_file[line_idx] = "\n"+r"\enzhbox{ "+head+line+"}{\n"+head+line_ch+"}\n" 446 | 447 | if not flag==0: # 子环境内 448 | mo = re.search(r'\\caption{(.*)}',line) # 翻译图注 449 | if mo: 450 | caption_en=mo.group(1).strip() 451 | if len(caption_en)>2: 452 | client, caption_zh = translate_text(client,caption_en) 453 | else: 454 | print(f"[**]警告:第{line_idx+start_idx-1}行的题注过短,可能有误,请检查。") 455 | caption_zh="" 456 | tex_file[line_idx]="\\caption{\\uline{"+caption_en+ "}\\\\" + caption_zh + "}\n"#re.sub(r'\\caption{(.*)}',doit,line) 457 | 458 | flag -= len(re.findall(r'\\end{.*?}',line)) 459 | 460 | tex_file[end_idx+1]=suffix # 接回尾巴 461 | 462 | # print('[*] 更新API状态……') 463 | # client=tt.create_client() 464 | return tex_file 465 | 466 | # def translate_captions(tex_file): 467 | # print('Translating captions') 468 | # client=tt.create_client() 469 | # def doit(mo): 470 | # text_en=mo.group(1) 471 | # text_ch=translate_text(client,text_en) 472 | # text_ch="\\caption{"+text_en+ "\\\\" + text_ch + "}" 473 | # return text_ch 474 | 475 | # L=len(tex_file) 476 | # for line_idx, line in enumerate(tex_file): 477 | # ProgressBar(line_idx+1,L) 478 | # tex_file[line_idx]=re.sub(r'\\caption{(.*)}',doit,line) 479 | 480 | # return tex_file 481 | 482 | async def translate_list1(client,tex_file): 483 | # 2025-02-27 21-39-35 异步并行改造 484 | print('[**] 翻译itemize和enumerate环境……') 485 | 486 | start_idx=FindFirst("==document boby begins",tex_file) 487 | if not start_idx: 488 | start_idx=FindFirst(r"\\begin{document}",tex_file) 489 | 490 | line_idx=start_idx 491 | count=0 492 | total_num=len(re.findall(r'\\begin\{(?:itemize|enumerate)\}',' '.join(tex_file))) 493 | if total_num==0: 494 | print("未找到,已完成。") 495 | return tex_file 496 | 497 | data_list=[] # [list_start_idx,list_end_idx,a_list_en] 498 | data_listline=[] # [list_start_idx, list_idx, text_en, r' \item '] 499 | 500 | # ==== 找到所有列表 ==== 501 | while not ("==document body ends" in tex_file[line_idx] or r"\end{document}" in tex_file[line_idx]): 502 | line=tex_file[line_idx] 503 | if ("== DO NOT TRANSLATE" in line): 504 | pass 505 | if re.search(r'\\begin\{(?:itemize|enumerate)\}',line) and not ("== DO NOT TRANSLATE" in line): 506 | list_start_idx=line_idx 507 | list_end_idx=FindFirst(r'\\end\{(?:itemize|enumerate)\}',tex_file[list_start_idx:])+list_start_idx 508 | 509 | a_list_en=tex_file[list_start_idx:list_end_idx+1].copy() 510 | data_list.append([list_start_idx,list_end_idx,a_list_en]) 511 | 512 | # a_list_zh=a_list_en.copy() 513 | flag=0 514 | 515 | for list_idx,list_line in enumerate(a_list_en): 516 | searchobj=re.search(r'\\item (.*)',list_line) # 找个item 517 | if searchobj: # 确保item行格式正确 518 | text_en=searchobj.group(1) 519 | data_listline.append([list_start_idx, list_idx, text_en, r' \item ']) 520 | # client, text_zh = translate_text(client, text_en) 521 | # a_list_zh[list_idx]=r' \item '+text_zh+'\n' 522 | else: # 其它行就随缘吧 523 | flag+=len(re.findall(r'\\begin{.*}',line)) #子环境层数 524 | if not flag: 525 | text_en=list_line 526 | data_listline.append([list_start_idx, list_idx, text_en, r'']) 527 | # client, text_zh = translate_text(client, text_en) 528 | # a_list_zh[list_idx]=text_zh+'\n' 529 | flag-=len(re.findall(r'\\end{.*}',line)) 530 | 531 | 532 | together=['\\enzhbox{\n',] + a_list_en + ['\n}{\n',] + a_list_en + ['\n}\n',] 533 | # tex_file=tex_file[:list_start_idx] + together + tex_file[list_end_idx+1:] 534 | line_idx=list_start_idx+len(together)+1 535 | count+=1 536 | if not (client.translator_name == "count_char_num"): 537 | ProgressBar(count,total_num) 538 | # print(f'\r已翻译了 {count}/{total_num} 个itemize/enumerate环境……',end='') 539 | sys.stdout.flush() 540 | sleep(0.001) 541 | else: 542 | line_idx+=1 543 | 544 | # ==== 翻译所有文本 ==== 545 | NN=len(data_listline) 546 | if client.translator_name == "doubao_async": 547 | ProgressBar_par(NN) 548 | # 控制同时进行的异步任务的数量,原理不明 549 | sema = asyncio.Semaphore(100) 550 | 551 | tasks = [ asyncio.create_task( taowa(client,item[2],sema) ) for item in data_listline ] 552 | zhdata = await asyncio.gather(*tasks) 553 | else: 554 | # tasks = [ client.trans_text(item[1]) for item in data ] 555 | # zhdata = list(tasks) 556 | zhdata=[] 557 | for i in range(NN): 558 | client, line_zh = translate_text(client, data_listline[i][2]) 559 | zhdata.append(line_zh) 560 | ProgressBar(i,NN) 561 | 562 | 563 | # ==== 组装回列表 ==== 564 | bias=0 565 | for thislist in data_list: 566 | list_start_idx = thislist[0] 567 | list_end_idx = thislist[1] 568 | list_en = thislist[2] 569 | 570 | idx4thislist = [ i for i,item in enumerate(data_listline) if item[0]==list_start_idx ] # 挑出data_listline中属于thislist的lines 571 | listidx4thislist =[ data_listline[j][1] for j in idx4thislist ] # thislist中的行号 572 | linezh4thislist = [ zhdata[j] for j in idx4thislist ] # 对应行号的译文 573 | linepfx4thislist =[ data_listline[j][3] for j in idx4thislist ] # 前缀(「\item」或者空) 574 | 575 | list_zh=list_en.copy() 576 | for k,list_idx in enumerate(listidx4thislist): 577 | list_zh[list_idx] = linepfx4thislist[k] + linezh4thislist[k] + "\n" # 对应行号的文本改成译文 578 | 579 | together=['\\enzhbox{\n',] + list_en + ['\n}{\n',] + list_zh + ['\n}\n',] 580 | tex_file=tex_file[: list_start_idx+bias ] + together + tex_file[ list_end_idx+bias+1 :] 581 | 582 | bias = len(together)-(list_end_idx-list_start_idx+1) 583 | 584 | 585 | 586 | return tex_file 587 | 588 | 589 | def translate_list(client, tex_file): 590 | # 用来翻译itemize和enumerate环境中的文本 591 | print('[**] 翻译itemize和enumerate环境……') 592 | # client=tt.create_client() 593 | # def doit(mo): # 图注翻译替换函数 594 | # text_en=mo.group(1) 595 | # client, text_ch=translate_text(client,text_en) 596 | # text_ch="\\caption{\\uline{"+text_en+ "}\\\\" + text_ch + "}" 597 | # return text_ch 598 | 599 | start_idx=FindFirst("==document boby begins",tex_file) 600 | if not start_idx: 601 | start_idx=FindFirst(r"\\begin{document}",tex_file) 602 | # end_idx=FindFirst("==document body ends",tex_file) 603 | # if not end_idx: 604 | # end_idx=FindFirst(r"\\end{document}",tex_file) 605 | 606 | line_idx=start_idx 607 | count=0 608 | total_num=len(re.findall(r'\\begin\{(?:itemize|enumerate)\}',' '.join(tex_file))) 609 | if total_num==0: 610 | print("未找到,",end="") 611 | 612 | while not ("==document body ends" in tex_file[line_idx] or r"\end{document}" in tex_file[line_idx]): 613 | line=tex_file[line_idx] 614 | if ("== DO NOT TRANSLATE" in line): 615 | pass 616 | if re.search(r'\\begin\{(?:itemize|enumerate)\}',line) and not ("== DO NOT TRANSLATE" in line): 617 | list_start_idx=line_idx 618 | list_end_idx=FindFirst(r'\\end\{(?:itemize|enumerate)\}',tex_file[list_start_idx:])+list_start_idx 619 | 620 | a_list_en=tex_file[list_start_idx:list_end_idx+1].copy() 621 | a_list_zh=a_list_en.copy() 622 | flag=0 623 | 624 | for list_idx,list_line in enumerate(a_list_en): 625 | searchobj=re.search(r'\\item (.*)',list_line) # 找个item 626 | if searchobj: # 确保item行格式正确 627 | text_en=searchobj.group(1) 628 | client, text_zh = translate_text(client, text_en) 629 | a_list_zh[list_idx]=r' \item '+text_zh+'\n' 630 | else: # 其它行就随缘吧 631 | flag+=len(re.findall(r'\\begin{.*}',line)) #子环境层数 632 | if not flag: 633 | text_en=list_line 634 | client, text_zh = translate_text(client, text_en) 635 | a_list_zh[list_idx]=text_zh+'\n' 636 | flag-=len(re.findall(r'\\end{.*}',line)) 637 | 638 | 639 | together=['\\enzhbox{\n',] + a_list_en + ['\n}{\n',] + a_list_zh + ['\n}\n',] 640 | tex_file=tex_file[:list_start_idx] + together + tex_file[list_end_idx+1:] 641 | line_idx=list_start_idx+len(together)+1 642 | count+=1 643 | if not (client.translator_name == "count_char_num"): 644 | ProgressBar(count,total_num) 645 | # print(f'\r已翻译了 {count}/{total_num} 个itemize/enumerate环境……',end='') 646 | sys.stdout.flush() 647 | sleep(0.001) 648 | else: 649 | line_idx+=1 650 | 651 | print("已完成。") 652 | return tex_file 653 | 654 | 655 | def AIsummary(client,tex,format_AIsum:str): 656 | print("[**] AI总结中……",end="") 657 | sys.stdout.flush() 658 | sleep(0.001) 659 | 660 | rsp :str =client.asksth("总结上面翻译的论文的内容") 661 | 662 | # 提行加粗换为latex格式 663 | rsp=rsp.replace("\n","\n\n") 664 | rsp=re.sub(r"\*\*(.*?)\*\*",r"\\textbf{\1}",rsp) 665 | rsp=re.sub(r"^[ \t]*-",r" •",rsp) 666 | 667 | # 装进去 668 | insert_id=FindFirst(r"% == insert here",format_AIsum) 669 | format_AIsum[insert_id]=rsp+"\n" 670 | start_idx=FindFirst("==document boby begins",tex) 671 | tex=tex[:start_idx-1]+format_AIsum+tex[start_idx:] 672 | print("已完成") 673 | return tex 674 | 675 | 676 | 677 | 678 | 679 | def post_decoration(tex): 680 | begin=FindFirst("==document boby begins",tex) 681 | if not begin: begin=0 682 | end=FindFirst("==document boby ends",tex) 683 | if not end : end=len(tex) 684 | for idx in range(begin,end): 685 | line=tex[idx] 686 | line=post_decoration_line(line) 687 | tex[idx]=line 688 | return tex 689 | 690 | def post_decoration_line(line): 691 | line=re.sub(r"([图表] ?\d+\.?(?:\d+)?)",r"\\textcolor{blue}{\1}",line) 692 | line=re.sub(r"([\((]\d+[\.-]\d+[a-g]?[\))])",r"\\textcolor{violet}{\1}",line) 693 | line=re.sub(r"(\[(?:\d+[,-]? ?)+\])",r"\\textcolor{green!50!black}{\1}",line) 694 | line=re.sub(r'"(.*?)"',r"「\1」",line) 695 | line=re.sub(r'“(.*?)”',r"「\1」",line) 696 | line=line.replace(r'\\%',r'\%') 697 | # line=re.sub(r"%",r"\%",line) 698 | return line 699 | 700 | 701 | if __name__=="__main__": 702 | # 测试 703 | # lines=[ 704 | # r"Right-hand side: Current profiles for discharge 119787 of DIIID: total $\left(J_{\|}\right)$, bootstrap $\left(J_{\text {bs }}\right)$, beam driven $\left(J_{\mathrm{NBCD}}\right)$ current densities, and the sum of the bootstrap and beam-driven current densities. After (ref.[55]).", 705 | 706 | # #r"\command{233} Because of the divergence-free nature of the magnetic field, the simplest topological configuration it can assume with no field lines exiting from a fixed volume is toroidal.", 707 | # #r"Introduce general 95\% coordinates $\psi, \theta, \zeta$, as shown in Fig. 1.2. Surfaces of constant $\psi$ are taken to consist topologically of nested tori, which necessarily possess an axis which will usually be designated by $\psi=0$." 708 | # ] 709 | 710 | from importlib import import_module 711 | 712 | translatorsdict={"1":"baidu","2":"tencent","3":"openai","4":"deepl","5":"doubao","9":"test","0":"count_char_num"} 713 | s=input("<< 选择翻译器"+str(translatorsdict)+":") 714 | 715 | # exec("import translators."+translatorsdict[s]+"_translator as tt ") # 感觉不太优雅,但是就这样吧! 716 | tt=import_module("translators."+translatorsdict[s]+"_translator") 717 | 718 | client=tt.create_client() 719 | # for line in lines: 720 | # print(line) 721 | while(1): 722 | line=input("input en:") 723 | head =r'\noindent ' if re.search(r'^[a-z]',line) else '' 724 | # print(head) 725 | client, line_ch=translate_text(client,line) 726 | output="\n"+r"\enzhbox{ "+head+line+"}{\n"+head+line_ch+"}\n" 727 | output=post_decoration_line(output) 728 | print(output) 729 | 730 | -------------------------------------------------------------------------------- /translator_keys_void/baidu_keys.yaml: -------------------------------------------------------------------------------- 1 | # 百度翻译API开通:https://hcfy.ai/docs/services/baidu-api 2 | id: '' 3 | key: '' 4 | -------------------------------------------------------------------------------- /translator_keys_void/deepl_keys.yaml: -------------------------------------------------------------------------------- 1 | # DeepL API尚不支持大陆银行卡开通,可某宝购买免费API(每月限50w字符) 2 | # 这里设计了弹夹机制,可遍历使用多个免费API 3 | '1': 4 | date: '15' 5 | key: '' 6 | state: 'on' 7 | used_percent: 25.3 8 | '2': 9 | date: '22' 10 | key: '' 11 | state: 'on' 12 | used_percent: 90.9 13 | 14 | -------------------------------------------------------------------------------- /translator_keys_void/doubao_keys.yaml: -------------------------------------------------------------------------------- 1 | # 【推荐!】豆包大模型API开通:https://www.volcengine.com/product/ark 2 | api_key: '' 3 | base_url: https://ark.cn-beijing.volces.com/api/v3 4 | context_api: https://ark.cn-beijing.volces.com/api/v3/context/create 5 | model: '' -------------------------------------------------------------------------------- /translator_keys_void/mathpix_keys.yaml: -------------------------------------------------------------------------------- 1 | # mathpix api开通:https://mathpix.com/pricing/api 2 | # mathpix API 0.005美元/页pdf 3 | app_id: 4 | app_key: -------------------------------------------------------------------------------- /translator_keys_void/openai_keys.yaml: -------------------------------------------------------------------------------- 1 | # 适用于任意支持OpenAI SDK的大模型,比如chatGPT、doubao、deepseek等。 2 | # 举例:开通deepseek https://hcfy.ai/docs/services/deepseek 3 | api_key: '' 4 | base_url: '' 5 | model: '' 6 | 7 | 8 | -------------------------------------------------------------------------------- /translator_keys_void/tencent_keys.yaml: -------------------------------------------------------------------------------- 1 | # 腾讯翻译API开通:https://hcfy.ai/docs/services/qq-api 2 | id: '' 3 | key: '' 4 | glossary_id: ["",] -------------------------------------------------------------------------------- /translators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/translators/__init__.py -------------------------------------------------------------------------------- /translators/baidu_translator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code shows an example of text translation from English to Simplified-Chinese. 4 | # This code runs on Python 2.7.x and Python 3.x. 5 | # You may install `requests` to run this code: pip install requests 6 | # Please refer to `https://api.fanyi.baidu.com/doc/21` for complete api document 7 | 8 | import requests,yaml,os,datetime,logging 9 | import random 10 | import json 11 | from hashlib import md5 12 | from time import sleep 13 | 14 | def create_client(): 15 | print('百度翻译为您服务') 16 | class baidu_client(object): 17 | def __init__(self): 18 | self.translator_name="baidu" 19 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 20 | logging.warning("翻译器:"+self.translator_name) 21 | 22 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 23 | for apidir in config["翻译设置"]["翻译APIkeys文件夹"]: 24 | if os.path.exists(apidir): 25 | print("[**] 读取API:"+apidir+'/baidu_keys.yaml') 26 | break 27 | with open(apidir+'/baidu_keys.yaml') as f: 28 | # Set your own appid/appkey. 29 | keys=yaml.load(f,Loader=yaml.Loader) 30 | appid = keys['id'] 31 | appkey = keys['key'] 32 | 33 | if not keys["id"]: 34 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 35 | logging.error("[error]未找到翻译器API keys") 36 | input("按回车退出……") 37 | exit() 38 | 39 | 40 | endpoint = 'http://api.fanyi.baidu.com' 41 | path = '/api/trans/vip/translate' 42 | self.url = endpoint + path 43 | 44 | # Build request 45 | headers = {'Content-Type': 'application/x-www-form-urlencoded'} 46 | # payload = {'appid': appid, 'from': from_lang, 'to': to_lang, 'q': query, 'salt': salt, 'sign': sign} 47 | paras= {'action':'1','appid': appid, 'appkey':appkey,'from': 'en', 'to': 'zh', 'q': [], 'salt': [], 'sign': []} # action=1:使用自定义术语库 48 | self.headers=headers 49 | self.p=paras 50 | 51 | def trans_text(self,text): 52 | self.__query=text 53 | 54 | # Generate salt and sign 55 | def make_md5(s, encoding='utf-8'): 56 | return md5(s.encode(encoding)).hexdigest() 57 | 58 | self.__salt = random.randint(32768, 65536) 59 | self.__sign = make_md5(self.p['appid'] + self.__query + str(self.__salt) + self.p['appkey'] ) 60 | 61 | self.p['q']=self.__query 62 | self.p['salt']=self.__salt 63 | self.p['sign']=self.__sign 64 | 65 | # Send request 66 | r = requests.post(self.url, params=self.p, headers=self.headers) 67 | result = r.json() 68 | return result['trans_result'][0]['dst'] 69 | 70 | client=baidu_client() 71 | 72 | return client 73 | 74 | def translator(client, text): 75 | sleep(0.2) # 每秒最多请求5次,可以删掉这行来搞快点 76 | return client, client.doit(text) 77 | 78 | 79 | if __name__=="__main__": # 测试用 80 | c=create_client() 81 | t_en="THE ELECTRON KINETIC EQUATION".lower() 82 | 83 | t_zh=c.trans_text(t_en) 84 | print(t_en,'\n',t_zh) 85 | -------------------------------------------------------------------------------- /translators/count_num_translator.py: -------------------------------------------------------------------------------- 1 | import sys 2 | # from transformers import AutoTokenizer 3 | from time import sleep 4 | 5 | 6 | def create_client(): 7 | print('[**] 数数总共有多少字符和token') 8 | class clientclass(): 9 | def __init__(self): 10 | self.translator_name='count_num' 11 | self.charnum=0 12 | self.tokennum=0 13 | # self.tnzer=AutoTokenizer.from_pretrained("./translators") 14 | 15 | 16 | def trans_text(self,text): 17 | self.charnum += len(text.replace(" ","")) 18 | # self.tokennum += len(self.tnzer.tokenize(text)) 19 | return text 20 | 21 | 22 | client=clientclass() 23 | return client 24 | 25 | # def translator(client,text): 26 | # client.count_and_add(text.replace(" ","")) 27 | # return client,text 28 | 29 | if __name__=="__main__": 30 | client=create_client() 31 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Bessel functions is in the notation of G. N. Watson (1922). $a = 3\mathrm{m}^{-3}, b=16\mathrm{Wb}$. " 32 | zh=client.trans_text(en) 33 | print([client.charnum,client.tokennum]) -------------------------------------------------------------------------------- /translators/deepl_translator.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Optional, Union 2 | import deepl,json,yaml,os,logging,datetime 3 | from time import sleep,time 4 | 5 | # 文档:https://github.com/DeepLcom/deepl-python 6 | # 安装:pip install --upgrade deepl 7 | 8 | 9 | 10 | def create_client(): 11 | print('[*] DeepL翻译为您服务') 12 | # with open('config.json',encoding='utf8') as f: config=json.load(f) 13 | # with open('translator_keys/deepl_keys.json') as f: keys=json.load(f) 14 | 15 | # glossary2use=config["翻译设置"]["deepL-要用的术语表"]#"fusion_glossary" #要用的术语表 16 | # refreshThisGlossary=config['翻译设置']['deepL-更新术语表'] #是否要重新装载该术语表 17 | 18 | class myclient(deepl.Translator): 19 | def __init__(self): 20 | self.translator_name="deepl" 21 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 22 | logging.warning("翻译器:"+self.translator_name) 23 | 24 | with open('设置.yaml', 'r',encoding="utf8") as file: config=yaml.load(file,Loader=yaml.Loader) 25 | for self.apidir in config["翻译设置"]["翻译APIkeys文件夹"]: 26 | if os.path.exists(self.apidir): 27 | print("[**] 读取API:"+self.apidir+'/deepl_keys.yaml') 28 | break 29 | # with open('config.json',encoding='utf8') as f: config=json.load(f) 30 | with open(self.apidir+'/deepl_keys.yaml') as f: keys=yaml.load(f,Loader=yaml.Loader) 31 | 32 | glossary2use=config["翻译设置"]["deepL-要用的术语表"]#"fusion_glossary" #要用的术语表 33 | refreshThisGlossary=config['翻译设置']['deepL-更新术语表'] #是否要重新装载该术语表 34 | 35 | anyAPIalive=False 36 | for idx in keys: 37 | if config['翻译设置']['deepL-重新检查账号额度']: 38 | keys[idx]["state"]="on" 39 | if keys[idx]["state"]=="on": 40 | auth_key = keys[idx]['key'] # Replace with your key 41 | if not keys[idx]['key']: 42 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 43 | logging.error("[error]未找到翻译器API keys") 44 | input("按回车退出……") 45 | exit() 46 | self.activated_key_idx=idx 47 | super().__init__(auth_key) # 初始化母class,即加载deepl翻译器 48 | 49 | usage=self.get_usage().character 50 | usage_prct=round(usage.count/usage.limit*100,1) 51 | self.charleft=usage.limit-usage.count 52 | keys[idx]["used_percent"]=usage_prct 53 | print(f"[*] 账号 {idx} 号已用额度:{usage_prct} %, {usage.count} / {usage.limit}",end="") 54 | 55 | if config['翻译设置']['deepL-只检查账号额度']: 56 | print(",继续检查下个额度……") 57 | continue 58 | 59 | if self.charleft<3000: 60 | print(",继续尝试下一个弹匣……") 61 | keys[idx]["state"]="off" 62 | continue 63 | 64 | 65 | print(",启用中。") 66 | anyAPIalive=True 67 | 68 | # 处理术语表 69 | glossary_ready=False 70 | glsrs = self.list_glossaries() # 当前API已有术语表 71 | for glsy in glsrs: 72 | if glsy.name == glossary2use: # 当前API已经有这个术语表了 73 | if refreshThisGlossary: 74 | self.delete_glossary(glsy) 75 | else: 76 | self.current_glsy=glsy.glossary_id # 记录其id 77 | print("[*] 已有并启用术语表: ",glsy.name) 78 | glossary_ready=True 79 | break 80 | 81 | if not glossary_ready: # 当面API没有这个术语表 82 | with open(f'glossaries/{glossary2use}.csv', 'r', encoding='utf-8') as csv_file: 83 | csv_data = csv_file.read() # Read the file contents as a string 84 | glsy = self.create_glossary_from_csv( 85 | "fusion_glossary", 86 | source_lang="EN", 87 | target_lang="ZH", 88 | csv_data=csv_data, 89 | ) 90 | self.current_glsy=glsy.glossary_id # 记录其id 91 | print("[*] 术语表已更新,并已启用:",glossary2use) 92 | 93 | break # 已成功装填API的break 94 | 95 | with open(self.apidir+'/deepl_keys.json','w+') as f: json.dump(keys,f,indent=4) 96 | 97 | if not anyAPIalive: 98 | raise AttributeError("[*] 所有DeepL密钥的额度都已不足!") 99 | 100 | 101 | 102 | def trans_text(self,text): 103 | self.charleft -= len(text) # 剩余额度扣除本次的字符数 104 | # print(client.charleft) 105 | 106 | if (self.charleft)<3000: 107 | print("[*] 换弹匣……") 108 | self.__init__() 109 | 110 | if len(text)>2: 111 | result = self.translate_text(text,source_lang="EN", target_lang="ZH-Hans",preserve_formatting=True,glossary=self.current_glsy) 112 | resulttext=result.text 113 | sleep(0.2) # 每秒最多请求5次,可以删掉这行来搞快点 114 | else: 115 | resulttext='' 116 | # usage=client.get_usage().character 117 | # print(usage.limit-usage.count) 118 | return resulttext 119 | 120 | def check_usage(self): 121 | with open(self.apidir+'/deepl_keys.json') as f: keys=json.load(f) 122 | 123 | usage=self.get_usage().character 124 | usage_prct=round(usage.count/usage.limit*100,1) 125 | self.charleft=usage.limit-usage.count 126 | keys[self.activated_key_idx]["used_percent"]=usage_prct 127 | print(f"[*] 账号 {self.activated_key_idx} 号已用额度:{usage_prct} %, {usage.count} / {usage.limit}") 128 | 129 | with open(self.apidir+'/deepl_keys.json','w+') as f: json.dump(keys,f,indent=4) 130 | 131 | 132 | 133 | 134 | # anyAPIalive=False 135 | # for idx in keys: 136 | # if config['翻译设置']['deepL-重新检查账号额度']: 137 | # keys[idx]["state"]="on" # 【可操作】解除该行的注释来手动刷新API的状态 138 | # if keys[idx]["state"]=="on": 139 | # auth_key = keys[idx]['key'] # Replace with your key 140 | # client = deepl.Translator(auth_key) 141 | 142 | # usage=client.get_usage().character 143 | # usage_prct=round(usage.count/usage.limit*100,1) 144 | # client.charleft=usage.limit-usage.count 145 | # keys[idx]["used_percent"]=usage_prct 146 | # print(f"[*] 账号 {idx} 号已用额度:{usage_prct} %, {usage.count} / {usage.limit}",end="") 147 | 148 | # if client.charleft<3000: 149 | # print(",继续尝试下一个弹匣……") 150 | # keys[idx]["state"]="off" 151 | # continue 152 | 153 | # print(",启用中。") 154 | # anyAPIalive=True 155 | 156 | # # 处理术语表 157 | # glossary_ready=False 158 | # glsrs = client.list_glossaries() # 当前API已有术语表 159 | # for glsy in glsrs: 160 | # if glsy.name == glossary2use: # 当前API已经有这个术语表了 161 | # if refreshThisGlossary: 162 | # client.delete_glossary(glsy) 163 | # else: 164 | # client.current_glsy=glsy.glossary_id # 记录其id 165 | # print("[*] 已有并启用术语表: ",glsy.name) 166 | # glossary_ready=True 167 | # break 168 | 169 | # if not glossary_ready: # 当面API没有这个术语表 170 | # with open(f'glossaries/{glossary2use}.csv', 'r', encoding='utf-8') as csv_file: 171 | # csv_data = csv_file.read() # Read the file contents as a string 172 | # glsy = client.create_glossary_from_csv( 173 | # "fusion_glossary", 174 | # source_lang="EN", 175 | # target_lang="ZH", 176 | # csv_data=csv_data, 177 | # ) 178 | # client.current_glsy=glsy.glossary_id # 记录其id 179 | # print("[*] 术语表已更新,并已启用:",glossary2use) 180 | 181 | # break # 已成功装填API的break 182 | 183 | # with open('translator_keys/deepl_keys.json','w+') as f: 184 | # json.dump(keys,f,indent=4) 185 | 186 | # if not anyAPIalive: 187 | # raise AttributeError("[*] 所有DeepL密钥的额度都已不足!") 188 | 189 | # usage=client.get_usage().character 190 | # usage_prct=round(usage.count/usage.limit*100,1) 191 | # print(f"[*] 当前DeepL账号已用额度:{usage_prct} %, {usage.count} / {usage.limit}") 192 | 193 | # if (usage.limit-usage.count)<3000: 194 | # keys[idx]["state"]="off" 195 | 196 | 197 | return myclient() 198 | 199 | def translator(client,text): 200 | client.charleft -= len(text) # 剩余额度扣除本次的字符数 201 | # print(client.charleft) 202 | 203 | if (client.charleft)<3000: 204 | print("[*] 换弹匣……") 205 | client=create_client() 206 | 207 | if len(text)>2: 208 | result = client.translate_text(text,source_lang="EN", target_lang="ZH",preserve_formatting=True,glossary=client.current_glsy) 209 | resulttext=result.text 210 | sleep(0.2) # 每秒最多请求5次,可以删掉这行来搞快点 211 | else: 212 | resulttext='' 213 | # usage=client.get_usage().character 214 | # print(usage.limit-usage.count) 215 | return client, resulttext 216 | 217 | if __name__=="__main__": 218 | client=create_client() 219 | # en=r"The validity of the momentum equation is also much wider than the ideal MHD conditions would imply, although the reasons involve considerably more subtle physics. Recall that the collision dominated assumption is required to neglect $\boldsymbol{\Pi}_{i}$ and $\Pi_{e}$. In a collisionless plasma the magnetic field in a certain sense plays the role of collisions for the perpendicular motion; that is, perpendicular to the field, particles are confined to the vicinity of a given field line executing nearly (two-dimensional) isotropic motion if their gyro radius is much smaller than the characteristic plasma dimension. In fact, a calculation of $\boldsymbol{\Pi}_{\perp i}$ in the collisionless regime (see, for instance, Bowers and Haines (1971)) shows that for the MHD ordering $\Pi_{\perp i} / p_{i} \sim r_{L i} / a \ll 1$. Therefore, the perpendicular motion is fluid-like, implying that the perpendicular components of the momentum equation provide an excellent description of plasma behavior in either the collision dominated or collisionless regimes." 220 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Bessel functions is in the notation of G. N. Watson (1922). $a = 3\mathrm{m}^{-3}, b=16\mathrm{Wb}$. " 221 | zh=client.trans_text(en) 222 | # client, zh=translator(client,en) 223 | print(zh) -------------------------------------------------------------------------------- /translators/doubao_async_translator.py: -------------------------------------------------------------------------------- 1 | # 需升级方舟 Python SDK到1.0.116版本或以上,pip install --upgrade 'volcengine-python-sdk[ark]' 2 | from volcenginesdkarkruntime import AsyncArk,Ark 3 | from time import time 4 | import yaml,datetime,logging,os 5 | import asyncio 6 | 7 | def create_client(): 8 | print("[**] Doubao_async为您服务!") 9 | class myclient(AsyncArk): 10 | def __init__(self): 11 | self.translator_name="doubao_async" 12 | 13 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 14 | logging.warning("翻译器:"+self.translator_name) 15 | 16 | # with open('translator_keys/openai_keys.json', 'r') as file: 17 | # keys = json.load(file) 18 | with open('设置.yaml', 'r',encoding="utf8") as file: self.config=yaml.load(file,Loader=yaml.Loader) 19 | for apidir in self.config["翻译设置"]["翻译APIkeys文件夹"]: 20 | if os.path.exists(apidir): 21 | print("[**] 读取API:"+apidir+'/doubao_keys.yaml') 22 | break 23 | with open(apidir+'/doubao_keys.yaml', 'r',encoding="utf8") as file: self.keys=yaml.load(file,Loader=yaml.Loader) # 读取成一个dict 24 | 25 | if not self.keys["api_key"]: 26 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 27 | logging.error("[error]未找到翻译器API keys") 28 | input("按回车退出……") 29 | exit() 30 | 31 | super().__init__(api_key=self.keys["api_key"]) 32 | 33 | # 2025-02-25 09-40-05 缓存模式 34 | # - "session" 能完整理解对话上下文,因此具备总结全文和AI问答的功能,代价是缓存调用量滚雪球,每次对话后越来越大 35 | # - "common_prefix" 只保留初始化时的前缀信息,每次对话时调用缓存大小不变,代价是不具备上下文理解能力 36 | # 2025-02-27 19-18-22 异步模式只"common_prefix" 37 | cachemode = "common_prefix" 38 | 39 | # # 缓存术语表的功能,试一试 2025-02-21 10-03-37 40 | with open(f"glossaries/{self.config['翻译设置']['doubao-要用的术语表']}.csv",'r', encoding='utf-8') as f: 41 | glsy=f.read() 42 | logging.warning("术语表:"+f"glossaries/{self.config['翻译设置']['doubao-要用的术语表']}.csv") 43 | 44 | # 索取contextid的工具人 45 | tmpclient = Ark(api_key=self.keys["api_key"]) 46 | response = tmpclient.context.create( 47 | model=self.keys["model"], 48 | messages=[ 49 | {"role": "system", "content": "你将要翻译一篇latex格式科技论文文本,要求:人名、单位、首字母缩写不要翻译;直接输出结果,不要做额外的解释或处理。下面是术语表,每行逗号前的英文对应逗号后的中文:\n"+glsy}, 50 | ], 51 | mode=cachemode, 52 | ttl=self.config["翻译设置"]["doubao-上下文超时时间"], 53 | ) 54 | self.contextid=response.id 55 | print("[**] 已加载术语表:"+self.config["翻译设置"]["doubao-要用的术语表"]) 56 | 57 | self.tokenup=0 58 | self.tokendown=0 59 | self.tokencache=0 60 | 61 | 62 | # logging.warning(".") 63 | # logging.warning(".") 64 | logging.warning(f"doubao client已生成,contextid = {self.contextid}") 65 | 66 | 67 | 68 | async def asksth(self,text): 69 | response = await self.context.completions.create( 70 | model=self.keys["model"], 71 | messages=[ 72 | {"role": "user", "content": text}, 73 | ], 74 | stream=False, 75 | max_tokens=4096, 76 | temperature=0.5, 77 | context_id=self.contextid, 78 | ) 79 | resulttext=response.choices[0].message.content 80 | 81 | # with open("doubao-contextid.yaml","r",encoding="utf8") as f: tt=yaml.load(f,Loader=yaml.Loader) 82 | # tt["expiretime"]=str(datetime.datetime.now()+datetime.timedelta(seconds=self.config["翻译设置"]["doubao-上下文超时时间"])) 83 | # with open("doubao-contextid.yaml","w",encoding="utf8") as f: yaml.dump(tt,f,allow_unicode=1) 84 | 85 | try: 86 | self.tokenup += response.usage["prompt_tokens"] 87 | self.tokendown += response.usage["completion_tokens"] 88 | self.tokencache += response.usage["prompt_tokens_details"]["cached_tokens"] 89 | except: 90 | self.tokenup += response.usage.prompt_tokens 91 | self.tokendown += response.usage.completion_tokens 92 | self.tokencache += response.usage.prompt_tokens_details.cached_tokens 93 | 94 | # self.check_usage() 95 | 96 | return resulttext 97 | 98 | async def trans_text(self,text): 99 | r = await self.asksth("翻译下文为中文:"+text) 100 | return r 101 | 102 | def check_usage(self): 103 | thestr="消耗总token数:输入{:,}(外加命中缓存{:,}),输出{:,},计费{:,.3f}元"\ 104 | .format(self.tokenup-self.tokencache, self.tokencache, self.tokendown, (self.tokenup-self.tokencache)*1e-6*0.8+self.tokendown*1e-6*2+self.tokencache*1e-6*0.16) 105 | logging.warning(thestr) 106 | return "[*] "+thestr 107 | 108 | 109 | return myclient() 110 | 111 | if __name__=="__main__": 112 | tic=time() 113 | 114 | client=create_client() 115 | # en="the kinetic theory in plasma physics" 116 | # en=r"The validity of the momentum equation is also much wider than the ideal MHD conditions would imply, although the reasons involve considerably more subtle physics. Recall that the collision dominated assumption is required to neglect $\boldsymbol{\Pi}_{i}$ and $\Pi_{e}$. In a collisionless plasma the magnetic field in a certain sense plays the role of collisions for the perpendicular motion; that is, perpendicular to the field, particles are confined to the vicinity of a given field line executing nearly (two-dimensional) isotropic motion if their gyro radius is much smaller than the characteristic plasma dimension. In fact, a calculation of $\boldsymbol{\Pi}_{\perp i}$ in the collisionless regime (see, for instance, Bowers and Haines (1971)) shows that for the MHD ordering $\Pi_{\perp i} / p_{i} \sim r_{L i} / a \ll 1$. Therefore, the perpendicular motion is fluid-like, implying that the perpendicular components of the momentum equation provide an excellent description of plasma behavior in either the collision dominated or collisionless regimes." 117 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Bessel functions is in the notation of G. N. Watson (1922). $a = 3\mathrm{m}^{-3}, b=16\mathrm{Wb}$. " 118 | # client,zh = translator(client,en) 119 | zh = asyncio.run(client.trans_text(en)) 120 | print(zh) 121 | 122 | toc=time() 123 | print(f"耗时 {toc-tic:.4f} s") 124 | -------------------------------------------------------------------------------- /translators/doubao_translator.py: -------------------------------------------------------------------------------- 1 | # 需升级方舟 Python SDK到1.0.116版本或以上,pip install --upgrade 'volcengine-python-sdk[ark]' 2 | from volcenginesdkarkruntime import Ark 3 | from time import time 4 | import yaml,datetime,logging,os 5 | 6 | def create_client(): 7 | print("[**] Doubao为您服务!") 8 | class myclient(Ark): 9 | def __init__(self): 10 | self.translator_name="doubao" 11 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 12 | logging.warning("翻译器:"+self.translator_name) 13 | 14 | # with open('translator_keys/openai_keys.json', 'r') as file: 15 | # keys = json.load(file) 16 | with open('设置.yaml', 'r',encoding="utf8") as file: self.config=yaml.load(file,Loader=yaml.Loader) 17 | for apidir in self.config["翻译设置"]["翻译APIkeys文件夹"]: 18 | if os.path.exists(apidir): 19 | print("[**] 读取API:"+apidir+'/doubao_keys.yaml') 20 | break 21 | with open(apidir+'/doubao_keys.yaml', 'r',encoding="utf8") as file: self.keys=yaml.load(file,Loader=yaml.Loader) # 读取成一个dict 22 | 23 | if not self.keys["api_key"]: 24 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 25 | logging.error("[error]未找到翻译器API keys") 26 | input("按回车退出……") 27 | exit() 28 | 29 | super().__init__(api_key=self.keys["api_key"]) 30 | 31 | # 2025-02-25 09-40-05 缓存模式 32 | # - "session" 能完整理解对话上下文,因此具备总结全文和AI问答的功能,代价是缓存调用量滚雪球,每次对话后越来越大 33 | # - "common_prefix" 只保留初始化时的前缀信息,每次对话时调用缓存大小不变,代价是不具备上下文理解能力 34 | cachemode = "session" if self.config["翻译设置"]["doubao-AI总结"] else "common_prefix" 35 | 36 | # # 缓存术语表的功能,试一试 2025-02-21 10-03-37 37 | with open(f"glossaries/{self.config['翻译设置']['doubao-要用的术语表']}.csv",'r', encoding='utf-8') as f: 38 | glsy=f.read() 39 | response = self.context.create( 40 | model=self.keys["model"], 41 | messages=[ 42 | {"role": "system", "content": "你将要翻译一篇科技论文,下面是术语表,每行逗号前的英文对应逗号后的中文:\n"+glsy}, 43 | ], 44 | mode=cachemode, 45 | ttl=self.config["翻译设置"]["doubao-上下文超时时间"], 46 | ) 47 | self.contextid=response.id 48 | print("[**] 已加载术语表:"+self.config["翻译设置"]["doubao-要用的术语表"]) 49 | 50 | with open("doubao-contextid.yaml","w",encoding="utf8") as f: 51 | tt={"cachemode":cachemode, 52 | "expiretime":str(datetime.datetime.now()+datetime.timedelta(seconds=self.config["翻译设置"]["doubao-上下文超时时间"])), 53 | "contextid":self.contextid} 54 | yaml.dump(tt,f,allow_unicode=1) 55 | 56 | self.tokenup=0 57 | self.tokendown=0 58 | self.tokencache=0 59 | 60 | logging.basicConfig(filename="log.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 61 | logging.warning(".") 62 | logging.warning(".") 63 | logging.warning(f"doubao client已生成,contextid = {self.contextid}") 64 | 65 | 66 | 67 | def asksth(self,text): 68 | response = self.context.completions.create( 69 | model=self.keys["model"], 70 | messages=[ 71 | {"role": "user", "content": text}, 72 | ], 73 | stream=False, 74 | max_tokens=4096, 75 | temperature=0.5, 76 | context_id=self.contextid, 77 | ) 78 | resulttext=response.choices[0].message.content 79 | 80 | with open("doubao-contextid.yaml","r",encoding="utf8") as f: tt=yaml.load(f,Loader=yaml.Loader) 81 | tt["expiretime"]=str(datetime.datetime.now()+datetime.timedelta(seconds=self.config["翻译设置"]["doubao-上下文超时时间"])) 82 | with open("doubao-contextid.yaml","w",encoding="utf8") as f: yaml.dump(tt,f,allow_unicode=1) 83 | 84 | try: 85 | self.tokenup += response.usage["prompt_tokens"] 86 | self.tokendown += response.usage["completion_tokens"] 87 | self.tokencache += response.usage["prompt_tokens_details"]["cached_tokens"] 88 | except: 89 | self.tokenup += response.usage.prompt_tokens 90 | self.tokendown += response.usage.completion_tokens 91 | self.tokencache += response.usage.prompt_tokens_details.cached_tokens 92 | 93 | # self.check_usage() 94 | 95 | return resulttext 96 | 97 | def trans_text(self,text): 98 | return self.asksth("将下面这段latex格式论文文本翻译为中文(人名、单位和缩写不要翻译;直接输出结果,不要做额外的处理):"+text) 99 | 100 | def check_usage(self): 101 | thestr="消耗总token数:输入{:,}(外加命中缓存{:,}),输出{:,},计费{}元"\ 102 | .format(self.tokenup-self.tokencache, self.tokencache, self.tokendown, round((self.tokenup-self.tokencache)*1e-6*0.8+self.tokendown*1e-6*2+self.tokencache*1e-6*0.16,3)) 103 | logging.warning(thestr) 104 | return "[*] "+thestr 105 | 106 | 107 | return myclient() 108 | 109 | if __name__=="__main__": 110 | tic=time() 111 | 112 | client=create_client() 113 | # en="the kinetic theory in plasma physics" 114 | # en=r"The validity of the momentum equation is also much wider than the ideal MHD conditions would imply, although the reasons involve considerably more subtle physics. Recall that the collision dominated assumption is required to neglect $\boldsymbol{\Pi}_{i}$ and $\Pi_{e}$. In a collisionless plasma the magnetic field in a certain sense plays the role of collisions for the perpendicular motion; that is, perpendicular to the field, particles are confined to the vicinity of a given field line executing nearly (two-dimensional) isotropic motion if their gyro radius is much smaller than the characteristic plasma dimension. In fact, a calculation of $\boldsymbol{\Pi}_{\perp i}$ in the collisionless regime (see, for instance, Bowers and Haines (1971)) shows that for the MHD ordering $\Pi_{\perp i} / p_{i} \sim r_{L i} / a \ll 1$. Therefore, the perpendicular motion is fluid-like, implying that the perpendicular components of the momentum equation provide an excellent description of plasma behavior in either the collision dominated or collisionless regimes." 115 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Because of the poor coupling of equilibria with this shape to the TCV vacuum vessel, we use a conformal wall with the distance chosen ( $d=1.275 a$ ) to give the same value of $l_{i, 0}$ as the TCV dee configuration at zero pressure." 116 | # client,zh = translator(client,en) 117 | zh = client.trans_text(en) 118 | print(zh) 119 | 120 | toc=time() 121 | print(f"耗时 {toc-tic:.4f} s") -------------------------------------------------------------------------------- /translators/openai_translator.py: -------------------------------------------------------------------------------- 1 | import openai,json,yaml,os,logging,datetime 2 | from time import sleep,time 3 | 4 | 5 | # def create_client(): 6 | # print('ChatGPT翻译为您服务') 7 | # with open('translator_keys/openai_keys.json', 'r') as file: 8 | # keys = json.load(file) 9 | # openai.api_key = keys['key'] 10 | # return 0 11 | 12 | # def translator(client, text, model='gpt-3.5-turbo'): 13 | # response = openai.ChatCompletion.create( 14 | # model="gpt-3.5-turbo", 15 | # messages=[ 16 | # {"role": "system", "content": "Translate English latex text about plasma physics to Chinese latex text.Do not translate person's name.Be faithful or accurate in translation. Make the translation readable or intelligible. Be elegant or natural in translation.Do not add any additional text in the translation. Ensure that all percentage signs (%) are properly escaped"}, 17 | # #添加专有名词的翻译词典 18 | # {"role": "system", "content": "- last closed surface:最外闭合磁面 "}, 19 | # {"role": "system", "content": "- kinetic:动理学 "}, 20 | 21 | 22 | # {"role": "user", "content": f" The text to be translated is:'{text}'\n"} 23 | # ] 24 | # ) 25 | 26 | # translation = response.choices[0].message.content.strip() 27 | # sleep(0.2) # 每秒最多请求5次,可以删掉这行来搞快点 28 | # return translation 29 | def create_client(): 30 | print("[**] OpenAI(还是啥的)为您服务!") 31 | class myclient(openai.OpenAI): 32 | def __init__(self): 33 | self.translator_name="openai" 34 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 35 | logging.warning("翻译器:"+self.translator_name) 36 | 37 | # with open('translator_keys/openai_keys.json', 'r') as file: 38 | # keys = json.load(file) 39 | with open('设置.yaml', 'r',encoding="utf8") as file: self.config=yaml.load(file,Loader=yaml.Loader) 40 | for apidir in self.config["翻译设置"]["翻译APIkeys文件夹"]: 41 | if os.path.exists(apidir): 42 | print("[**] 读取API:"+apidir+'/openai_keys.yaml') 43 | break 44 | with open( apidir+'/openai_keys.yaml', 'r',encoding="utf8") as file: 45 | self.keys=yaml.load(file,Loader=yaml.Loader) # 读取成一个dict 46 | 47 | if not self.keys["api_key"]: 48 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 49 | logging.error("[error]未找到翻译器API keys") 50 | input("按回车退出……") 51 | exit() 52 | 53 | super().__init__(api_key=self.keys["api_key"], base_url=self.keys["base_url"]) 54 | 55 | # # 缓存术语表的功能,试一试 2025-02-21 10-03-37 56 | # with open("glossaries/fusion_glossary.csv",'r', encoding='utf-8') as f: 57 | # glsy=f.read() 58 | # response = openai.OpenAI(api_key=self.keys["api_key"], base_url=self.keys["context_api"]).chat.completions.create( 59 | # model=self.keys["model"], 60 | # messages=[ 61 | # {"role": "system", "content": "你将要翻译一系列科技论文,人名和缩写保持原装不翻译,下面是术语表,每行逗号前的英文对应逗号后的中文:\n"+glsy}, 62 | # ], 63 | # mode="session", 64 | # ttl=360, 65 | # ) 66 | # self.contextid=response.id 67 | 68 | 69 | 70 | def asksth(self,text): 71 | response = self.chat.completions.create( 72 | model=self.keys["model"], 73 | messages=[ 74 | {"role": "user", "content": text}, 75 | ], 76 | stream=False, 77 | max_tokens=4096, 78 | temperature=0.5, 79 | ) 80 | resulttext=response.choices[0].message.content 81 | return resulttext 82 | 83 | def trans_text(self,text): 84 | return self.asksth("将下面这段latex格式论文文本翻译为中文(直接输出结果):"+text) 85 | 86 | 87 | return myclient() 88 | 89 | 90 | if __name__=="__main__": 91 | tic=time() 92 | 93 | client=create_client() 94 | en="the kinetic theory in plasma physics" 95 | # en=r"The validity of the momentum equation is also much wider than the ideal MHD conditions would imply, although the reasons involve considerably more subtle physics. Recall that the collision dominated assumption is required to neglect $\boldsymbol{\Pi}_{i}$ and $\Pi_{e}$. In a collisionless plasma the magnetic field in a certain sense plays the role of collisions for the perpendicular motion; that is, perpendicular to the field, particles are confined to the vicinity of a given field line executing nearly (two-dimensional) isotropic motion if their gyro radius is much smaller than the characteristic plasma dimension. In fact, a calculation of $\boldsymbol{\Pi}_{\perp i}$ in the collisionless regime (see, for instance, Bowers and Haines (1971)) shows that for the MHD ordering $\Pi_{\perp i} / p_{i} \sim r_{L i} / a \ll 1$. Therefore, the perpendicular motion is fluid-like, implying that the perpendicular components of the momentum equation provide an excellent description of plasma behavior in either the collision dominated or collisionless regimes." 96 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Because of the poor coupling of equilibria with this shape to the TCV vacuum vessel, we use a conformal wall with the distance chosen ( $d=1.275 a$ ) to give the same value of $l_{i, 0}$ as the TCV dee configuration at zero pressure." 97 | 98 | zh = client.trans_text(en) 99 | print(zh) 100 | toc=time() 101 | print(f"耗时 {toc-tic:.4f} s") -------------------------------------------------------------------------------- /translators/qwen_translator.py: -------------------------------------------------------------------------------- 1 | import openai,json,yaml,os,logging,datetime 2 | from time import sleep,time 3 | 4 | 5 | def create_client(): 6 | print("[**] Qwen为您服务!") 7 | class myclient(openai.OpenAI): 8 | def __init__(self): 9 | self.translator_name="qwen" 10 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 11 | logging.warning("翻译器:"+self.translator_name) 12 | 13 | # with open('translator_keys/openai_keys.json', 'r') as file: 14 | # keys = json.load(file) 15 | with open('设置.yaml', 'r',encoding="utf8") as file: self.config=yaml.load(file,Loader=yaml.Loader) 16 | for apidir in self.config["翻译设置"]["翻译APIkeys文件夹"]: 17 | if os.path.exists(apidir): 18 | print("[**] 读取API:"+apidir+'/qwen_keys.yaml') 19 | break 20 | with open( apidir+'/qwen_keys.yaml', 'r',encoding="utf8") as file: 21 | self.keys=yaml.load(file,Loader=yaml.Loader) # 读取成一个dict 22 | 23 | if not self.keys["api_key"]: 24 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 25 | logging.error("[error]未找到翻译器API keys") 26 | input("按回车退出……") 27 | exit() 28 | 29 | super().__init__(api_key=self.keys["api_key"], base_url=self.keys["base_url"]) 30 | 31 | 32 | 33 | def trans_text(self,text): 34 | 35 | with open("glossaries/fusion_glossary_distill.csv",'r',encoding="utf8") as f: 36 | # with open("glossaries/void.csv",'r',encoding="utf8") as f: 37 | glsy=f.readlines() 38 | 39 | glsylist=[] 40 | for l in glsy: 41 | cut=l.strip().split(",") 42 | glsylist.append({"source":cut[0],"target":cut[1]}) 43 | 44 | 45 | translation_options = { 46 | "source_lang": "English", 47 | "target_lang": "Chinese" 48 | } 49 | translation_options["terms"]=glsylist 50 | 51 | response = self.chat.completions.create( 52 | model="qwen-mt-turbo", 53 | messages=[ 54 | {"role": "user", "content": text}, 55 | ], 56 | extra_body={ 57 | "translation_options": translation_options 58 | } 59 | ) 60 | resulttext=response.choices[0].message.content 61 | 62 | print(response) 63 | return resulttext 64 | 65 | # def trans_text(self,text): 66 | # return self.asksth("将下面这段latex格式论文文本翻译为中文(直接输出结果):"+text) 67 | 68 | 69 | return myclient() 70 | 71 | 72 | if __name__=="__main__": 73 | tic=time() 74 | 75 | client=create_client() 76 | en="the kinetic theory in plasma physics" 77 | # en=r"The validity of the momentum equation is also much wider than the ideal MHD conditions would imply, although the reasons involve considerably more subtle physics. Recall that the collision dominated assumption is required to neglect $\boldsymbol{\Pi}_{i}$ and $\Pi_{e}$. In a collisionless plasma the magnetic field in a certain sense plays the role of collisions for the perpendicular motion; that is, perpendicular to the field, particles are confined to the vicinity of a given field line executing nearly (two-dimensional) isotropic motion if their gyro radius is much smaller than the characteristic plasma dimension. In fact, a calculation of $\boldsymbol{\Pi}_{\perp i}$ in the collisionless regime (see, for instance, Bowers and Haines (1971)) shows that for the MHD ordering $\Pi_{\perp i} / p_{i} \sim r_{L i} / a \ll 1$. Therefore, the perpendicular motion is fluid-like, implying that the perpendicular components of the momentum equation provide an excellent description of plasma behavior in either the collision dominated or collisionless regimes." 78 | en=r" Also shown in Fig. 3 are two additional cases that compare the variation of the shape at the two different elongations. The first case has the high elongation ( $\kappa=3$ ) of the TCV dee shape, but with higher triangularity ( $\delta=0.6$ ) and no squareness $(\lambda=0)$. Because of the poor coupling of equilibria with this shape to the TCV vacuum vessel, we use a conformal wall with the distance chosen ( $d=1.275 a$ ) to give the same value of $l_{i, 0}$ as the TCV dee configuration at zero pressure." 79 | 80 | zh = client.trans_text(en) 81 | print(zh) 82 | toc=time() 83 | print(f"耗时 {toc-tic:.4f} s") -------------------------------------------------------------------------------- /translators/tencent_translator.py: -------------------------------------------------------------------------------- 1 | from tencentcloud.common import credential 2 | from tencentcloud.tmt.v20180321 import tmt_client, models 3 | from time import sleep 4 | 5 | import json,os,yaml,logging,datetime 6 | 7 | # =========== 腾讯翻译API========== 8 | # 安装: pip3.11 install --upgrade tencentcloud-sdk-python 9 | 10 | def create_client(): 11 | print('[**] 腾讯翻译为您服务') 12 | # 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 13 | # 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 14 | # 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 15 | 16 | class TencentClient(tmt_client.TmtClient): 17 | def __init__(self): 18 | self.translator_name="tencent" 19 | logging.basicConfig(filename=f"log{datetime.datetime.now().strftime('%y%m')}.txt", level=logging.WARNING, format='[%(asctime)s] %(message)s',encoding="utf8") 20 | logging.warning("翻译器:"+self.translator_name) 21 | 22 | with open('设置.yaml', 'r',encoding="utf8") as file: self.config=yaml.load(file,Loader=yaml.Loader) 23 | for apidir in self.config["翻译设置"]["翻译APIkeys文件夹"]: 24 | if os.path.exists(apidir): 25 | print("[**] 读取API:"+apidir+'/tencent_keys.yaml') 26 | break 27 | print("[**] 术语表id:"+str(self.config["翻译设置"]["tencent-要用的术语表id"])) 28 | 29 | with open( apidir+'/tencent_keys.yaml', 'r',encoding="utf8") as file: 30 | self.keys=yaml.load(file,Loader=yaml.Loader) 31 | 32 | if not self.keys["id"]: 33 | print("[error] 你还没填写翻译器API keys!请到 {apidir}/ 中填写。若还没有API,申请方法请见README!") 34 | logging.error("[error]未找到翻译器API keys") 35 | input("按回车退出……") 36 | exit() 37 | 38 | cred = credential.Credential(self.keys['id'], self.keys['key']) 39 | 40 | super().__init__(cred, "ap-beijing") 41 | 42 | def trans_text(self,en): 43 | req = models.TextTranslateRequest() 44 | params = { 45 | "Source": "en", 46 | "Target": "zh", 47 | "ProjectId": 0, 48 | "SourceText": en, 49 | "TermRepoIDList":self.config["翻译设置"]["tencent-要用的术语表id"], 50 | } 51 | req.from_json_string(json.dumps(params)) 52 | 53 | # 返回的resp是一个TextTranslateBatchResponse的实例,与请求对象对应 54 | resp = self.TextTranslate(req) 55 | 56 | # 输出 57 | text_zh=resp.TargetText 58 | return text_zh 59 | 60 | 61 | 62 | return TencentClient() 63 | 64 | # def translator(client,text): 65 | # # 实例化一个请求对象,每个接口都会对应一个request对象 66 | # req = models.TextTranslateRequest() 67 | # params = { 68 | # "Source": "en", 69 | # "Target": "zh", 70 | # "ProjectId": 0, 71 | # "SourceText": text 72 | # } 73 | # req.from_json_string(json.dumps(params)) 74 | 75 | # # 返回的resp是一个TextTranslateBatchResponse的实例,与请求对象对应 76 | # resp = client.TextTranslate(req) 77 | 78 | # # 输出 79 | # text_zh=resp.TargetText 80 | # sleep(0.2) # 每秒最多请求5次,可以删掉这行来搞快点 81 | # return client, text_zh 82 | 83 | if __name__=="__main__": # 测试用 84 | c=create_client() 85 | t_en="THE ELECTRON KINETIC EQUATION" 86 | 87 | t_zh=c.trans_text(t_en) 88 | print(t_en,'\n',t_zh) -------------------------------------------------------------------------------- /translators/test_translator.py: -------------------------------------------------------------------------------- 1 | import random,re 2 | 3 | 4 | 5 | def create_client(): 6 | print("[**] 假文测试!") 7 | class lorem_client: 8 | def __init__(self): 9 | self.translator_name="lorem" 10 | self.seed =["的","了","在","是","和","一","这","有","他","我","也","不","就","地","着","中","上","说","都","人","个","对","种","把","为","要","你","而","来","我们","又","一个","与","从","年","到","还","它","大","等","她","两","去","没有","里","得","时","多","他们","发展","用","那","以","所","很","可以","使","但","自己","小","之","能","下","或","看","就是","被","什么","三","这个","会","好","可","后","这样","给","向","社会","由","进行","问题","工作","如","呢","于","其","起来","国家","过","不能","并","这些","生产","生活","只","将","新","想","几","因为","不是","经济","更","研究","已","当","却","主要","再","由于","我国","最","关系","作用","不同","中国","才","人们","出","但是","现在","则","需要","所以","因此","如果","已经","一定","们","各","重要","象","一些","情况","吧","二","次","月","便","知道","时候","做","必须","成","人民","四","走","出来","活动","同","方面","条","高","吗","科学","也是","即","条件","天","许多","通过","思想","发生","叫","为了","老","过程","比","起","而且","影响","方法","要求","内","技术","点","一般","较","让","具有","形成","对于","日","事","时间","认为","还是","真","长","世界","只有","以后","教育","它们","同时","性","表现","产生","出现","企业","社会主义","作","者","没","各种","之间","家","组织","前","水","一样","成为","可能","根据","开始","吃","还有","话","存在","地方","变化","可是","革命","作为","这里","提高","五","同志","跟","以及","见","发现","及","一切","运动","呀","每","听","历史","地区","第一","物质","问","外","你们","位","正","形式","打","认识","那么","例如","学生","政治","比较","全","儿","应","第二","怎么","经过","提出","艺术","自然","头","过去","领导","完全","东西","其他","无","得到","劳动","本","谁","决定","结构","党","现象","受","理论","虽然","带","学习","孩子","特别","工业","啊","一点","建立","管理","文化","利用","先","人类","应该","建设","图","规定","有些","精神","基本","声","结果","看到","手","连","大家","时期","啦","意义","法","十","另","其中","才能","能够","分","间","当时","因","美国","解决","指","只是","语言","增加","内容","该","计划","笑","今天","相","不仅","注意","群众","联系","曾","水平","类","快","使用","写","分析","当然","既","有关","实现","此","系统","直接","不过","按","说明","产品","张","总","全国","基础","十分","市场","找","斗争","环境","特点","为什么","学","于是","反映","引起","创造","参加","甚至","讲","坐","能力","像","开","觉得","一下","民族","放","具体","知识","有的","包括","下来","部门","结合","岁","正确","任务","部分","那些","不会","任何","太","眼睛","经验","实际","随着","农业","道","极","少","不断","这时","最后","件","单位","句","数","而是","表示","之后","关于","六","整个","心","性质","受到","政府","至","到了","作品","青年","目的","工人","规律","农民","元","变","实行","力量","非","一起","先生","后来","名","请","然后","干","办法","站","并不","制度","钱","有人","心理","怎样","原则","多少","处","原来","那个","等等","商品","干部","部","实践","您","所谓","低","行为","第","统一","拿","日本","矛盾","以上","大量","死","个人","指出","然而","代表","学校","原因","几个","达到","因素","感到","实验","地位","方向","正在","因而","程度","并且","完成","造成","八","回来","改变","往往","看见","政策","目前","半"] 11 | self.seed_punc = ",,,,,,,、、;;。。。。——!?" 12 | 13 | def lorem_zh(self,text): 14 | 15 | output=text.split(" ") 16 | i=0 17 | I=random.randint(1,15) 18 | for j,s in enumerate(output): 19 | if not re.search(r'xx\d\d',s): 20 | output[j]=random.choice(self.seed) 21 | i=i+1 22 | if i>=I: 23 | output[j]=output[j]+random.choice(self.seed_punc) 24 | i=0 25 | I=random.randint(1,10) 26 | 27 | if not re.search('。',output[-1]): 28 | output[-1]=output[-1]+"。" 29 | 30 | # print(output) 31 | return "".join(output) 32 | 33 | def trans_text(self,text): 34 | return self.lorem_zh(text) 35 | 36 | return lorem_client() 37 | 38 | def translator(client, text): 39 | # word_len=len(text.split()) 40 | # zh_len=word_len*1.2 41 | return client,client.lorem_zh(text) -------------------------------------------------------------------------------- /样例202502/471-1993-Ward.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/471-1993-Ward.pdf -------------------------------------------------------------------------------- /样例202502/471-1993-Ward.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt]{article} 2 | \usepackage[utf8]{inputenc} 3 | \usepackage[T1]{fontenc} 4 | \usepackage{amsmath} 5 | \usepackage{amsfonts} 6 | \usepackage{amssymb} 7 | \usepackage[version=4]{mhchem} 8 | \usepackage{stmaryrd} 9 | \usepackage{graphicx} 10 | \usepackage[export]{adjustbox} 11 | \graphicspath{ {./images/} } 12 | 13 | \title{PRESSURE AND INDUCTANCE EFFECTS ON THE VERTICAL STABILITY OF SHAPED TOKAMAKS } 14 | 15 | \author{D.J. WARD, A. BONDESON, F. HOFMANN\\ 16 | (Centre de recherches en physique des plasmas, Association Euratom-Confédération Suisse, Ecole polytechnique fédérale de Lausanne, Lausanne, Switzerland)} 17 | \date{} 18 | 19 | 20 | \begin{document} 21 | \maketitle 22 | \section{LETTERS} 23 | 24 | 25 | \begin{abstract} 26 | Numerical calculations are presented to show the influence of pressure and inductance on the vertical stability of shaped tokamaks. High values of $\epsilon \beta_{p}$ improve the vertical stability of dee shaped tokamaks but are destabilizing for an inverse dee. For elongated cross-sections, the pressure effect is well described by a linear dependence of the maximum value of the stable internal inductance $l_{\mathrm{i}}$ on $\epsilon \beta_{\mathrm{p}}$, with a coefficient that depends on the geometry and increases with the triangularity. Stability diagrams are shown in terms of $l_{\mathrm{i}}$ versus $\epsilon \beta_{\mathrm{p}}$ for TCV- and DIII-D-like crosssections. Current profile effects depend critically on the wall configuration: low values of $l_{\mathrm{j}}$ are stabilizing if the wall is close, but increase the driving force of the instability in the absence of a wall. The competition between these two effects is considered for a configuration with discrete external conductors. 27 | \end{abstract} 28 | 29 | \section{INTRODUCTION} 30 | Modern tokamaks are generally designed so as to take advantage of the increased current capability of an elongated cross-section and the resulting improvement of the beta limit [1,2] and confinement time [3]. A well known drawback of elongation is vertical instability $[4,5]$, which requires the use of conducting walls close to the plasma assisted by active feedback stabilization on the $L / R$ time-scale of the resistive wall. Work on the DIII-D tokamak has established that vertical instability is the factor that limits the achievable elongation [2, 6]. For the TCV experiment [7] in Lausanne, designed for a maximum elongation of $\kappa=3$, the vertical stability is a major issue, and we have therefore investigated numerically the operational limits due to the vertical instability and how these depend on, e.g., the shape of the plasma cross-section and the equilibrium profiles. 31 | 32 | It is found experimentally [8] that the vertical stability of strongly elongated tokamaks is favoured by a low internal inductance $l_{\mathrm{i}}$, because this increases the coupling of the plasma current to the surrounding wall. Vertical stability requires an internal inductance less than some threshold value $l_{\mathrm{i}, \text { crit }}$, which decreases with\\ 33 | increasing elongation and wall distance. Here, we mean by $l_{\mathrm{i}, \text { crit }}$ the value of $l_{\mathrm{i}}$ for which a plasma surrounded by a realistic resistive wall has an $n=0$ growth rate, $\gamma_{\text {crit }}$, below which the vertical position can be controlled by a practical feedback system. 34 | 35 | Our principal result is that $l_{\mathrm{i}, \text { crit }}$ is strongly influenced by pressure in combination with triangular shaping of the cross-section. We find numerically that $l_{i, \text { crit }}$ is an approximately linear function of $\epsilon \beta_{\mathrm{p}}$, independent of the details of the current profile and aspect ratio, but sensitively dependent on the geometry of the crosssection and the distance to the wall. For the usual dee shape, pressure is stabilizing, i.e. $l_{\mathrm{i} \text {, crit }}$ increases with $\epsilon \beta_{\mathrm{p}}$, whereas in an inverse dee, pressure is destabilizing. The increased upper limit in internal inductance for a normal dee is a favourable effect, not only because it makes it possible to reach a higher elongation, but also because the beta limit $[2,9]$ and confinement time [10] improve with the internal inductance at fixed elongation. Reference [2] shows convincing evidence that the optimum condition for reaching high beta is at the intersection of the $n=0$ and $n=1$ stability boundaries, where $n$ is the toroidal mode number. 36 | 37 | The stabilizing effect of low inductance $l_{\mathrm{i}}$ is due to improved wall coupling in configurations with a completely surrounding wall. However, broad current profiles tend to give higher ideal growth rates with the wall at infinity. Here, we shall discuss the competition of these effects for a configuration where the wall is replaced by discrete conductors. 38 | 39 | \section{STABILITY DIAGRAMS FOR TCV AND DIII-D CROSS-SECTIONS} 40 | Figure 1 shows the limit in internal inductance $l_{\mathrm{i}, \text {, rit }}$ as a function of $\epsilon \beta_{p}$ for three different classes of current profiles in a 'TCV cross-section' at aspect ratio $A=1 / \epsilon=R_{0} / a=3.7$ (curves $1-3$ ). The following definitions are used for the poloidal beta:\\ 41 | $\beta_{\mathrm{p}} \equiv \frac{4}{\mu_{0} I_{\mathrm{p}}^{2} R_{0}} \int_{\mathrm{pt}} p \mathrm{~d}^{3} x$\\ 42 | and internal inductance\\ 43 | $l_{\mathrm{i}} \equiv \frac{2}{\mu_{0}^{2} I_{\mathrm{p}}^{2} R_{0}} \int_{\mathrm{p} \ell} B_{\mathrm{p}}^{2} \mathrm{~d}^{3} x$\\ 44 | The plasma-vacuum boundary is specified as\\ 45 | $R / a=A+\cos (\theta+\delta \sin \theta+\lambda \sin 2 \theta)$\\ 46 | $Z / a=\kappa \sin \theta$\\ 47 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-3} 48 | 49 | FIG. 1. Vertical stability diagram in terms of $1_{i, \text { crit }}$ and $\epsilon \beta_{p}$ for the TCV configuration. Curves $1-3$ show the results for the standard TCV configuration for three different types of current profiles. Curve 4 shows the results for the TCV plasma and wall shape expanded to an aspect ratio of $\mathrm{R}_{0} / \mathrm{a}=7.0$ for the first current profile.\\ 50 | and the geometry referred to as 'TCV dee' has elongation $\kappa=3$, triangularity $\delta=0.5$ and squareness $\lambda=0.2$. Equilibria have been computed with the CHEASE code [11] and stability with the NOVA-W code [12], which is capable of computing the growth rates of $n=0$ modes with a resistive wall, as well as with an ideal wall or with no wall. Figure 1 refers to resistive wall instabilities (cases that are stable with an ideal wall), and it is assumed that the mode can be stabilized by active feedback control if the resistive wall growth time is longer than $7 \%$ of the $L / R$ time of the wall (more precisely, for its ' $m=1$ ' eigenmode), i.e. 0.5 ms . The conducting wall represents the TCV vacuum vessel [7]. 51 | 52 | Several conclusions can be drawn from Fig. 1. Firstly, the limit in $l_{\mathrm{i}}$ is the same function of $\beta_{\mathrm{p}}$ for the three different classes of current profiles. The three current profiles differ significantly, and Fig. 2 shows the profiles 1 and 3 for the surface averaged toroidal current density $I^{*}$ at the point $l_{\mathrm{i}}=l_{\mathrm{i}, \text { crit }}$ at low and high pressures ( $\epsilon \beta_{\mathrm{p}}=0$ and 0.5 , respectively). (The pressure profiles have been chosen as uniformly scaled versions of those that give the ballooning limit with a\\ 53 | given $I^{*}$ profile.) Secondly, curve 4 refers to an equilibrium with a larger aspect ratio, $A=7$. The large aspect ratio result coincides almost exactly with that for $A=3.7$ when it is plotted in terms of $l_{\mathrm{i}}$ and $\epsilon \beta_{\mathrm{p}}$. Thus, for a fixed, elongated cross-section (but with varying current profile and aspect ratio) $n=0$ stability requires $l_{\mathrm{i}}1$, destabilizes vertical shifts but that a weakly elongated equilibrium can be stabilized by finite aspect ratio effects without the use of a conducting shell. Vertical displacements are stable if the decay index $n$ of the external vertical field satisfies $n \equiv-\left(R_{0} / B_{z}^{\text {ext }}\right)\left(\partial B_{z}^{\text {ext }} / \partial R\right)_{R=R_{0}}>0$. 73 | 74 | Zakharov's expression [4,5] for $n$ implies that a plasma with a flat current profile is vertically stable when\\ 75 | $\kappa-1<\left(\frac{a}{R_{0}}\right)^{2}\left(\frac{3}{4} \ln \frac{8 R_{0}}{a}-\frac{17}{16}\right)$\\[0pt] 76 | Laval et al. [13] showed that an elongated plasma can be stabilized by a conducting wall. For a flat current profile, their stability condition (in the near circular approximation) is\\ 77 | $\kappa-1<2\left(\frac{a}{d}\right)^{2}$\\ 78 | where $d$ is the wall radius. Comparison of the conditions (2) and (3) shows that for the elongations, aspect ratios and wall distances typical of modern tokamaks, wall stabilization is far more important than finite aspect ratio effects [21], and the discharges would be strongly unstable without a wall. 79 | 80 | The effects of more complex shaping, including finite aspect ratio and pressure effects, were investigated semi-analytically for a surface current distribution by Rebhan and Salat [17]. For vertically elongated equilibria, they found that an inverse dee ( $\delta<0$ ) is destabilized by pressure, but a standard dee ( $\delta>0$ ) can be stabilized by pressure (see Fig. 4(a) of Ref. [17]). A stabilizing effect of finite pressure in combination with positive triangularity on the vertical stability of elongated equilibria is also indicated by the results [19] obtained with the ERATO stability code. This effect is the basic reason for the increased value of $l_{\mathrm{i}, \text { crit }}$ at high $\epsilon \beta_{\mathrm{p}}$ in the operational diagrams, Figs 1 and 3. The main new result shown in these diagrams is the appreciable size of the pressure effect on vertical stability in terms of the operational parameters, $l_{\mathrm{i}}$ and $\epsilon \beta_{\mathrm{p}}$, for more realistic current distributions than the surface current model of Ref. [17]. 81 | 82 | It has been shown $[14,18]$ that resistive wall growth rates (for equilibria that are unstable without a wall but stable with an ideally conducting wall) can be expressed in terms of the ideal MHD potential energies of the vertical shift mode in the absence of a wall, $\delta W_{\infty}$, and with an ideally conducting wall in the position of the resistive wall, $\delta W_{\mathrm{d}}$, as\\ 83 | $\gamma_{\mathrm{res}}=-\left(b / \tau_{\mathrm{w}}\right) \delta W_{\infty} / \delta W_{\mathrm{d}}$\\ 84 | Here, $\tau_{\mathrm{w}}$ is the $L / R$ time of the wall and $b$ is a numerical factor that depends on the current distribution in the wall. This expression gives valuable analytical insight. However, for numerical calculations it is more straightforward to introduce a resistive wall and solve the full eigenvalue problem as is done by NOVA-W. This automatically takes into account the effects of non-rigid displacements [22] and avoids the calculation of $\delta W_{\mathrm{d}}$ for a stable oscillatory mode which can be hidden by a continuous spectrum. 85 | 86 | In the following two sections, we show the vertical stability results for ideal and resistive walls obtained with the NOVA-W code with the aim of placing the results for TCV dee and DIII-D cross-sections into a broader framework.\\ 87 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-6} 88 | 89 | FIG. 4. Growth rates (in $\mathrm{s}^{-1}$ ) versus triangularity for a resistive wall conformal to the plasma shape at a midplane distance of $\mathrm{d}=1.3 \mathrm{a}$ for seversal shapes ranging from the inverse dee $(\delta=-0.6)$ to the regular dee $(\delta=0.6)$ at high beta $\left(\beta_{p}=0.6\right)$ and low beta $\left(\beta_{p}=0.06\right)$.\\ 90 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-6(1)} 91 | 92 | F1G. 5. Plot of the square of the normalized ideal wall MHD growth rate $\gamma_{N}^{2}$ versus $\mathrm{a}^{2} / \mathrm{d}^{2}$, with an ideally conducting wall. The results are shown for three shapes (inverse dee, ellipse, regular dee) at high $\beta_{p}$ (solid symbols) and low $\beta_{p}$ (open symbols). 93 | 94 | \section{PRESSURE EFFECTS} 95 | The operational diagrams in Figs 1 and 3 show a much stronger stabilizing effect of $\epsilon \beta_{\mathrm{p}}$ in the DIII-Dlike cross-section ( $\kappa=2.5, \delta=0.6, \lambda=0$ ) than for the TCV dee shape ( $\kappa=3.0, \delta=0.5, \lambda=0.2$ ).\\ 96 | Figure 3 shows that the most important reason for this difference is the more triangular shape of DIII-D (note that a positive $\lambda$ decreases the effective triangularity [9]). The strong dependence of the pressure effect on triangularity is illustrated by Fig. 4. This figure shows resistive wall growth rates for elongated crosssections ( $\kappa=2.5, A=3$ ) at low and high pressures ( $\beta_{p}=0.06$ and 0.6 , respectively) and at several different triangularities ranging from $\delta=-0.6$ (inverse dee) to $\delta=+0.6$ (standard dee). The wall is a conformal copy of the plasma surface with minor radius $d=1.3 a$ and has the same resistivity and thickness as the TCV vacuum vessel used for Fig. 1. Pressure is strongly destabilizing for the inverse dee, somewhat stabilizing for the ellipse and clearly stabilizing for the standard dee. The inverse dee is strongly destabilized, and with $\beta_{\mathrm{p}}=0.6$ the mode is near marginal stability with an ideally conducting wall, see Fig. 5. 97 | 98 | Figure 5 shows the square of the normalized ideal wall MHD growth rate (a measure of the ideal MHD driving energy) versus the reciprocal wall radius squared for three different triangularities ( $\delta=-0.6$, $0.0,0.6$ ) and for both high and low pressures. The dee shape is clearly the most stable among all the cases. For this configuration, a finite pressure is significantly stabilizing in the absence of a wall and remains so when wall stabilization is accounted for. 99 | 100 | By contrast, for the inverse dee, pressure is clearly destabilizing both with and without a wall. The critical wall distance for the inverse dee is quite close to $d=1.3 a$, and therefore the resistive wall growth rate (with the wall at that position) is very large in Fig. 4 for that case. For the pure ellipse, the free space growth rate is virtually the same for the low and high pressure cases, but high pressure shows a stabilizing influence in the presence of a wall, and the growth rate falls below that for the inverse dee as the wall is moved inward. 101 | 102 | Plots of the equilibrium flux surfaces show that, for the dee shape, increased pressure reduces the central elongation. This can be interpreted as the result of squeezing in the vertical direction by the combination of triangular shape and the Shafranov shift. The same effect leads to an increased elongation at high $\beta_{p}$ in an inverse dee. 103 | 104 | \section{LETTERS} 105 | We conclude that the primary effect of pressure on the dee shape is to lower the free space driving energy. Conversely, pressure increases the free space energy for the inverse dee. Thus, the favourable effect of pressure shown in the operational diagrams, Figs 1 and 3 , is mainly due to the lowering of the free space driving energy and not to its effect on the wall coupling. For the ellipse, the free space growth rates are virtually unaffected by pressure, but there is an increase in the wall stabilization for the high pressure case. 106 | 107 | \section{CURRENT PROFILE EFFECTS} 108 | It is well known that the current profile strongly influences the vertical stability. The almost identical results for different classes of current profiles in Fig. 1 show that the relevant parameter characterizing the current distribution is the internal inductance. Flat current profiles with low internal inductance lead to stronger coupling between the plasma and the external conductors. However, we find computationally that, in the absence of a conducting shell, the growth rate generally increases with decreasing inductance (see also Ref. [20]). This is shown in Fig. 6, where the ideal wall growth rate is plotted as a function of the wall radius for two DIII-D shaped equilibria with different internal inductances, $l_{\mathrm{i}}=0.6$ and 0.8 , respectively. 109 | 110 | Peaking of the current profile is evidently stabilizing when the wall is distant but destabilizing when the wall is sufficiently close. At a wall distance of roughly $d=1.4 a$, the two curves in Fig. 6 cross, and the growth rate is independent of the inductance. This point is close to the critical wall distance. Therefore, the internal inductance has a rather small effect on the marginal position of the ideal wall, but it has a much stronger effect on the resistive growth rates with a close fitting wall [14]. In fact, with the wall at $d=1.3 a$, the two cases in Fig. 6 have nearly a factor of two difference in the resistive growth rate. The reduction of the free space growth rate with increasing inductance appears to be due mainly to a reduction of the ellipticity of the central flux surfaces. It should be noted that there are many competing effects, for example a similar reduction of the central triangularity, which reduces the finite pressure stabilization. In addition, peaking of the current profile effectively increases the aspect ratio, so that the toroidal stabilization is reduced. However, as discussed in Section 3, the toroidal stabilization is insignificant for highly elongated cross-sections.\\ 111 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-7} 112 | 113 | FIG. 6. Plot of $\gamma_{N}^{2}$ versus $\mathrm{a}^{2} / \mathrm{d}^{2}$ with an ideally conducting wall for DIII-D-like equilibria with no pressure for $1_{i}=0.6$ (dashed curve) and for $1_{i}=0.8$ (solid curve). 114 | 115 | \subsection{Passive stabilization by discrete conductors} 116 | While the effect of broadening the current profile increases the destabilizing force on the equilibrium, it also increases the stabilizing effect of a completely surrounding conducting wall. The balance between these competing effects is changed if the passive stabilization is provided primarily by discrete conductors instead of a complete, surrounding wall. As an example, we consider the configuration indicated in Fig. 7. The equilibrium has $\kappa=1.9, \delta=0.7$ and $A=4.54$. Figure 8 shows that in this configuration the growth rate increases with decreasing $l_{\mathrm{i}}$. This effect has been observed previously by Pearlstein [23] and by Jardin [24]. 117 | 118 | An interesting comparison is obtained by replacing the discrete conductors by the complete wall, as indicated by a dotted contour in Fig. 7. The total wall resistance was normalized to that of the passive conductors. Figure 8 shows that with the closed wall configuration the growth rate decreases monotonically with decreasing $l_{\mathrm{i}}$. 119 | 120 | Figure 7 shows the contours of perturbed flux for the cases of (a) high and (b) low $l_{\mathrm{i}}$ in Fig. 8. While the coupling of the perturbed flux to the closed wall is\\ 121 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-8(1)} 122 | 123 | FIG. 7. The plasma boundary, the discrete conductor sets and (shown as a dotted contour) a fictitious completely surrounding wall for the comparison in Fig. 8. The vacuum vessel is quite distant from the plasma. The perturbed flux contours are shown for two equilibria with (a) high $1_{i}$ and (b) low $1_{i}$ in the configuration with discrete conductors.\\ 124 | \includegraphics[max width=\textwidth, center]{2025_01_10_a0135324997886412d98g-8} 125 | 126 | FIG. 8. Growth rates (in $s^{-1}$ ) versus $1_{i}$ for the configuration in Fig. 7 stabilized by discrete conductors with the vacuum vessel far from the plasma. For comparison, growth rates are shown with a completely surrounding wall (conformal to the plasma surface at $\mathrm{d}=1.3 \mathrm{a}$ ).\\ 127 | improved in the low $l_{i}$ case, the coupling to the discrete conductors is not. Therefore, the increase in the destabilizing force due to the broader current profile dominates, and the growth rate increases with decreasing $l_{\mathrm{i}}$. 128 | 129 | We conclude that, for highly elongated tokamaks, there are two main effects of the internal inductance on vertical stability. Firstly, wall stabilization is improved for low internal inductance because of increased magnetic coupling. Secondly, current peaking reduces the shaping of the internal flux surfaces, which reduces the instability growth rate in the absence of a wall. For highly elongated, feedback stabilized discharges with a closed wall, the effect on wall coupling is more important, and stability improves at low inductance. However, when there is not a completely surrounding wall, the competition of these two effects is more subtle and depends on the details of the current profile and of the placement of the conductors. 130 | 131 | \section{CONCLUSIONS} 132 | We have found that high values of $\epsilon \beta_{\mathrm{p}}$ significantly improve the vertical stability of dee shaped tokamaks. 133 | 134 | \section{LETTERS} 135 | The effect can be described in terms of an almost linear dependence of the critical internal inductance on $\epsilon \beta_{\mathrm{p}}, l_{\mathrm{i}, \text { crit }} \approx l_{\mathrm{i}, 0}+c \epsilon \beta_{\mathrm{p}}$. Comparison between different cross-sections shows that the coefficient $c$ increases strongly with triangularity and decreases somewhat with elongation. For a DIII-D-like cross-section, the dependence of $l_{\mathrm{i}, \text { crit }}$ on $\epsilon \beta_{\mathrm{p}}$ is quite pronounced. This effect is beneficial for reaching high beta, because it increases the maximum stable elongation or, alternatively, allows the current profile to be more peaked, which increases the beta limit due to the $n=1$ external kink mode $[2,9]$. 136 | 137 | \section{ACKNOWLEDGEMENTS} 138 | This work was supported in part by the Swiss National Science Foundation. We acknowledge the work of H . Lütjens in adapting the CHEASE equilibrium code for NOVA-W. 139 | 140 | \section{REFERENCES} 141 | [1] TROYON, F., et al., Plasma Phys. Control. Fusion 26 (1984) 209.\\[0pt] 142 | [2] LAZARUS, E.A., et al., Phys. Fluids B 3 (1991) 2220; LAZARUS, E.A., et al., Phys. Fluids B 4 (1992) 3644.\\[0pt] 143 | [3] YUSHMANOV, P.N., et al., Nucl. Fusion 30 (1990) 1999.\\[0pt] 144 | [4] ZAKHAROV, L.E., Sov. Phys. - Tech. Phys. 16 (1971) 645 (English translation: Zh. Tekh. Fiz. 41 (1971) 823).\\[0pt] 145 | [5] MUKHOVATOV, V.S., SHAFRANOV, V.D., Nucl. Fusion 11 (1971) 605.\\[0pt] 146 | [6] LAZARUS, E.A., et al., Nucl. Fusion 30 (1990) 111.\\[0pt] 147 | [7] HOFMANN, F., et al., in Fusion Technology 1986 (Proc. 14th Symp. Avignon, 1986), Vol. 1, Pergamon Press, Oxford (1986) 687.\\[0pt] 148 | [8] TAYLOR, T.S., et al., in Plasma Physics and Controlled Nuclear Fusion Research 1990 (Proc. 13th Int. Conf. Washington, DC, 1990), Vol. 1, IAEA, Vienna (1991) 177 ; LAO, L.L., et al., Phys. Fluids B 4 (1992) 232.\\[0pt] 149 | [9] ERIKSSON, G., et al., in Plasma Physics (Proc. 1992 Int. Conf. Innsbruck), Vol. 16C, Part I, European Physical Society (1992) 343.\\[0pt] 150 | [10] ZARNSTORFF, M.C., et al., in Plasma Physics and Controlled Nuclear Fusion Research 1990 (Proc. 13th Int. Conf. Washington, DC, 1990), Vol. 1, IAEA, Vienna (1991) 109.\\[0pt] 151 | [11] LÜTJENS, H., et al., Comput. Phys. Commun. 69 (1992) 287.\\[0pt] 152 | [12] WARD, D.J., et al., J. Comput. Phys. 104 (1993) 221.\\[0pt] 153 | [13] LAVAL, G., et al., Phys. Fluids 17 (1974) 835.\\[0pt] 154 | [14] HANEY, S.W., FREIDBERG, J.P., Phys. Fluids B 1 (1989) 1637.\\[0pt] 155 | [15] ERIKSSON, H.G., Plasma Phys. Control. Fusion 34 (1992) 1721.\\[0pt] 156 | [16] REBHAN, E., Nucl. Fusion 15 (1975) 277.\\[0pt] 157 | [17] REBHAN, E., SALAT, A., Nucl. Fusion 16 (1976) 805.\\[0pt] 158 | [18] HOFMANN, F., SCHULTZ, C.G., in Controlled Fusion and Plasma Physics (Proc. 16th Eur. Conf. Venice, 1989), Vol. 13B, Part I, European Physical Society (1987) 335.\\[0pt] 159 | [19] BERNARD, L.C., et al., Nucl. Fusion 18 (1978) 1331.\\[0pt] 160 | [20] BECKER, G., LACKNER, K., in Plasma Physics and Controlled Nuclear Fusion Research 1976 (Proc. 6th Int. Conf. Berchtesgaden, 1976), Vol. 2, IAEA, Vienna (1977) 401.\\[0pt] 161 | [21] STAMBAUGH, R.D., et al., Nucl. Fusion 32 (1992) 1642.\\[0pt] 162 | [22] WARD, D.J., JARDIN, S.C., Nucl. Fusion 32 (1992) 973.\\[0pt] 163 | [23] PEARLSTEIN, L.D., Lawrence Livermore National Laboratory, personal communication, 1992.\\[0pt] 164 | [24] JARDIN, S.C., Plasma Physics Laboratory, Princeton University, personal communication, 1992.\\ 165 | (Manuscript received 21 December 1992\\ 166 | Final manuscript received 29 March 1993) 167 | 168 | 169 | \end{document} -------------------------------------------------------------------------------- /样例202502/[排版]471-1993-Ward.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/[排版]471-1993-Ward.pdf -------------------------------------------------------------------------------- /样例202502/[排版]471-1993-Ward.tex: -------------------------------------------------------------------------------- 1 | %---------------------------------------------------------------------------------------- 2 | % PACKAGES AND OTHER DOCUMENT CONFIGURATIONS 3 | %---------------------------------------------------------------------------------------- 4 | % \RequirePackage{silence} 5 | % \WarningsOff* 6 | % \batchmode 7 | % \documentclass[twoside,twocolumn]{article} 8 | \documentclass[utf8]{ctexart} 9 | \raggedbottom 10 | \usepackage{ctex} 11 | 12 | % ======== 通用设置 ======== 13 | 14 | % 页面布局 15 | \usepackage{geometry} 16 | \geometry{a4paper,top=3cm,bottom=3cm,inner=2cm,outer=2cm,marginparwidth=1.8cm} 17 | 18 | % 兼容utf8的字体设置 19 | \setmainfont{CMU Serif} 20 | % \setCJKmainfont[ItalicFont={华文楷体}]{思源宋体 CN} 21 | % 思源宋体CN下载:https://github.com/adobe-fonts/source-han-serif/releases/download/2.002R/14_SourceHanSerifCN.zip 22 | 23 | % 必备数学套件 24 | \usepackage{amsmath,amsthm,amsfonts,amssymb} 25 | \usepackage{bm,bbm,upgreek} 26 | 27 | % 图片导入配置 28 | \usepackage{graphicx} 29 | \usepackage[export]{adjustbox} 30 | % 搜寻图片的路径 31 | \graphicspath{ {./images/} } 32 | 33 | % 图注设置 34 | \usepackage[small,labelfont=bf,up,up,margin=2em]{caption} % Custom captions under/above floats in tables or figures 35 | 36 | % 公式、图等的编号设置 37 | \usepackage{chngcntr} 38 | % \counterwithout{figure}{chapter} 39 | % \counterwithin{equation}{section} 40 | 41 | % 列表设置 42 | \usepackage{enumitem} % Customized lists 43 | \setlist[itemize]{itemsep=0pt} % Make itemize lists more compact 44 | \setlist[enumerate]{itemsep=0pt,parsep=0pt,label={[\arabic*]}} 45 | 46 | % 页眉页脚 47 | \usepackage{fancyhdr} 48 | \pagestyle{fancy} 49 | \fancyfoot[EL,OR]{\bfseries· \thepage ·} 50 | \fancyfoot[C]{} 51 | \renewcommand{\headrulewidth}{0pt} 52 | 53 | % 标题设置 54 | \usepackage{titling} % Customizing the title section 55 | % 摘要环境设置(book模板中无效) 56 | \usepackage{abstract} % Allows abstract customization 57 | \renewcommand{\abstractnamefont}{\normalfont\bfseries} % Set the "Abstract" text to bold 58 | \renewcommand{\abstracttextfont}{\normalfont\small\itshape} % Set the abstract itself to small italic text 59 | 60 | % 色彩 61 | \usepackage[svgnames]{xcolor} % added by Wenyin for color 62 | 63 | % 超链接设置 64 | \usepackage[ 65 | colorlinks, 66 | linkcolor=blue, 67 | bookmarksnumbered=true, 68 | bookmarksopen=true 69 | ]{hyperref} 70 | % unicode支持:pdf目录可以正确显示公式 71 | \hypersetup{unicode, psdextra} 72 | % PDF目录自定义 73 | \usepackage{bookmark} 74 | \bookmarksetup{ 75 | open, 76 | numbered, 77 | addtohook={% 78 | \ifnum\bookmarkget{level}=0 % chapter 79 | \bookmarksetup{bold,color=orange}% 80 | \fi 81 | } 82 | } 83 | 84 | 85 | 86 | 87 | % ======== 可选设置 ======== 88 | 89 | % for multiple references with dash 90 | \usepackage[noadjust]{cite} 91 | \renewcommand{\citedash}{--} % when \usepackage{cite} 92 | 93 | % 额外数学包 94 | \usepackage{mathrsfs} % for \mathscr 95 | \usepackage{mathtools} % for $\intertext{text}$ 96 | \usepackage{breqn} % 一个可以自动公式断行的公式环境,效果一般 97 | \usepackage{mhchem} %化学式 98 | \usepackage{esint} 99 | 100 | % 表格类 101 | \usepackage{booktabs} % Horizontal rules in tables 102 | %\usepackage{longtable} % 长表格 103 | %\usepackage{tabu} % 强大的表格包 104 | %\usepackage{supertabular} 105 | 106 | % 杂技 107 | \usepackage{multirow} % 多栏布局 108 | \usepackage{ulem} % 下划线 109 | \usepackage{tikz} % 绘图工具 110 | \usepackage{framed} % 文字加框 111 | \usepackage{setspace} % 设置行间距等 112 | \usepackage{minitoc} % 小目录 113 | %\usepackage{tcolorbox} % 多彩盒子工具,巨复杂 114 | %\tcbuselibrary{skins,breakable,raster} 115 | \usepackage{float} % 图片位置:H 116 | \usepackage{multicol} % 普通多栏布局 117 | 118 | % 多文件 119 | \usepackage{subfiles} 120 | 121 | %代码抄录 122 | \usepackage{shortvrb} 123 | % \MakeShortVerb|* %|*·|*可以直接原文抄录为texttt 124 | %\usepackage{listings} 125 | %\lstset{ 126 | % language=[LaTeX]TeX, %语言 127 | % backgroundcolor=\color{yellow!10}, %背景颜色 128 | % basicstyle=\small\ttfamily, %基本字格式 129 | % keywordstyle=\bfseries\color{purple}, %关键字格式 130 | % commentstyle=\color{gray}, %注释格式 131 | % numbers=left, %行号 132 | % numberstyle=\ttfamily\small, %行号格式 133 | % breaklines, %允许断行 134 | % frame=shadowbox, %外框线 135 | % escapeinside={<@}{@>}, %逃逸部分,还给Latex编码 136 | % lineskip=0pt, %行距 137 | % xleftmargin=0.05\linewidth, 138 | % xrightmargin=0.05\linewidth, %盒子宽度 139 | % morekeywords={rowfont} %更多自定义关键词 140 | % } 141 | 142 | 143 | 144 | % 段落分栏包,实现中英对照排版的核心工具 145 | \usepackage{paracol} 146 | \setlength{\columnseprule}{0.5pt} 147 | \setlength{\columnsep}{2em} 148 | \columnratio{0.4} 149 | 150 | 151 | % ======== 自定义命令 ======== 152 | 153 | % 数学自定义 154 | \newcommand{\vect}[1]{\mathbf{\boldsymbol{#1}}} % works for both English and Greek letters, but it does not work with mathtime pro lite fonts, see https://tex.stackexchange.com/questions/3535/bold-math-automatic-choice-between-mathbf-and-boldsymbol-for-latin-and-greek 155 | % \newcommand{\matr}[1]{\boldsymbol{\mathrm{#1}}} % \matrix is defined in LaTeX2e kernel 156 | \newcommand{\tens}[1]{\boldsymbol{\mathrm{#1}}} 157 | \newcommand\ii{\symup{i}} 158 | \newcommand\ee{\symup{e}} 159 | \newcommand\dd{\symup{d}} 160 | \newcommand\ppi{\symup{\pi}} %常用的正体字符:i,e,d,\pi 161 | 162 | \renewcommand{\paragraph}[1]{\textbf{#1}} 163 | % ====== 对照排版的设置 ====== 164 | 165 | % ===中英文对照排版,四六开=== 166 | \columnratio{0.4} 167 | \newcommand\mainskip{-5pt} 168 | \newcommand\enzhbox[2]{ 169 | \quad\par \begin{paracol}{2} \colseprulecolor{black} 170 | \begin{spacing}{1.0} 171 | \footnotesize #1 172 | \end{spacing} 173 | \switchcolumn[1] 174 | #2 175 | \end{paracol} \quad\par 176 | } 177 | 178 | % ===中英文对照排版,五五开=== 179 | %\columnratio{0.48} 180 | %\newcommand\mainskip{-5pt} 181 | %\newcommand\enzhbox[2]{ 182 | % \quad\par \begin{paracol}{2} \colseprulecolor{black} 183 | % \begin{spacing}{1.0} 184 | % \small #1 185 | % \end{spacing} 186 | % \switchcolumn[1] 187 | % #2 188 | % \end{paracol} \quad\par 189 | %} 190 | 191 | % === 仅英文(#1)/仅中文(#2) === 192 | % \newcommand\mainskip{5pt} 193 | % \newcommand\enzhbox[2]{#1} 194 | %\newcommand\enzhbox[2]{#2} 195 | 196 | %%编号层级表 197 | %%-1 part 198 | %%0 chapter 199 | %%1 section 200 | %%2 subsection 201 | %%3 subsubsection 202 | %%4 paragraph 203 | %%5 subparagraph 204 | % % 章节标题编号深度 205 | % \setcounter{secnumdepth}{3} 206 | % % 目录深度 207 | % \setcounter{tocdepth}{2} 208 | % % 小目录深度 209 | % \setcounter{minitocdepth}{3} 210 | % \renewcommand\mtctitle{本章目录} 211 | 212 | %---------------------------------------------------------------------------------------- 213 | % TITLE SECTION 214 | %---------------------------------------------------------------------------------------- 215 | 216 | % \setlength{\droptitle}{-4\baselineskip} % Move the title up 217 | 218 | % \pretitle{\begin{center}\Huge\bfseries} % Article title formatting 219 | % \posttitle{\end{center}} % Article title closing formatting 220 | \title{PRESSURE AND INDUCTANCE EFFECTS ON THE VERTICAL STABILITY OF SHAPED TOKAMAKS } 221 | \author{D.J. WARD, A. BONDESON, F. HOFMANN et al.} 222 | 223 | \newcommand\paperref{D.J. WARD. 1993 Nucl. Fusion 33 821} 224 | 225 | \date{\paperref} 226 | \fancyhead[C]{\small \paperref} 227 | \fancyhead[L,R]{} 228 | \renewcommand\headrulewidth{0.6pt} 229 | \renewcommand{\maketitlehookd}{% 230 | \begin{abstract} 231 | Numerical calculations are presented to show the influence of pressure and inductance on the vertical stability of shaped tokamaks. High values of $\epsilon \beta_{p}$ improve the vertical stability of dee shaped tokamaks but are destabilizing for an inverse dee. For elongated cross-sections, the pressure effect is well described by a linear dependence of the maximum value of the stable internal inductance $l_{\mathrm{i}}$ on $\epsilon \beta_{\mathrm{p}}$, with a coefficient that depends on the geometry and increases with the triangularity. Stability diagrams are shown in terms of $l_{\mathrm{i}}$ versus $\epsilon \beta_{\mathrm{p}}$ for TCV- and DIII-D-like crosssections. Current profile effects depend critically on the wall configuration: low values of $l_{\mathrm{j}}$ are stabilizing if the wall is close, but increase the driving force of the instability in the absence of a wall. The competition between these two effects is considered for a configuration with discrete external conductors. 232 | \end{abstract} 233 | } 234 | 235 | %---------------------------------------------------------------------------------------- 236 | 237 | \begin{document} 238 | \begin{sloppypar} 239 | % \nonstopmode 240 | % \WarningsOff[latex] 241 | % 公式环境的一些设置 242 | \allowdisplaybreaks[3] 243 | \setlength{\abovedisplayskip}{-6pt} 244 | \setlength{\belowdisplayskip}{10pt} 245 | \setlength{\abovedisplayshortskip}{0pt} 246 | \setlength{\belowdisplayshortskip}{0pt} 247 | \setlength{\parskip}{\mainskip} 248 | 249 | % \setcounter{chapter}{3} 250 | \maketitle 251 | 252 | % ==document boby begins 253 | 254 | 255 | \section{INTRODUCTION} 256 | Modern tokamaks are generally designed so as to take advantage of the increased current capability of an elongated cross-section and the resulting improvement of the beta limit [1,2] and confinement time [3]. A well known drawback of elongation is vertical instability $[4,5]$, which requires the use of conducting walls close to the plasma assisted by active feedback stabilization on the $L / R$ time-scale of the resistive wall. Work on the DIII-D tokamak has established that vertical instability is the factor that limits the achievable elongation [2, 6]. For the TCV experiment [7] in Lausanne, designed for a maximum elongation of $\kappa=3$, the vertical stability is a major issue, and we have therefore investigated numerically the operational limits due to the vertical instability and how these depend on, e.g., the shape of the plasma cross-section and the equilibrium profiles. 257 | 258 | It is found experimentally [8] that the vertical stability of strongly elongated tokamaks is favoured by a low internal inductance $l_{\mathrm{i}}$, because this increases the coupling of the plasma current to the surrounding wall. Vertical stability requires an internal inductance less than some threshold value $l_{\mathrm{i}, \text { crit }}$, which decreases with increasing elongation and wall distance. Here, we mean by $l_{\mathrm{i}, \text { crit }}$ the value of $l_{\mathrm{i}}$ for which a plasma surrounded by a realistic resistive wall has an $n=0$ growth rate, $\gamma_{\text {crit }}$, below which the vertical position can be controlled by a practical feedback system. 259 | 260 | 261 | Our principal result is that $l_{\mathrm{i}, \text { crit }}$ is strongly influenced by pressure in combination with triangular shaping of the cross-section. We find numerically that $l_{i, \text { crit }}$ is an approximately linear function of $\epsilon \beta_{\mathrm{p}}$, independent of the details of the current profile and aspect ratio, but sensitively dependent on the geometry of the crosssection and the distance to the wall. For the usual dee shape, pressure is stabilizing, i.e. $l_{\mathrm{i} \text {, crit }}$ increases with $\epsilon \beta_{\mathrm{p}}$, whereas in an inverse dee, pressure is destabilizing. The increased upper limit in internal inductance for a normal dee is a favourable effect, not only because it makes it possible to reach a higher elongation, but also because the beta limit $[2,9]$ and confinement time [10] improve with the internal inductance at fixed elongation. Reference [2] shows convincing evidence that the optimum condition for reaching high beta is at the intersection of the $n=0$ and $n=1$ stability boundaries, where $n$ is the toroidal mode number. 262 | 263 | The stabilizing effect of low inductance $l_{\mathrm{i}}$ is due to improved wall coupling in configurations with a completely surrounding wall. However, broad current profiles tend to give higher ideal growth rates with the wall at infinity. Here, we shall discuss the competition of these effects for a configuration where the wall is replaced by discrete conductors. 264 | 265 | \section{STABILITY DIAGRAMS FOR TCV AND DIII-D CROSS-SECTIONS} 266 | Figure 1 shows the limit in internal inductance $l_{\mathrm{i}, \text {, rit }}$ as a function of $\epsilon \beta_{p}$ for three different classes of current profiles in a 'TCV cross-section' at aspect ratio $A=1 / \epsilon=R_{0} / a=3.7$ (curves $1-3$ ). The following definitions are used for the poloidal beta: 267 | \begin{align*} 268 | \beta_{\mathrm{p}} \equiv \frac{4}{\mu_{0} I_{\mathrm{p}}^{2} R_{0}} \int_{\mathrm{pt}} p \mathrm{~d}^{3} x 269 | \end{align*} 270 | 271 | and internal inductance 272 | \begin{align*} 273 | l_{\mathrm{i}} \equiv \frac{2}{\mu_{0}^{2} I_{\mathrm{p}}^{2} R_{0}} \int_{\mathrm{p} \ell} B_{\mathrm{p}}^{2} \mathrm{~d}^{3} x 274 | \end{align*} 275 | 276 | The plasma-vacuum boundary is specified as 277 | \begin{gather*} 278 | R / a=A+\cos (\theta+\delta \sin \theta+\lambda \sin 2 \theta) \tag{1}\\ 279 | Z / a=\kappa \sin \theta 280 | \end{gather*} 281 | 282 | 283 | 284 | 285 | and the geometry referred to as 'TCV dee' has elongation $\kappa=3$, triangularity $\delta=0.5$ and squareness $\lambda=0.2$. Equilibria have been computed with the CHEASE code [11] and stability with the NOVA-W code [12], which is capable of computing the growth rates of $n=0$ modes with a resistive wall, as well as with an ideal wall or with no wall. Figure 1 refers to resistive wall instabilities (cases that are stable with an ideal wall), and it is assumed that the mode can be stabilized by active feedback control if the resistive wall growth time is longer than $7 \%$ of the $L / R$ time of the wall (more precisely, for its ' $m=1$ ' eigenmode), i.e. 0.5 ms . The conducting wall represents the TCV vacuum vessel [7]. 286 | \begin{figure}[H] 287 | \centering 288 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-3} 289 | \caption{Vertical stability diagram in terms of $1_{i, \text { crit }}$ and $\epsilon \beta_{p}$ for the TCV configuration. Curves $1-3$ show the results for the standard TCV configuration for three different types of current profiles. Curve 4 shows the results for the TCV plasma and wall shape expanded to an aspect ratio of $\mathrm{R}_{0} / \mathrm{a}=7.0$ for the first current profile.\\} 290 | \label{fig1.} 291 | \end{figure} 292 | 293 | % ==AUTO MOVED 294 | 295 | Several conclusions can be drawn from Fig. 1. Firstly, the limit in $l_{\mathrm{i}}$ is the same function of $\beta_{\mathrm{p}}$ for the three different classes of current profiles. The three current profiles differ significantly, and Fig. 2 shows the profiles 1 and 3 for the surface averaged toroidal current density $I^{*}$ at the point $l_{\mathrm{i}}=l_{\mathrm{i}, \text { crit }}$ at low and high pressures ( $\epsilon \beta_{\mathrm{p}}=0$ and 0.5 , respectively). (The pressure profiles have been chosen as uniformly scaled versions of those that give the ballooning limit with a given $I^{*}$ profile.) Secondly, curve 4 refers to an equilibrium with a larger aspect ratio, $A=7$. The large aspect ratio result coincides almost exactly with that for $A=3.7$ when it is plotted in terms of $l_{\mathrm{i}}$ and $\epsilon \beta_{\mathrm{p}}$. Thus, for a fixed, elongated cross-section (but with varying current profile and aspect ratio) $n=0$ stability requires $l_{\mathrm{i}}1$, destabilizes vertical shifts but that a weakly elongated equilibrium can be stabilized by finite aspect ratio effects without the use of a conducting shell. Vertical displacements are stable if the decay index $n$ of the external vertical field satisfies $n \equiv-\left(R_{0} / B_{z}^{\text {ext }}\right)\left(\partial B_{z}^{\text {ext }} / \partial R\right)_{R=R_{0}}>0$. 315 | \begin{figure}[H] 316 | \centering 317 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-5} 318 | \caption{Vertical stability diagram in terms of $1_{i, \text { crit }}$ and $\epsilon \beta_{p}$ for several equilibria of varying shapes. Two curves are shown for the DIII-D-like equilibrium with two different wall positions. The walls are conformal to the plasma shape at midplane distances of $\mathrm{d}=1.3 \mathrm{a}$ and $\mathrm{d}=1.4 \mathrm{a}$. For comparison, curve 1 from Fig. 1 for the TCV dee configuration is also shown. Two other stability boundaries intermediate between the DIII-D-like and the TCV dee equilibria are shown, with $\kappa=3.0, \delta=0.6, \lambda=0$ and with $\kappa=2.5, \delta=0.5, \lambda=0.2$.} 319 | \label{fig3.} 320 | \end{figure} 321 | 322 | 323 | % ==AUTO MOVED 324 | 325 | Zakharov's expression [4,5] for $n$ implies that a plasma with a flat current profile is vertically stable when 326 | \begin{align*} 327 | \kappa-1<\left(\frac{a}{R_{0}}\right)^{2}\left(\frac{3}{4} \ln \frac{8 R_{0}}{a}-\frac{17}{16}\right) \tag{2} 328 | \end{align*} 329 | Laval et al. [13] showed that an elongated plasma can be stabilized by a conducting wall. For a flat current profile, their stability condition (in the near circular approximation) is 330 | 331 | \begin{align*} 332 | \kappa-1<2\left(\frac{a}{d}\right)^{2} \tag{3} 333 | \end{align*} 334 | 335 | where $d$ is the wall radius. Comparison of the conditions (2) and (3) shows that for the elongations, aspect ratios and wall distances typical of modern tokamaks, wall stabilization is far more important than finite aspect ratio effects [21], and the discharges would be strongly unstable without a wall. 336 | 337 | 338 | The effects of more complex shaping, including finite aspect ratio and pressure effects, were investigated semi-analytically for a surface current distribution by Rebhan and Salat [17]. For vertically elongated equilibria, they found that an inverse dee ( $\delta<0$ ) is destabilized by pressure, but a standard dee ( $\delta>0$ ) can be stabilized by pressure (see Fig. 4(a) of Ref. [17]). A stabilizing effect of finite pressure in combination with positive triangularity on the vertical stability of elongated equilibria is also indicated by the results [19] obtained with the ERATO stability code. This effect is the basic reason for the increased value of $l_{\mathrm{i}, \text { crit }}$ at high $\epsilon \beta_{\mathrm{p}}$ in the operational diagrams, Figs 1 and 3. The main new result shown in these diagrams is the appreciable size of the pressure effect on vertical stability in terms of the operational parameters, $l_{\mathrm{i}}$ and $\epsilon \beta_{\mathrm{p}}$, for more realistic current distributions than the surface current model of Ref. [17]. 339 | 340 | It has been shown $[14,18]$ that resistive wall growth rates (for equilibria that are unstable without a wall but stable with an ideally conducting wall) can be expressed in terms of the ideal MHD potential energies of the vertical shift mode in the absence of a wall, $\delta W_{\infty}$, and with an ideally conducting wall in the position of the resistive wall, $\delta W_{\mathrm{d}}$, as 341 | \begin{align*} 342 | \gamma_{\mathrm{res}}=-\left(b / \tau_{\mathrm{w}}\right) \delta W_{\infty} / \delta W_{\mathrm{d}} 343 | \end{align*} 344 | Here, $\tau_{\mathrm{w}}$ is the $L / R$ time of the wall and $b$ is a numerical factor that depends on the current distribution in the wall. This expression gives valuable analytical insight. However, for numerical calculations it is more straightforward to introduce a resistive wall and solve the full eigenvalue problem as is done by NOVA-W. This automatically takes into account the effects of non-rigid displacements [22] and avoids the calculation of $\delta W_{\mathrm{d}}$ for a stable oscillatory mode which can be hidden by a continuous spectrum. 345 | 346 | In the following two sections, we show the vertical stability results for ideal and resistive walls obtained with the NOVA-W code with the aim of placing the results for TCV dee and DIII-D cross-sections into a broader framework. 347 | \begin{figure}[H] 348 | \centering 349 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-6} 350 | \caption{Growth rates (in $\mathrm{s}^{-1}$ ) versus triangularity for a resistive wall conformal to the plasma shape at a midplane distance of $\mathrm{d}=1.3 \mathrm{a}$ for seversal shapes ranging from the inverse dee $(\delta=-0.6)$ to the regular dee $(\delta=0.6)$ at high beta $\left(\beta_{p}=0.6\right)$ and low beta $\left(\beta_{p}=0.06\right)$.\\} 351 | \label{fig4.} 352 | \end{figure} 353 | 354 | \begin{figure}[H] 355 | \centering 356 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-6(1)} 357 | \caption{Plot of the square of the normalized ideal wall MHD growth rate $\gamma_{N}^{2}$ versus $\mathrm{a}^{2} / \mathrm{d}^{2}$, with an ideally conducting wall. The results are shown for three shapes (inverse dee, ellipse, regular dee) at high $\beta_{p}$ (solid symbols) and low $\beta_{p}$ (open symbols).} 358 | \label{fig} 359 | \end{figure} 360 | 361 | 362 | \section{PRESSURE EFFECTS} 363 | 364 | The operational diagrams in Figs 1 and 3 show a much stronger stabilizing effect of $\epsilon \beta_{\mathrm{p}}$ in the DIII-Dlike cross-section ( $\kappa=2.5, \delta=0.6, \lambda=0$ ) than for the TCV dee shape ( $\kappa=3.0, \delta=0.5, \lambda=0.2$ ). 365 | 366 | Figure 3 shows that the most important reason for this difference is the more triangular shape of DIII-D (note that a positive $\lambda$ decreases the effective triangularity [9]). The strong dependence of the pressure effect on triangularity is illustrated by Fig. 4. This figure shows resistive wall growth rates for elongated crosssections ( $\kappa=2.5, A=3$ ) at low and high pressures ( $\beta_{p}=0.06$ and 0.6 , respectively) and at several different triangularities ranging from $\delta=-0.6$ (inverse dee) to $\delta=+0.6$ (standard dee). The wall is a conformal copy of the plasma surface with minor radius $d=1.3 a$ and has the same resistivity and thickness as the TCV vacuum vessel used for Fig. 1. Pressure is strongly destabilizing for the inverse dee, somewhat stabilizing for the ellipse and clearly stabilizing for the standard dee. The inverse dee is strongly destabilized, and with $\beta_{\mathrm{p}}=0.6$ the mode is near marginal stability with an ideally conducting wall, see Fig. 5. 367 | 368 | Figure 5 shows the square of the normalized ideal wall MHD growth rate (a measure of the ideal MHD driving energy) versus the reciprocal wall radius squared for three different triangularities ( $\delta=-0.6$, $0.0,0.6$ ) and for both high and low pressures. The dee shape is clearly the most stable among all the cases. For this configuration, a finite pressure is significantly stabilizing in the absence of a wall and remains so when wall stabilization is accounted for. 369 | 370 | By contrast, for the inverse dee, pressure is clearly destabilizing both with and without a wall. The critical wall distance for the inverse dee is quite close to $d=1.3 a$, and therefore the resistive wall growth rate (with the wall at that position) is very large in Fig. 4 for that case. For the pure ellipse, the free space growth rate is virtually the same for the low and high pressure cases, but high pressure shows a stabilizing influence in the presence of a wall, and the growth rate falls below that for the inverse dee as the wall is moved inward. 371 | 372 | Plots of the equilibrium flux surfaces show that, for the dee shape, increased pressure reduces the central elongation. This can be interpreted as the result of squeezing in the vertical direction by the combination of triangular shape and the Shafranov shift. The same effect leads to an increased elongation at high $\beta_{p}$ in an inverse dee. 373 | 374 | 375 | We conclude that the primary effect of pressure on the dee shape is to lower the free space driving energy. Conversely, pressure increases the free space energy for the inverse dee. Thus, the favourable effect of pressure shown in the operational diagrams, Figs 1 and 3 , is mainly due to the lowering of the free space driving energy and not to its effect on the wall coupling. For the ellipse, the free space growth rates are virtually unaffected by pressure, but there is an increase in the wall stabilization for the high pressure case. 376 | 377 | \section{CURRENT PROFILE EFFECTS} 378 | It is well known that the current profile strongly influences the vertical stability. The almost identical results for different classes of current profiles in Fig. 1 show that the relevant parameter characterizing the current distribution is the internal inductance. Flat current profiles with low internal inductance lead to stronger coupling between the plasma and the external conductors. However, we find computationally that, in the absence of a conducting shell, the growth rate generally increases with decreasing inductance (see also Ref. [20]). This is shown in Fig. 6, where the ideal wall growth rate is plotted as a function of the wall radius for two DIII-D shaped equilibria with different internal inductances, $l_{\mathrm{i}}=0.6$ and 0.8 , respectively. 379 | 380 | Peaking of the current profile is evidently stabilizing when the wall is distant but destabilizing when the wall is sufficiently close. At a wall distance of roughly $d=1.4 a$, the two curves in Fig. 6 cross, and the growth rate is independent of the inductance. This point is close to the critical wall distance. Therefore, the internal inductance has a rather small effect on the marginal position of the ideal wall, but it has a much stronger effect on the resistive growth rates with a close fitting wall [14]. In fact, with the wall at $d=1.3 a$, the two cases in Fig. 6 have nearly a factor of two difference in the resistive growth rate. The reduction of the free space growth rate with increasing inductance appears to be due mainly to a reduction of the ellipticity of the central flux surfaces. It should be noted that there are many competing effects, for example a similar reduction of the central triangularity, which reduces the finite pressure stabilization. In addition, peaking of the current profile effectively increases the aspect ratio, so that the toroidal stabilization is reduced. However, as discussed in Section 3, the toroidal stabilization is insignificant for highly elongated cross-sections. 381 | \begin{figure}[H] 382 | \centering 383 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-7} 384 | \caption{Plot of $\gamma_{N}^{2}$ versus $\mathrm{a}^{2} / \mathrm{d}^{2}$ with an ideally conducting wall for DIII-D-like equilibria with no pressure for $1_{i}=0.6$ (dashed curve) and for $1_{i}=0.8$ (solid curve).} 385 | \label{fig6.} 386 | \end{figure} 387 | 388 | 389 | \subsection{Passive stabilization by discrete conductors} 390 | While the effect of broadening the current profile increases the destabilizing force on the equilibrium, it also increases the stabilizing effect of a completely surrounding conducting wall. The balance between these competing effects is changed if the passive stabilization is provided primarily by discrete conductors instead of a complete, surrounding wall. As an example, we consider the configuration indicated in Fig. 7. The equilibrium has $\kappa=1.9, \delta=0.7$ and $A=4.54$. Figure 8 shows that in this configuration the growth rate increases with decreasing $l_{\mathrm{i}}$. This effect has been observed previously by Pearlstein [23] and by Jardin [24]. 391 | 392 | An interesting comparison is obtained by replacing the discrete conductors by the complete wall, as indicated by a dotted contour in Fig. 7. The total wall resistance was normalized to that of the passive conductors. Figure 8 shows that with the closed wall configuration the growth rate decreases monotonically with decreasing $l_{\mathrm{i}}$. 393 | 394 | Figure 7 shows the contours of perturbed flux for the cases of (a) high and (b) low $l_{\mathrm{i}}$ in Fig. 8. While the coupling of the perturbed flux to the closed wall is improved in the low $l_{i}$ case, the coupling to the discrete conductors is not. Therefore, the increase in the destabilizing force due to the broader current profile dominates, and the growth rate increases with decreasing $l_{\mathrm{i}}$. 395 | \begin{figure}[H] 396 | \centering 397 | \includegraphics[max width=0.85\textwidth,max height=0.5\textheight]{2025_01_10_a0135324997886412d98g-8(1)} 398 | \caption{The plasma boundary, the discrete conductor sets and (shown as a dotted contour) a fictitious completely surrounding wall for the comparison in Fig. 8. The vacuum vessel is quite distant from the plasma. The perturbed flux contours are shown for two equilibria with (a) high $1_{i}$ and (b) low $1_{i}$ in the configuration with discrete conductors.\\} 399 | \label{fig7.} 400 | \end{figure} 401 | 402 | \begin{figure}[H] 403 | \centering 404 | \includegraphics[max width=0.85\textwidth,max height=0.3\textheight]{2025_01_10_a0135324997886412d98g-8} 405 | \caption{Growth rates (in $s^{-1}$ ) versus $1_{i}$ for the configuration in Fig. 7 stabilized by discrete conductors with the vacuum vessel far from the plasma. For comparison, growth rates are shown with a completely surrounding wall (conformal to the plasma surface at $\mathrm{d}=1.3 \mathrm{a}$ ).\\} 406 | \label{fig8.} 407 | \end{figure} 408 | 409 | 410 | 411 | We conclude that, for highly elongated tokamaks, there are two main effects of the internal inductance on vertical stability. Firstly, wall stabilization is improved for low internal inductance because of increased magnetic coupling. Secondly, current peaking reduces the shaping of the internal flux surfaces, which reduces the instability growth rate in the absence of a wall. For highly elongated, feedback stabilized discharges with a closed wall, the effect on wall coupling is more important, and stability improves at low inductance. However, when there is not a completely surrounding wall, the competition of these two effects is more subtle and depends on the details of the current profile and of the placement of the conductors. 412 | 413 | \section{CONCLUSIONS} 414 | We have found that high values of $\epsilon \beta_{\mathrm{p}}$ significantly improve the vertical stability of dee shaped tokamaks. 415 | 416 | The effect can be described in terms of an almost linear dependence of the critical internal inductance on $\epsilon \beta_{\mathrm{p}}, l_{\mathrm{i}, \text { crit }} \approx l_{\mathrm{i}, 0}+c \epsilon \beta_{\mathrm{p}}$. Comparison between different cross-sections shows that the coefficient $c$ increases strongly with triangularity and decreases somewhat with elongation. For a DIII-D-like cross-section, the dependence of $l_{\mathrm{i}, \text { crit }}$ on $\epsilon \beta_{\mathrm{p}}$ is quite pronounced. This effect is beneficial for reaching high beta, because it increases the maximum stable elongation or, alternatively, allows the current profile to be more peaked, which increases the beta limit due to the $n=1$ external kink mode $[2,9]$. 417 | 418 | \section{ACKNOWLEDGEMENTS} 419 | This work was supported in part by the Swiss National Science Foundation. We acknowledge the work of H . Lütjens in adapting the CHEASE equilibrium code for NOVA-W. 420 | \setlength{\parskip}{0pt} \small % ==document body ends 421 | 422 | 423 | %---------------------------------------------------------------------------------------- 424 | \end{sloppypar} 425 | \begin{flushright} 426 | \vfill \footnotesize 427 | ——本翻译PDF由Paper_translator生成, \url{https://github.com/DertahSama/Paper_translator} 428 | \end{flushright} 429 | \end{document} 430 | -------------------------------------------------------------------------------- /样例202502/[翻译@deepL]471-1993-Ward - 副本.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/[翻译@deepL]471-1993-Ward - 副本.pdf -------------------------------------------------------------------------------- /样例202502/[翻译@doubao]471-1993-Ward.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/[翻译@doubao]471-1993-Ward.pdf -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-3.jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-4.jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-5.jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-6(1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-6(1).jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-6.jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-7.jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-8(1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-8(1).jpg -------------------------------------------------------------------------------- /样例202502/images/2025_01_10_a0135324997886412d98g-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DertahSama/Paper_translator/f2da58bfacbfe5d708f8a85a791a2b914f700328/样例202502/images/2025_01_10_a0135324997886412d98g-8.jpg -------------------------------------------------------------------------------- /样例202502/suffix.txt: -------------------------------------------------------------------------------- 1 | \section{REFERENCES} 2 | [1] TROYON, F., et al., Plasma Phys. Control. Fusion 26 (1984) 209.\\[0pt] 3 | [2] LAZARUS, E.A., et al., Phys. Fluids B 3 (1991) 2220; LAZARUS, E.A., et al., Phys. Fluids B 4 (1992) 3644.\\[0pt] 4 | [3] YUSHMANOV, P.N., et al., Nucl. Fusion 30 (1990) 1999.\\[0pt] 5 | [4] ZAKHAROV, L.E., Sov. Phys. - Tech. Phys. 16 (1971) 645 (English translation: Zh. Tekh. Fiz. 41 (1971) 823).\\[0pt] 6 | [5] MUKHOVATOV, V.S., SHAFRANOV, V.D., Nucl. Fusion 11 (1971) 605.\\[0pt] 7 | [6] LAZARUS, E.A., et al., Nucl. Fusion 30 (1990) 111.\\[0pt] 8 | [7] HOFMANN, F., et al., in Fusion Technology 1986 (Proc. 14th Symp. Avignon, 1986), Vol. 1, Pergamon Press, Oxford (1986) 687.\\[0pt] 9 | [8] TAYLOR, T.S., et al., in Plasma Physics and Controlled Nuclear Fusion Research 1990 (Proc. 13th Int. Conf. Washington, DC, 1990), Vol. 1, IAEA, Vienna (1991) 177 ; LAO, L.L., et al., Phys. Fluids B 4 (1992) 232.\\[0pt] 10 | [9] ERIKSSON, G., et al., in Plasma Physics (Proc. 1992 Int. Conf. Innsbruck), Vol. 16C, Part I, European Physical Society (1992) 343.\\[0pt] 11 | [10] ZARNSTORFF, M.C., et al., in Plasma Physics and Controlled Nuclear Fusion Research 1990 (Proc. 13th Int. Conf. Washington, DC, 1990), Vol. 1, IAEA, Vienna (1991) 109.\\[0pt] 12 | [11] LÜTJENS, H., et al., Comput. Phys. Commun. 69 (1992) 287.\\[0pt] 13 | [12] WARD, D.J., et al., J. Comput. Phys. 104 (1993) 221.\\[0pt] 14 | [13] LAVAL, G., et al., Phys. Fluids 17 (1974) 835.\\[0pt] 15 | [14] HANEY, S.W., FREIDBERG, J.P., Phys. Fluids B 1 (1989) 1637.\\[0pt] 16 | [15] ERIKSSON, H.G., Plasma Phys. Control. Fusion 34 (1992) 1721.\\[0pt] 17 | [16] REBHAN, E., Nucl. Fusion 15 (1975) 277.\\[0pt] 18 | [17] REBHAN, E., SALAT, A., Nucl. Fusion 16 (1976) 805.\\[0pt] 19 | [18] HOFMANN, F., SCHULTZ, C.G., in Controlled Fusion and Plasma Physics (Proc. 16th Eur. Conf. Venice, 1989), Vol. 13B, Part I, European Physical Society (1987) 335.\\[0pt] 20 | [19] BERNARD, L.C., et al., Nucl. Fusion 18 (1978) 1331.\\[0pt] 21 | [20] BECKER, G., LACKNER, K., in Plasma Physics and Controlled Nuclear Fusion Research 1976 (Proc. 6th Int. Conf. Berchtesgaden, 1976), Vol. 2, IAEA, Vienna (1977) 401.\\[0pt] 22 | [21] STAMBAUGH, R.D., et al., Nucl. Fusion 32 (1992) 1642.\\[0pt] 23 | [22] WARD, D.J., JARDIN, S.C., Nucl. Fusion 32 (1992) 973.\\[0pt] 24 | [23] PEARLSTEIN, L.D., Lawrence Livermore National Laboratory, personal communication, 1992.\\[0pt] 25 | [24] JARDIN, S.C., Plasma Physics Laboratory, Princeton University, personal communication, 1992.\\ 26 | (Manuscript received 21 December 1992\\ 27 | Final manuscript received 29 March 1993) 28 | 29 | -------------------------------------------------------------------------------- /设置.yaml: -------------------------------------------------------------------------------- 1 | PDF识别设置: 2 | 保存路径: ../论文翻译ouput/ 3 | 4 | 排版设置: 5 | 处理filepath里储存的文件名: 0 6 | 立即编译所得tex: 0 7 | 这是一本书: 0 8 | 9 | 翻译设置: 10 | # 通用设置 11 | 处理filepath里储存的文件名: 1 12 | 立即编译所得tex: 1 13 | 翻译APIkeys文件夹: [../translator_keys, translator_keys, translator_keys_void] # 按顺序寻找,找到第一个存在的文件夹即读取 14 | 15 | 默认翻译器: "5.1" # "x":不设默认;"1":百度;"2":腾讯;"3":openai;"4":deepl;"5":doubao;"5.1":doubao_async 16 | 17 | # 1:百度专用设置 18 | 19 | # 2:腾讯专用设置 20 | tencent-要用的术语表id: ["",] # 术语表id,可以有多个,用逗号隔开 21 | 22 | # 3:openai专用设置 23 | 24 | # 4:deepl专用设置 25 | deepL-只检查账号额度: 0 26 | deepL-更新术语表: 1 27 | deepL-要用的术语表: fusion_glossary # 放在glosaaries文件夹里的术语表文件名 28 | deepL-重新检查账号额度: 1 29 | 30 | # 5:doubao专用设置 31 | doubao-AI总结: 0 # 是否在文章开头添加AI总结、具备AI问答能力。不可用于过长(超过20页PDF)的文章。 32 | # 这关系到要采用的工作模式,开启的话费用更贵(不开启,模式"common_prefix",费用线性于文章段数;开启,模式"session",再额外加一平方于文章段数的项) 33 | doubao-要用的术语表: fusion_glossary_distill #fusion_glossary # 放在glosaaries文件夹里的术语表文件名 34 | doubao-上下文超时时间: 3600 # 单位秒,每次对话后重新计时 35 | 36 | 37 | 38 | --------------------------------------------------------------------------------