2018年4月3日星期二

让 macOS 里编译的 CTeX 文档中仿宋字体在 Windows 里不要乱码

MacTex 里直接用 CTeX 文类的 \fangsong 命令的话,会默认使用华文仿宋字体(STFangsong)。
这样的文件用 latexmk 编译得到的 pdf 会在 windows 里乱码,不能显示其中的仿宋字体。
但直接用 xelatex 编译并不会如此。

经 @johannes_gutenberg 告知,实际上 latexmk 在编译时有两步:
1. tex -> xdv
xelatex -no-pdf [...] input.tex
可能编译多次

2. xdv -> pdf
xdvipdfmx input.xdv

而第二步中,这个华文仿宋字体由于版权(?)原因,不会被嵌入到 pdf 内。
可以显示使用 -E 选项要求 xdvipdfmx 嵌入字体。

对于 latexmk,则可以如下操作:
1. 工作目录新建空文件 latexmkrc
2. 其中内容写上 $xdvipdfmx="xdvipdfmx -E -o %D %O %S"
就可以让 latexmk 生成 pdf 时总嵌入字体。

2017年8月17日星期四

让 LG KBB-710 键盘支持 iOS 10

大约去年暑期时,冲动购物买了 LG 的 KBB-710 键盘。买回来试了下感觉不错,但平时也不怎么需要用,就收起来没再试过。
等这几天翻出来想用时,发现一个奇怪的问题:与 iOS 设备配对成功之后,想要再次从断开状态恢复连接就会失败,提示找不到设备。断开包括 iOS 锁屏、键盘卷起、键盘切换连接设备等。

网上搜了下,发现大量用户都表示 iOS 10 之后遇到了类似的问题。而 LG 官方也直接宣布这键盘不支持 iOS 10了。
LG 给了个临时解决方案,让每次需要使用时都忽略设备然后重新配对。但是在我这里,重新配对时需要等超长的设备搜索时间。

网上搜索一番无果之后,倒是让我试出来一个临时解决方案:

  1. 每当需要恢复连接键盘时,把键盘展开,把 iOS 的蓝牙设置打开。这时设置里应该会显示一个未找到的键盘。
  2. 按住 KBB-710 上你上次进行匹配的蓝牙数字键两秒,进入重新匹配模式。
  3. 在 iOS 蓝牙设置里点击你的键盘。
这样就能快速匹配成功,至少避免了每次忽略设备都要重新等待设备搜索的过程。

2017年3月24日星期五

配置群晖支持 python 版 shadowsocks

问题描述

直接使用 pip 安装 shadowsocks,启动时可能卡在 RuntimeError: can not find library crypto 这一步。
这里是在使用 ctypes 查找 libcrypto.so,而群晖自带的 python 里,ctypes 版本太老,不支持 armv7,以至于 ctypes.util.find_library()实际上找不到任何可用的库。

解决方案

去新一点的 Linux 发行版上,拷一个 /usr/lib/python2.7/ctypes/util.py 回来,替换掉群晖自己这个文件即可。
我找了个 Ubuntu14 就解决问题了。
消息来源:https://forum.synology.com/enu/viewtopic.php?t=84921

2016年10月23日星期日

让 Windows 中的 LaTeXTools 支持中文目录

LaTeXTools 是 Sublime Text 的一个插件,可以用来方便地在 Sublime Text 中处理 LaTeX 文件。

我目前所使用的 v3.11.2 版稍有问题,无法正确处理中文目录,原因是其 makepdf.py 文件使用 subprocess.Popen 调用 Latex 的外部指令时,对传入的工作目录 cwd 没有进行特殊字符判断,直接给了 Popen。如果工作目录含有中文字符的话,就会报一个
UnicodeEncodeError: 'ascii' codec can't encode characters in position xx-xx: ordinal not in range(128)
的错误。

解决方案:
自己 encoding 一下 cwd,再传给 Popen。
在第 142 行,
if self.caller.plat == "windows":
之后另起一行,缩进并加入下列内容

