计算化学公社

标题: cp2k计算平面平均LDOS的后处理脚本 [打印本页]

作者
Author:
Stardust0831    时间: 2025-4-1 00:55
标题: cp2k计算平面平均LDOS的后处理脚本
本帖最后由 Stardust0831 于 2025-4-1 00:58 编辑

几个月前,我在文献里看到了这样的图 (, 下载次数 Times of downloads: 48) 。图中通过平面平均的LDOS来展现异质结界面的能带弯曲。在尝试用cp2k+multiwfn重复的时候,发现multiwfn只能计算某条线上的LDOS,由于修改multiwfn源代码遇到了环境问题,我基于multiwfn现有的计算某条线的LDOS的功能写了个批处理脚本,可以批量计算上不同(X,Y)坐标对应的垂直于Z平面的线上的LDOS,对这些不同的(X,Y)坐标下得到的值取平均,取的点足够密时也就实现了平面平均。此脚本避免了反复读取molden文件而增加耗时。该脚本需要使用powershell7运行。由于是依赖于multiwfn的已有功能完成的计算,这个LDOS的结果是gamma点而非考虑了不同k点。考虑特定k点的这一部分我暂时没有想到很好的解决策略,就用这个脚本抛砖引玉一下,看看各位大佬有没有更好的思路。
以下为脚本本体,部分内容根据备注自行修改:
  1. #!/usr/bin/pwsh
  2. # ./auto.ps1 -OutputFolder /opt/example/output
  3. param(
  4.   [string] $OutputFolder = $PSScriptRoot
  5. )
  6. function Start-Multiwfn
  7. {
  8.   param(
  9.     [string] $MultiwfnPath,
  10.     [string] $MoldenFile,
  11.     [System.IntPtr] $Affinity
  12.   )
  13.   $startInfo = New-Object System.Diagnostics.ProcessStartInfo
  14.   $startInfo.RedirectStandardInput = $true
  15.   $startInfo.RedirectStandardOutput = $true
  16.   $startInfo.StandardInputEncoding = [System.Text.Encoding]::UTF8
  17.   $startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
  18.   $startInfo.FileName = $MultiwfnPath
  19.   $startInfo.Arguments = "$MoldenFile -slient"
  20.   $process = [System.Diagnostics.Process]::Start($startInfo)
  21.   $process.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::RealTime
  22.   $process.ProcessorAffinity = $Affinity
  23.   $process.Refresh()
  24.   
  25.   return $process
  26. }
  27. function Push-Data
  28. {
  29.   param(
  30.     [string] $StartPoint,
  31.     [string] $EndPoint,
  32.     [int] $Number
  33.   )
  34.   # Wait input until specific output
  35.   while ($true)
  36.   {
  37.     if ($Reader.Peek() -le 0)
  38.     {
  39.       Start-Sleep -Seconds 1
  40.       Write-Host $s
  41.       ++$s
  42.       continue
  43.     }
  44.    
  45.     $line = $Reader.ReadLine()
  46.     Write-Host $line
  47.     if ($line.Contains('========== Plot density-of-states (DOS) =========='))
  48.     {
  49.       break
  50.     }
  51.   }
  52.   
  53.   $Writer.WriteLine("11")
  54.   
  55.   Start-Sleep -Seconds 1
  56.   $Writer.WriteLine($StartPoint)
  57.   
  58.   Start-Sleep -Seconds 1
  59.   $Writer.WriteLine($EndPoint)
  60.   
  61.   Start-Sleep -Seconds 1
  62.   $Writer.WriteLine($Number)
  63.   
  64.   $s = 0
  65.   while ($true)
  66.   {
  67.     if ($Reader.Peek() -le 0)
  68.     {
  69.       Start-Sleep -Seconds 1
  70.       Write-Host $s
  71.       ++$s
  72.       continue
  73.     }
  74.    
  75.     $line = $Reader.ReadLine()
  76.     Write-Host $line
  77.     if ($line.Contains('-------- Post-processing menu --------'))
  78.     {
  79.       break
  80.     }
  81.   }
  82.   
  83.   $Writer.WriteLine("3")
  84.   
  85.   while ($true)
  86.   {
  87.     if ($Reader.Peek() -le 0)
  88.     {
  89.       Start-Sleep -Seconds 1
  90.       Write-Host $s
  91.       ++$s
  92.       continue
  93.     }
  94.    
  95.     $line = $Reader.ReadLine()
  96.     Write-Host $line
  97.     if ($line.Contains('-------- Post-processing menu --------'))
  98.     {
  99.       break
  100.     }
  101.   }
  102.   $timestamp = Get-Date -Format "yyyyMMddHHmmss"
  103.   $filename = "LDOS" + "_" + $StartPoint + "_" + $EndPoint + "_" + $Number + "_$timestamp.txt"
  104.   # !!!IMPORTANT!!! Move and rename output file
  105.   Move-Item -Path "$PSScriptRoot/LDOS.txt" -Destination "$OutputFolder/$filename"
  106.   $Writer.WriteLine("0")
  107.   
  108. }
  109. # Script Entry
  110. try
  111. {
  112.   $timestamp = Get-Date -Format "yyyyMMddHHmmss"
  113.   $OutputFolder = [System.IO.Path]::Combine($OutputFolder, $timestamp)
  114.   [System.IO.Directory]::CreateDirectory($OutputFolder)
  115.   # !!!IMPORTANT!!! Start Multiiwfn process
  116.   $process = Start-Multiwfn -MultiwfnPath "$PSScriptRoot/Multiwfn.exe" -MoldenFile "$PSScriptRoot/test1/FAPbI3-ch3opeai-sp-MOS-1_0.molden" -Affinity 0xfff
  117.   $Reader = $process.StandardOutput
  118.   $Writer = $process.StandardInput
  119.   $s = 0
  120.   while ($true)
  121.   {
  122.     if ($Reader.Peek() -le 0)
  123.     {
  124.       Start-Sleep -Seconds 1
  125.       Write-Host $s
  126.       ++$s
  127.       continue
  128.     }
  129.    
  130.     $line = $Reader.ReadLine()
  131.     Write-Host $line
  132.     if ($line.Contains('************ Main function menu ************'))
  133.     {
  134.       break
  135.     }
  136.   }
  137.   $Writer.WriteLine("\r\n")
  138.   
  139.   # Add additional option, $Writer.WriteLine("10")
  140.   $Writer.WriteLine("10")
  141.   Start-Sleep -Seconds 1
  142.   $Writer.WriteLine("8")
  143.   Start-Sleep -Seconds 1
  144.   $Writer.WriteLine("2")
  145.   Start-Sleep -Seconds 1
  146.   $Writer.WriteLine("-10,2,2")
  147.   Start-Sleep -Seconds 1
  148.   $Writer.WriteLine("3")
  149.   Start-Sleep -Seconds 1
  150.   #$Writer.WriteLine("0.4")
  151.   Start-Sleep -Seconds 1
  152.   for ($i = 0; $i -lt 5; ++$i)
  153.   {
  154.     Push-Data -StartPoint "$i,0,0" -EndPoint "$i,0,30" -Number 20
  155.   }
  156.   $process.Close()
  157.   return
  158. }
  159. catch
  160. {
  161.   Write-Error $_.Exception
  162. }
  163. finally
  164. {
  165.   if (-not $process.HasExited){
  166.     $process.Close()
  167.   }
  168. }
