|
本帖最后由 Stardust0831 于 2025-4-1 00:58 编辑
几个月前,我在文献里看到了这样的图
。图中通过平面平均的LDOS来展现异质结界面的能带弯曲。在尝试用cp2k+multiwfn重复的时候,发现multiwfn只能计算某条线上的LDOS,由于修改multiwfn源代码遇到了环境问题,我基于multiwfn现有的计算某条线的LDOS的功能写了个批处理脚本,可以批量计算上不同(X,Y)坐标对应的垂直于Z平面的线上的LDOS,对这些不同的(X,Y)坐标下得到的值取平均,取的点足够密时也就实现了平面平均。此脚本避免了反复读取molden文件而增加耗时。该脚本需要使用powershell7运行。由于是依赖于multiwfn的已有功能完成的计算,这个LDOS的结果是gamma点而非考虑了不同k点。考虑特定k点的这一部分我暂时没有想到很好的解决策略,就用这个脚本抛砖引玉一下,看看各位大佬有没有更好的思路。
以下为脚本本体,部分内容根据备注自行修改:
- #!/usr/bin/pwsh
- # ./auto.ps1 -OutputFolder /opt/example/output
- param(
- [string] $OutputFolder = $PSScriptRoot
- )
- function Start-Multiwfn
- {
- param(
- [string] $MultiwfnPath,
- [string] $MoldenFile,
- [System.IntPtr] $Affinity
- )
- $startInfo = New-Object System.Diagnostics.ProcessStartInfo
- $startInfo.RedirectStandardInput = $true
- $startInfo.RedirectStandardOutput = $true
- $startInfo.StandardInputEncoding = [System.Text.Encoding]::UTF8
- $startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
- $startInfo.FileName = $MultiwfnPath
- $startInfo.Arguments = "$MoldenFile -slient"
- $process = [System.Diagnostics.Process]::Start($startInfo)
- $process.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::RealTime
- $process.ProcessorAffinity = $Affinity
- $process.Refresh()
-
- return $process
- }
- function Push-Data
- {
- param(
- [string] $StartPoint,
- [string] $EndPoint,
- [int] $Number
- )
- # Wait input until specific output
- while ($true)
- {
- if ($Reader.Peek() -le 0)
- {
- Start-Sleep -Seconds 1
- Write-Host $s
- ++$s
- continue
- }
-
- $line = $Reader.ReadLine()
- Write-Host $line
- if ($line.Contains('========== Plot density-of-states (DOS) =========='))
- {
- break
- }
- }
-
- $Writer.WriteLine("11")
-
- Start-Sleep -Seconds 1
- $Writer.WriteLine($StartPoint)
-
- Start-Sleep -Seconds 1
- $Writer.WriteLine($EndPoint)
-
- Start-Sleep -Seconds 1
- $Writer.WriteLine($Number)
-
- $s = 0
- while ($true)
- {
- if ($Reader.Peek() -le 0)
- {
- Start-Sleep -Seconds 1
- Write-Host $s
- ++$s
- continue
- }
-
- $line = $Reader.ReadLine()
- Write-Host $line
- if ($line.Contains('-------- Post-processing menu --------'))
- {
- break
- }
- }
-
- $Writer.WriteLine("3")
-
- while ($true)
- {
- if ($Reader.Peek() -le 0)
- {
- Start-Sleep -Seconds 1
- Write-Host $s
- ++$s
- continue
- }
-
- $line = $Reader.ReadLine()
- Write-Host $line
- if ($line.Contains('-------- Post-processing menu --------'))
- {
- break
- }
- }
- $timestamp = Get-Date -Format "yyyyMMddHHmmss"
- $filename = "LDOS" + "_" + $StartPoint + "_" + $EndPoint + "_" + $Number + "_$timestamp.txt"
- # !!!IMPORTANT!!! Move and rename output file
- Move-Item -Path "$PSScriptRoot/LDOS.txt" -Destination "$OutputFolder/$filename"
- $Writer.WriteLine("0")
-
- }
- # Script Entry
- try
- {
- $timestamp = Get-Date -Format "yyyyMMddHHmmss"
- $OutputFolder = [System.IO.Path]::Combine($OutputFolder, $timestamp)
- [System.IO.Directory]::CreateDirectory($OutputFolder)
- # !!!IMPORTANT!!! Start Multiiwfn process
- $process = Start-Multiwfn -MultiwfnPath "$PSScriptRoot/Multiwfn.exe" -MoldenFile "$PSScriptRoot/test1/FAPbI3-ch3opeai-sp-MOS-1_0.molden" -Affinity 0xfff
- $Reader = $process.StandardOutput
- $Writer = $process.StandardInput
- $s = 0
- while ($true)
- {
- if ($Reader.Peek() -le 0)
- {
- Start-Sleep -Seconds 1
- Write-Host $s
- ++$s
- continue
- }
-
- $line = $Reader.ReadLine()
- Write-Host $line
- if ($line.Contains('************ Main function menu ************'))
- {
- break
- }
- }
- $Writer.WriteLine("\r\n")
-
- # Add additional option, $Writer.WriteLine("10")
- $Writer.WriteLine("10")
- Start-Sleep -Seconds 1
- $Writer.WriteLine("8")
- Start-Sleep -Seconds 1
- $Writer.WriteLine("2")
- Start-Sleep -Seconds 1
- $Writer.WriteLine("-10,2,2")
- Start-Sleep -Seconds 1
- $Writer.WriteLine("3")
- Start-Sleep -Seconds 1
- #$Writer.WriteLine("0.4")
- Start-Sleep -Seconds 1
- for ($i = 0; $i -lt 5; ++$i)
- {
- Push-Data -StartPoint "$i,0,0" -EndPoint "$i,0,30" -Number 20
- }
- $process.Close()
- return
- }
- catch
- {
- Write-Error $_.Exception
- }
- finally
- {
- if (-not $process.HasExited){
- $process.Close()
- }
- }
复制代码
该脚本会把计算得到的不同线段的LDOS输出到特定文件夹,可以通过这个C#程序来完成对这些数据取平均,从而实现平面平均的效果:
- using System.Text;
- using System.Text.RegularExpressions;
- var dictionary = new Dictionary<(double, double), double>();
- var files = Directory.GetFiles(Environment.CurrentDirectory, "*.txt", SearchOption.AllDirectories);
- foreach (var file in files)
- {
- using var reader = new StreamReader(file);
- while (!reader.EndOfStream)
- {
- var line = reader.ReadLine()?.Trim();
- if (string.IsNullOrEmpty(line))
- {
- continue;
- }
- line = Regex.Replace(line, "( ){2,}", " ");
- var values = line.Split(' ');
- var key = (double.Parse(values[0]), double.Parse(values[1]));
- var value = double.Parse(values[2]);
- dictionary[key] = value;
- }
- }
- if (File.Exists("result.txt")) File.Move("result.txt", [ DISCUZ_CODE_1 ]quot;result_{DateTime.Now:yyyyMMddHHmmss}).txt");
- using var writer = new StreamWriter("result.txt", false, Encoding.UTF8);
- foreach (var (key, value) in dictionary)
- {
- writer.WriteLine([ DISCUZ_CODE_1 ]quot;{key.Item1} {key.Item2} {value}");
- }
复制代码
|
评分 Rate
-
查看全部评分 View all ratings
|