fixed_tex_dir = self.caller.tex_dir
if isinstance(fixed_tex_dir, unicode):
    fixed_tex_dir = fixed_tex_dir.encode(sys.getfilesystemencoding())

将紧随其后的
cwd=self.caller.tex_dir
替换为
cwd=fixed_tex_dir
注意上述内容中,所有四个空格都要替换为 tab 缩进。

参阅
1. Sublime Text 2的Tortoise插件中文路径问题
2. subprocess.call fails with unicode strings in command line - Python tracker

2016年6月27日星期一

Minecraft 开服指导:同时兼容 Forge 和 Essentials 类插件

本文为截止当前( 2016年06月27日)对 Minecraft 开服方式的小结

主要目标是:同时兼容 Forge 和 Essentials 类插件

  1. 对于 1.7.10
    1. 对于早于 forge1403 的版本:直接使用 Cauldron 
      1. https://sourceforge.net/projects/cauldron-unofficial/files/1.7.10/
    2. 对于后续版本
      1. 考虑使用 Kcauldron
        1. https://prok.pw/downloads.html
        2. 但已经废弃
      2. 考虑使用 Thermos
        1. http://cyberdynecc.github.io/Thermos/
    3. 上述都直接支持标准 essentials 插件
      1. http://dev.bukkit.org/bukkit-plugins/essentials/
    4. 使用 forge + forge essentials
      1. 代价是禁怪不如原始 essentials 方便,但有其它功能
      2. http://files.minecraftforge.net/
      3. http://minecraft.curseforge.com/projects/forge-essentials-74735/files
  2. 对于 1.8
    1. 使用 spigot + 相关 essentials
      1. 代价是不支持 forge mod
      2. https://www.spigotmc.org/
      3. 第三方构筑 https://www.getbukkit.org/spigot.html
      4. 插件: https://hub.spigotmc.org/jenkins/job/Spigot-Essentials/
    2. 使用 forge + forge essentials
      1. 同1.7.10
      2. 但暂无1.8.9编译版本?
    3. 使用 forge + sponge + sponge essentials
      1. http://files.minecraftforge.net/spongepowered/
      2. https://forums.spongepowered.org/t/essentialcmds-v8-1-11/
  3. 对于 1.9
    1. 使用 spigot + essentials
      1. 没 mod
    2. 使用 forge + sponge + sponge essentials
  4. 对于 1.10
    1. 使用 forge
      1. 没插件
    2. 使用 spigot
      1. 没 mod

2015年3月15日星期日

在Abaqus中使用c++写用户子程序

Abaqus 6.13之后的版本多了一个功能,可以用c++或者c来写用户子程序了;之前的版本中只支持使用fortran语言。
网上在这方面的资料太少,因此把我的折腾过程记录一下。

  • 在abaqus中加载编译环境用和fortran相同的方法(不过我试的时候没需要,应该是ifortvar带进去了)
  • abaqus_v6.env里没什么要改的
  • 在cpp文件中如下修改
    • 要先#include <aba_for_c.h>
      • 这会带进来个FOR_NAME宏,所有从abaqus调用的函数,以及调用abaqus的函数,都用类似下面的方法声明
      • extern "C" 是让cpp用c的方法声明符号——即符号名称中不包含变量类型,不知重载是怎么解决的
        • 就算不能重载也没关系,只有和abaqus通信的函数要这么处理
      • 例子
        • extern "C" void FOR_NAME(xit)();
          • 这个是abaqus提供的函数
          • 对于需要传入的参数中包含字符串的,见文末说明。
        • extern "C" void FOR_NAME(umat)(double* STRESS,void* STATEV,double*DDSDDEori,void* SSE,void* SPD,void* SCD,void* RPL,void* DDSDDT,void* DRPLDE,void* DRPLDT,void* STRAN,double* DSTRAN,void* TIME,void* DTIME,void* TEMP,void* DTEMP,void* PREDEF,void* DPRED,void* CMNAME,int& NDI,int& NSHR,int& NTENS,void* NSTATV,double* PROPS,void* NPROPS,void* COORDS,void* DROT,void* PNEWDT,void* CELENT,void* DFGRD0,void* DFGRD1,void* NOEL,void* NPT,void* LAYER,void* KSPT,void* KSTEP,void* KINC){ }
          • 这里的void*都是偷懒了,只声明对自己要用的变量就行
    • 对于二维数组,fortran是列优先的,cpp是行优先的
    • fortran是1开始数的,cpp是0开始数的
    • DDSDDE这个二维数组,有两种办法
      • 如果你确信你只对3维问题跑,则它一定是6*6的,可以把DDSDDE在函数头里声明为 double DDSDDE[][6],或者double (*DDSDDE)[6]
      • 否则的话,开头声明为double* DDSDDEori
        • double** DDSDDE=new double*[NTENS];
        • for(int i=0;i<NTENS;i++) DDSDDE[i]=DDSDDEori+NTENS*i;
        • 这个方法略占行数,不过并没有效率下降。
