前言
上篇文章我們大體捋順了Pstream類,但上篇沒有講到的是Pstream類很多東西是從UPstream類繼承來的
這次我們大體看一下UPstream類,以避免Pstream類內很多繼承來的東西不會用
簡述幾個常用的函式如下:
Pstream::myProcNo()
//- Number of this process (starting from masterNo() = 0)
static int myProcNo(const label communicator = 0)
{
return myProcNo_[communicator];
}
就像我們提到的,靜態成員變數一般有兩種初始化方式,一種是全域區直接定義,另一種是利用靜態成員函式進行值的回傳,Pstream::myProcNo()是后者
輸入引數默認從零開始計算行程數量,回傳值型別為static DynamicList < int >,容器初始大小是10
//- My processor number
static DynamicList<int> myProcNo_;
Foam::DynamicList<int> Foam::UPstream::myProcNo_(10);
這里我覺得有必要擴展解釋下Foam::DynamicList,Foam內非常常見的一種資料型別
Foam::DynamicList,公有繼承于Foam::List的vector容器

openfoam對其的描述為:
A 1D vector of objects of type < T > that resizes itself as necessary to accept the new objects.
Internal storage is a compact array and the list can be shrunk to compact storage. The increase of list size is controlled by three template parameters, which allows the list storage to either increase by the given increment or by the given multiplier and divider (allowing non-integer multiples).
Foam::DynamicList的介紹里說是一個可以根據需要調整自身大小以接受新物件的一維容器,內部存盤是一個緊湊的陣列
講實話看解釋并沒有怎么理解,直接閱讀相關實作程式
#include "DynamicList.H"
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
template<class T, unsigned SizeInc, unsigned SizeMult, unsigned SizeDiv>
Foam::DynamicList<T, SizeInc, SizeMult, SizeDiv>::DynamicList(Istream& is)
:
List<T>(is),
capacity_(List<T>::size())
{}
template<class T, unsigned SizeInc, unsigned SizeMult, unsigned SizeDiv>
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const DynamicList<T, SizeInc, SizeMult, SizeDiv>& lst
)
{
os << static_cast<const List<T>&>(lst);
return os;
}
template<class T, unsigned SizeInc, unsigned SizeMult, unsigned SizeDiv>
Foam::Istream& Foam::operator>>
(
Istream& is,
DynamicList<T, SizeInc, SizeMult, SizeDiv>& lst
)
{
is >> static_cast<List<T>&>(lst);
lst.capacity_ = lst.List<T>::size();
return is;
}
首先看Foam::DynamicList的建構式,利用初始化串列創建了大小為輸入引數的List< T >,隨后又把這個大小給了相關的成員變數,后續是兩個多載,其他構造大同小異
那這就很清晰了,Foam::DynamicList本質上還是List,
但又有新的問題了,那為什么在openfoam釋義中提及vector或者array呢
能看到Foam::DynamicList并沒有多載[],寫到這里我原以為只是一個類似陣列一樣可以拓展記憶體的List時,無法像vector一樣隨機存盤,但無意間發現Foam::DynamicList多載了(),我把多載那部分給大家看一下哈
template<class T, unsigned SizeInc, unsigned SizeMult, unsigned SizeDiv>
inline T& Foam::DynamicList<T, SizeInc, SizeMult, SizeDiv>::operator()
(
const label elemI
)
{
if (elemI >= List<T>::size())
{
setSize(elemI + 1);
}
return this->operator[](elemI);
}
能看到是可以隨機存盤的,并且呼叫的this指標,說明內部是List< T > ,但是外殼是陣列
此刻我們就明白了Foam::DynamicList為什么說自己是一維容器,有兩種情況:
- 如果不超過陣列大小,在插入和讀取時,使用的List進行插入,復雜度僅是O(1)
- 但是超過陣列大小,進行插入操作,需要類似vector一樣重新分配空間,但又好在是List,重新分配空間無需復制粘貼折騰,只需要傳地址即可
并且在以上基礎上可以類似vector進行隨機訪問元素,兼顧了兩者優點
寫到這里不由得感慨,openfoam作為數值計算程式,在資料型別選擇上還是有自己獨到之處的,不僅要考慮安全性還要考慮效率
如果我需要插入或彈出一個資料,傳list地址即可,但是我還有隨機存盤需求,那就外邊套一層陣列的殼吧,擴容也方便
講到這里多提一嘴
類似的還有Foam::DLList,
namespace Foam
{
template<class T>
using DLList = LList<DLListBase, T>;
}
大概是包著List外殼的List容器,如果是這樣,插入復雜度是O(1),讀取復雜度是O(n)
那我們再回到問題的開始,為什么的型別是Foam::DynamicList
因為myProcNo_需要動態變化,如果出現行程的增加和刪減,可以類似陣列進行擴容,
所以在并行計算中,Foam::DynamicList使用的非常頻繁,后續會發現經常出現在其他并行函式的回傳值中
后續還有
Pstream::nProcs()
Pstream::myProcNo()
Pstream::parRun()
UPstream::exit(0)
這些函式需要去說下,今天有點累了,下期再聊
后續探索一定會有更多驚喜等待著我們
結語
一起探索openfoam也是相當有趣的一件事,非常歡迎私信討論
指正的價值要比打賞更重要,下面是個人聯系方式,能結交到志同道合的朋友是我的榮幸

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/544947.html
標籤:其他
