●苗志宏,馬金強(qiáng)
(武警學(xué)院 消防工程系,河北廊坊 065000)
FDS(Fire Dynamics Simulator)是美國(guó)國(guó)家技術(shù)標(biāo)準(zhǔn)局(NIST)建筑火災(zāi)實(shí)驗(yàn)室開(kāi)發(fā)的基于場(chǎng)模擬的火災(zāi)動(dòng)力學(xué)模擬軟件[1-2]。它采用數(shù)值方法求解一系列適用于低速流動(dòng)熱驅(qū)動(dòng)形的N-S方程,并以火災(zāi)時(shí)的煙氣流動(dòng)和熱傳遞過(guò)程為重點(diǎn)研究對(duì)象。FDS的特點(diǎn)是針對(duì)性較強(qiáng),可以得到比較詳細(xì)的物理量的時(shí)空分布,能精細(xì)地體現(xiàn)火災(zāi)現(xiàn)象。目前FDS已經(jīng)被用來(lái)解決消防領(lǐng)域中的一些實(shí)際問(wèn)題,在火災(zāi)理論研究、建筑性能化設(shè)計(jì)中,常用這種方法來(lái)模擬火災(zāi)過(guò)程[3-4]。但是,F(xiàn)DS是基于控制臺(tái)的應(yīng)用程序,場(chǎng)景建模文件的構(gòu)建只能通過(guò)手工編輯文本文件的方式進(jìn)行,文件編輯需要熟悉FDS的文件格式和記憶大量的命令;同時(shí),F(xiàn)DS的模擬計(jì)算結(jié)果需要使用SmokeView軟件來(lái)展現(xiàn)三維場(chǎng)景,它們都需要用戶回到DOS環(huán)境中使用命令形式來(lái)調(diào)用,這些對(duì)于FDS的用戶是個(gè)不小的困難,直接影響著軟件的應(yīng)用效率。因此,對(duì)FDS的場(chǎng)景建模環(huán)境進(jìn)行專門(mén)的研究和開(kāi)發(fā),使其擁有更強(qiáng)的功能和更高的效率,成為火災(zāi)和消防科學(xué)領(lǐng)域的設(shè)計(jì)及研究人員關(guān)注的重點(diǎn)課題[5-7]。本文給出了一個(gè)Windows下基于圖形用戶界面的FDS場(chǎng)景建模環(huán)境的設(shè)計(jì)過(guò)程。該環(huán)境集FDS場(chǎng)景建模文檔編輯、FDS運(yùn)算、FDS運(yùn)算步驟輸出以及SmokeView的運(yùn)行為一身,可以使火災(zāi)模擬的效率大大提高。
火災(zāi)模擬軟件FDS編程環(huán)境的主界面如圖1所示,其組成主要部分有主框架和客戶區(qū)。在主框架中有標(biāo)題欄、菜單欄、工具欄和狀態(tài)欄??蛻魠^(qū)由3個(gè)子窗口組成,分別是工作目錄窗口、編輯窗口和運(yùn)算過(guò)程顯示窗口,其中編輯窗口可同時(shí)打開(kāi)多個(gè)文檔。FDS的場(chǎng)景建模命令在編輯窗口中按文本文件進(jìn)行編輯,具有一般文本編輯的各種功能,并且對(duì)FDS命令的關(guān)鍵字具有語(yǔ)法識(shí)別功能,并按高亮顯示。工作目錄窗口按樹(shù)型目錄顯示當(dāng)前工作目錄中的所有文件,這樣FDS運(yùn)算輸出文件也顯示在其中,選中文件后雙擊鼠標(biāo)右鍵可打開(kāi)文件。運(yùn)算過(guò)程顯示窗口顯示FDS運(yùn)算過(guò)程的步驟信息,這里我們將FDS原來(lái)在控制臺(tái)下的步驟顯示重定向到該窗口,并屏蔽了控制臺(tái)窗口。狀態(tài)欄中能顯示當(dāng)前運(yùn)算的信息和當(dāng)前光標(biāo)所在的行號(hào)和列號(hào)。建模環(huán)境主界面與FDS后臺(tái)運(yùn)算的連接是設(shè)計(jì)的核心部分,其運(yùn)行結(jié)構(gòu)圖如圖2所示。
圖1 FDS場(chǎng)景建模環(huán)境主界面
圖2 FDS場(chǎng)景建模運(yùn)行結(jié)構(gòu)圖
FDS編程環(huán)境的主要功能包括:多文檔編輯,調(diào)用外部程序FDS,運(yùn)算過(guò)程顯示等。場(chǎng)景建模環(huán)境由VC++6.0平臺(tái)進(jìn)行設(shè)計(jì),采用MFC的多文檔視圖模式進(jìn)行開(kāi)發(fā)。開(kāi)發(fā)基本過(guò)程如下:
窗口界面是用戶的主要操作區(qū)域,如圖1所示??蛻魠^(qū)中的工作目錄窗口和運(yùn)算過(guò)程顯示窗口是以浮動(dòng)窗口方式設(shè)計(jì)的,初始情況下分別??吭谥鞔翱诘淖筮吅拖露?。其主要實(shí)現(xiàn)過(guò)程是采用了Cristi Posea提供的 CSizingControlBar類和 CSizingControl-BarG 類(類聲明和實(shí)現(xiàn)文件是:sizecbar.h,sizecbar.cpp,源代碼見(jiàn) http://www.codeproject.com/Articles/6/CSizingControlBar-a-resizable-control-bar),它們是從MFC中CControlBar類繼承來(lái)的。
為此,在工程FdsEditor中載入文件sizecbar.h,sizecbar.cpp,scbarg.h,scbarg.cpp,并在 stdafx.h 文件中添加文件包含指令:#include"sizecbar.h"#include"scbarg.h"。這樣就可以在主框架類CMain-Frame中添加以下3個(gè)成員對(duì)象:(1)CSizingControl-BarG m_wndLeftBar(工作目錄窗口);(2)CBottomBar m_wndBottomBar(運(yùn)算過(guò)程顯示窗口);(3)CTreeCtrl m_wndTree(工作目錄窗口中的樹(shù)狀目錄)。這里CBottomBar是CSizingControlBarG的公有派生類,在其中添加了CEdit類型的公有成員對(duì)象m_wndEdit,它是運(yùn)算過(guò)程顯示窗口中的編輯框。并在CBottom-Bar類中重寫(xiě)WM_CREATE消息映射函數(shù)OnCreate()。在CMainFrame類的成員函數(shù)OnCreate()中,可調(diào)用Create函數(shù)來(lái)實(shí)現(xiàn)上面3個(gè)成員對(duì)象的創(chuàng)建和控制窗口的初始??课恢?這里省去了代碼實(shí)現(xiàn)部分)。
關(guān)鍵字高亮編輯器的設(shè)計(jì)使用了已有的類CSynEditView[8],該類是 CRichEditorView 的派生類,既繼承了CRichEditorView類的所有功能,又具有關(guān)鍵字高亮顯示的特點(diǎn),因此在工程中將視類CFdsEditorView設(shè)置為CSynEditView的派生類。為使FDS的建模關(guān)鍵字按高亮顯示,這里需要在CSynEdit-View類的成員函數(shù)LoadSynWord(INT nLanguage)的分支結(jié)構(gòu)switch中添加FDS建模語(yǔ)句的關(guān)鍵字,如&HEAD、&MISC等(這里省去了代碼實(shí)現(xiàn)部分)。
建模環(huán)境主界面與FDS后臺(tái)運(yùn)算的連接是本設(shè)計(jì)的核心部分。本文建模環(huán)境中FDS運(yùn)算過(guò)程是通過(guò)建立一個(gè)線程[9]來(lái)開(kāi)啟FDS運(yùn)算引擎的,主要是通過(guò)調(diào)用線程創(chuàng)建函數(shù)AfxBeginThread()來(lái)實(shí)現(xiàn)。通過(guò)主框架中運(yùn)算按鈕的響應(yīng)函數(shù)OnBuildFds5()來(lái)調(diào)用AfxBeginThread(),其調(diào)用流程如圖3所示。
圖3 FDS運(yùn)算調(diào)用流程圖
其實(shí)現(xiàn)代碼為:
void CMainFrame::OnBulidFds5()
{
//TODO:Add your command handler code here
//Step 1:讀取FDS安裝路徑//
ifstream infile("FdsPath.txt");//FDS安裝路徑已存放在 FdsPath.txt中
if(!infile)
{MessageBox("請(qǐng)先設(shè)置FDS的安裝路徑!");
return;}
char str[255];
int i=0;
while(infile.get(str[i++ ]))
{}
strFdsSetupPath=str;//存放FDS安裝路徑
infile.close();
//Step 2:重新或繼續(xù)運(yùn)算選擇//
CString strStop;//存放stop文件路徑
strStop=GetFdsStopFile();
//先判斷*.stop是否存在,如果存在則刪除掉!
if(strStop!="")//有否stop文件
{DeleteFile(strStop);//刪除stop文件
UINT nRet=MessageBox("檢測(cè)到stop文件,如果要繼續(xù)上次運(yùn)算,則請(qǐng)?jiān)贛ISC語(yǔ)句里添加:RESTART=.TRUE.;選擇確定按鈕,則回到文件添加:RESTART=.TRUE.;選擇取消按鈕,則重新計(jì)算.","Stop 文件",MB_OKCANCEL);
if(nRet==IDOK)
{return;}
}
//Step 3:設(shè)置運(yùn)算狀態(tài)//
BuildState=1;
SmokeviewState=FALSE;
//Step 4:獲取FDS建模文檔//
GetFdsDocPath();
//Step 5:為FDS創(chuàng)建和啟動(dòng)一個(gè)線程//
if(strFdsSetupPath!="")
AfxBeginThread(FDSThreadFun,this);
}
上面代碼中分別調(diào)用了成員函數(shù)GetFdsDocPath(),GetFdsStopFile()來(lái)獲取FDS建模文檔的路徑和中斷文件(*.stop)的路徑。由于篇幅問(wèn)題這里略去實(shí)現(xiàn)代碼,其方法是先獲得活動(dòng)文檔類的指針,然后調(diào)用文檔類的函數(shù)GetPathName()來(lái)實(shí)現(xiàn)。
在主框架類CMainFrame中添加一個(gè)靜態(tài)成員函數(shù) FDSThreadFun(),以它作為函數(shù) AfxBeginThread中的線程的入口函數(shù),并聲明一個(gè)全局線程句柄m_hThread。
為重定向控制臺(tái)下運(yùn)算步驟信息至本環(huán)境的相應(yīng)窗口中,在函數(shù)FDSThreadFun()中通過(guò)調(diào)用API函數(shù) CreatePipe()來(lái)創(chuàng)建匿名管道(Anonymous Pipes),并將標(biāo)準(zhǔn)輸出重定向到匿名管道。然后通過(guò)API函數(shù)CreateProcess()來(lái)創(chuàng)建一個(gè)子進(jìn)程實(shí)現(xiàn)對(duì)外部應(yīng)用軟件FDS的調(diào)用,并利用ReadFile()函數(shù)來(lái)讀取匿名管道中的運(yùn)算步驟信息。最后將運(yùn)算步驟信息重新顯示在主框架的下端窗口中。
為實(shí)現(xiàn)FDS運(yùn)算中途暫停和停止,在主框架中的工具欄增加“暫停/繼續(xù)”和“停止”兩個(gè)按鈕。FDS的暫停運(yùn)算是通過(guò)使用SuspendThread掛起該線程來(lái)實(shí)現(xiàn)的,繼續(xù)運(yùn)算是使用線程恢復(fù)函數(shù)ResumeThread來(lái)實(shí)現(xiàn)的?!皶和?繼續(xù)”的響應(yīng)函數(shù)代碼如下:
void CMainFrame::OnBulidSuspendAndContinue()
{
//TODO:Add your command handler code here
m_fdsRun=!m_fdsRun;//FDS是否處于運(yùn)算狀態(tài)
if(m_fdsRun)
{::SuspendThread(m_hThread);
m_wndToolBar.SetButtonText(11,"繼續(xù)");}
else
{::ResumeThread(m_hThread);
m_wndToolBar.SetButtonText(11,"暫停");
}}
由于FDS內(nèi)核采用大渦模擬算法,運(yùn)算時(shí)間會(huì)很長(zhǎng),因此在工具欄中添加了“停止”按鈕來(lái)中途停止運(yùn)算,以便下次從原來(lái)停止的地方繼續(xù)運(yùn)算。為此,在“停止”按鈕的響應(yīng)函數(shù)中,實(shí)現(xiàn)了自動(dòng)產(chǎn)生Stop文件的過(guò)程。
輸入的建模文檔經(jīng)過(guò)FDS運(yùn)算后,就會(huì)輸出可以在SmokeView中打開(kāi)的smv文件。為啟動(dòng)Smoke-View模塊并在其中同時(shí)打開(kāi)smv文件,在主框架的工具欄中添加了“SmokeView”按鈕,其響應(yīng)函數(shù)如下所示:
void CMainFrame::OnBuildSmokeview()
{
//TODO:Add your command handler code here
CString strChid;
strChid=GetFdsCHIDFile();//獲得輸出文件名
strChid=strChid+".smv";//加擴(kuò)展名 smv
if(BuildSuccess)//運(yùn)算成功
//啟動(dòng)smokeview,并打開(kāi)當(dāng)前的smv文件
ShellExecute(NULL,"open","smokeview.exe",strChid,"",SW_SHOW);
else//啟動(dòng) smokeview
ShellExecute(NULL,"open","smokeview.exe",NULL,"",SW_SHOW);
}
上面代碼中使用了API函數(shù)ShellExecute來(lái)調(diào)用外部程序SmokeView。
下面實(shí)際運(yùn)行設(shè)計(jì)好的FDS場(chǎng)景建模環(huán)境,為此選用FDS5.0提供的一個(gè)例子room_fire.fds來(lái)運(yùn)行,打開(kāi)文件后,進(jìn)行運(yùn)算,其最終的運(yùn)算效果圖如圖4所示。
圖4 運(yùn)算效果圖
本文設(shè)計(jì)出了Windows下的FDS場(chǎng)景建模環(huán)境,該環(huán)境采用類似VC++6.0開(kāi)發(fā)界面風(fēng)格進(jìn)行設(shè)計(jì),使FDS場(chǎng)景建模文檔編輯、FDS運(yùn)算、FDS運(yùn)算步驟輸出以及SmokeView的運(yùn)行為一體。本環(huán)境屏蔽了FDS基于控制臺(tái)的參數(shù)輸入輸出過(guò)程,使FDS的建模輸入和運(yùn)算輸出展現(xiàn)在同一個(gè)圖形用戶界面中。使用本文設(shè)計(jì)的FDS場(chǎng)景建模環(huán)境可以大大提高火災(zāi)模擬的效率。
[1]Kevin McGrattan,Bryan Klein,Simo Hostikka,et al.Fire Dynamics Simulator(Version 5)User’s Guide[M].US:National Institute of Standards and Technology,2009.
[2]Kevin McGrattan,Simo Hostikka,Jason Floyd,et al.Fire Dynamics Simulator(Version 5)Technical Reference Guide[M].US:National Institute of Standards and Technology,2009.
[3]霍然.性能化建筑防火分析與設(shè)計(jì)[M].合肥:安徽科學(xué)技術(shù)出版社,2003.
[4]李引擎.建筑防火性能化設(shè)計(jì)[M].北京:化學(xué)工業(yè)出版社,2005.
[5]陳馳,任愛(ài)珠,張新.基于虛擬現(xiàn)實(shí)的建筑火災(zāi)模擬系統(tǒng)[J].自然災(zāi)害學(xué)報(bào),2007,16(1):55-60.
[6]邵鋼,金浩,楊培中,等.可視化隧道火災(zāi)仿真系統(tǒng)開(kāi)發(fā)[J].計(jì)算機(jī)仿真,2007,24(3):198-206.
[7]吳煒煜,高佐人,任愛(ài)珠.基于FDS的火場(chǎng)空間物理建模器研究[J].系統(tǒng)仿真學(xué)報(bào),2005,17(8):1800-1802.
[8]夏俊杰,趙剛.基于MFC的代碼編輯器設(shè)計(jì)方法[J].現(xiàn)代電子技術(shù),2012,35(12):28-30.
[9]孫鑫.VC++深入詳解[M].修訂版.北京:電子工業(yè)出版社,2012.