完成了上面的配置之后,你应当能跑一个典型的c++写的用户子程序(如umat了)。但为了使用方便起见,你应该还想要调用外部库。
  • 调用外部库
    • 如armadillo
    • 正常安装armadillo库之后即可使用
    • 如果要矩阵乘法,就要BLAS;要解方程,就要LAPACK
      • 他俩的lib应当从链接器中提供,这意味着——
      • 修改abaqus_v6.env中的link_sl,在末尾添加'blas_win64_MT.lib' , 'lapack_win64_MT.lib' ,并将两个文件拷贝到vs的cpp库中(选择amd64)目录
        • 在我的机子上是 C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\amd64
      • 将对应的两个dll拷到system32里
        • 否则程序运行中会报错弹框退出
    • 可以用mat ddsddeMat=mat(DDSDDEori,NTENS,NTENS,false,true);直接构建对应 的矩阵或列向量
      • 开头把DDSDDE声明为double*或者void*
      • 第一个false为不拷贝数据,直接用原始位置
      • 第二个true为strict,即不添加空间,保证总是用这一段
      • 要注意这里不用转置
        • 二维数组中,fortran是列优先的,c++是行优先的,但arma使用一维数组初始化矩阵时,是列优先的(至少在armadillo-4.650.3中是)。
最后说点兼容性问题
  • abaqus 6.13或更高版本支持在standard或者explicit中用c或cpp
  • abaqus 6.14-2中仍然不支持直接用cae来指定cpp后缀的用户子程序,只能用命令行的user=xxxxx.cpp来指定。因此要用cae生成input文件,用命令行计算,最后可以用cae查看计算结果
---
从c++调用fortran的函数,其参数列表中含有字符串
——关于fortran 中的character*
fortran中的字符串是自知长度的,可以通过len()访问
在c++中无法产生这一类

在向subroutine传递字符串时,具体行为是编译器相关的
  • 有的编译器会传递一个结构体,其中包含1个char*指针,和一个size_t的值
  • 有的编译器在整个函数的参数列表末尾按顺序依次再传递各个字符串的长度
intel fortran 是第二种

对于第一种情况,可以构造一个类CHARACTER来模拟行为
这里有个写好的

对于第二种情况,在c++中声明函数就要考虑到末尾的整形变量,调用时也要如此考虑
  • 声明 extern "C" void FOR_NAME(getoutdir) (char* outdir, int* lenoutdir, int len);
  • 调用 getoutdir(temp, &len, 200);
    • 其中200为char temp[200];
参阅
http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html
https://computing.llnl.gov/tutorials/bgq/ 中的 Miscellaneous 一节
http://arnholm.org/software/cppf77/cppf77.htm

2013年9月12日星期四

在Airmail中使用QQ邮箱

Airmail是一款轻量级Mac下的邮件客户端。

在其中添加QQ邮箱账户时如下设置:
收件服务器设置为imap.qq.com,使用993端口的SSL登陆,登陆方式选NONE
发件服务器设置为smtp.qq.com,使用465端口的SSL登陆,登陆方式选PLAIN

根据腾讯的官方说明,如果你使用的是qq的vip邮箱或是foxmail邮箱,用户名要带上完整域名,否则只填写@前面的部分。