复制代码


该脚本会把计算得到的不同线段的LDOS输出到特定文件夹,可以通过这个C#程序来完成对这些数据取平均,从而实现平面平均的效果:
  1. using System.Text;
  2. using System.Text.RegularExpressions;

  3. var dictionary = new Dictionary<(double, double), double>();
  4. var files = Directory.GetFiles(Environment.CurrentDirectory, "*.txt", SearchOption.AllDirectories);
  5. foreach (var file in files)
  6. {
  7.     using var reader = new StreamReader(file);
  8.     while (!reader.EndOfStream)
  9.     {
  10.         var line = reader.ReadLine()?.Trim();
  11.         if (string.IsNullOrEmpty(line))
  12.         {
  13.             continue;
  14.         }

  15.         line = Regex.Replace(line, "( ){2,}", " ");
  16.         var values = line.Split(' ');
  17.         var key = (double.Parse(values[0]), double.Parse(values[1]));
  18.         var value = double.Parse(values[2]);
  19.         dictionary[key] = value;
  20.     }
  21. }

  22. if (File.Exists("result.txt")) File.Move("result.txt", [        DISCUZ_CODE_1        ]quot;result_{DateTime.Now:yyyyMMddHHmmss}).txt");
  23. using var writer = new StreamWriter("result.txt", false, Encoding.UTF8);
  24. foreach (var (key, value) in dictionary)
  25. {
  26.     writer.WriteLine([        DISCUZ_CODE_1        ]quot;{key.Item1} {key.Item2} {value}");
  27. }
复制代码



作者
Author:
berserker.npc    时间: 2025-7-4 19:09
你好,我试着运行这个脚本,结果导入文件成功后就一直输出数字,是哪一部分的原因呢?
P1是运行脚本后的输出,P2是正常使用multiwfn导入文件后的结果,P3是我修改过的部分代码
作者
Author:
Stardust0831    时间: 2025-7-9 01:45
berserker.npc 发表于 2025-7-4 19:09
你好,我试着运行这个脚本,结果导入文件成功后就一直输出数字,是哪一部分的原因呢?
P1是运行脚本后的输 ...

可能是由于体系特殊,multiwfn输出变了,脚本没有捕获到预期的输出。
提供具体结构的cif文件以及molden文件,我这边帮你试一下。




欢迎光临 计算化学公社 (http://ccc.keinsci.com/) Powered by Discuz! X3.3