2016. 02. 03 / 하루생각 Blog
[OpenFOAM 기본] OpenFOAM 문법 기본
들어가기 |
OpenFOAM 을 이용한 코드 작성 및 분석을 위한 기본 문법
기준 OpenFOAM 버전 |
OpenFOAM 2.2 ~ 3.0 정도
- label 정수
- scalar 스칼라(실수)
- vector 벡터
- word 문자열
- bool 논리형
- dimensionedScalar 스칼라
- dimensionedVector 벡터
dimensionSet으로 단위를 정의한다.
// m/s
dimensionSet dim(0, 1, -1, 0, 0, 0, 0); // [kg m s K mol A Cd]
dimensionedVector vel("vel", dimensionSet(0, 1, -1, 0, 0, 0, 0), vector(0., 0., 0.));
dimensionedVector acc("acc", dimensionSet(0, 1, -2, 0, 0, 0, 0), vector(0., 0., 0.));
vector v = vel.value(); // 값 추출
dimensionSet dim(vel.dimensions()); // 단위 추출
단위의 프리셋
- dimless (무차원)
- dimMass
- dimLength
- dimTemperature
- dimArea
- dimVolume
- dimVelocity
- dimAcceleration
- dimDensity
- dimForce
- dimEnergy
- dimPressure
dimensionedVector vel("vel", dimLength/dimTime, vector(0., 0., 0.));
dimensionedVector acc("acc", dimLength/sqr(dimTime), vector(0., 0., 0.));
dimensionedVector vel("vel", dimVelocity, vector(0., 0., 0.)); dimensionedVector acc("acc", dimAcceleration, vector(0., 0., 0.));
List&<label> a; // label 의 리스트
a.append(1);
a.append(2);
a.append(3);
forAll(a, i)
{
Info<< a[i] << endl;
}
키워드 부분은, 다음과 같은 형식이다.
<키워드> <항목 1> <항목 2> ... <항목 N>;
단위의 프리셋
- labelList
- scalarList
- vectorList
- wordList
- boolList
단위를 포함하는 리스트
- volScalarField 셀의 스칼라장
- volVectorField 셀의 벡터장
- surfaceScalarField 면의 스칼라장
- surfaceVectorField 면의 벡터장
스칼라 |
a = sqr(x); // 2 승
a = pow2(x); // 2 승
a = pow3(x); // 3 승
a = pow4(x); // 4 승
a = pow5(x); // 5 승
a = pow6(x); // 6 승
a = pow025(x); // 0.25 승
a = pow(x, r); // r 승
스칼라 |
scalar vy = v.y();
scalar vz = v.z();
scalar b = magSqr(v1); // sqr(mag(v1))
vector v4 = v1 - v2;
텐서 |
1., 2., 3.,
4., 5., 6.,
7., 8., 9.
);
scalar txy = t.xy();
scalar txz = t.xz();
scalar tyx = t.yx();
...
scalar tzz = t.zz();
scalar b = magSqr(t); // 각성분의 magSqrt() 의 합
SymmTensor<scalar> t3 = twoSymm(t); // 2.*sym(t)
Tensor<scalar> t3 = dev2(t); // t - 2./3.*tr(t)
scalar b = invariantII(t); // 제2불변량
scalar c = invariantIII(t); // 제3불변량
Tensor<scalar> t2 = eigenVectors(t);
필드 |
scalar pmax = max(p).value();
scalar pmin = min(p).value();
Yi.max(0.);
Yi.min(1.);
입출력 |
Info<< "hello" << endl;
Info<< "x = " << x << endl;
Info<< "v = ("
<< v[0] << ", " << v[1] << ", " << v[2]
<< ")" << endl;
에러정지
(
"main()" // 위치
) << "Error" // 에러 메세지
<< exit(FatalError); // 종료
기존의 딕셔너리를 사용
label n(readLabel(transportProperties.lookup("n"));
scalar a(readScalar(transportProperties.lookup("a")));
vector v(transportProperties.lookup("v"));
word w(transportProperties.lookup("w"));
bool b(readBool(transportProperties.lookup("b")));
dimensionedScalar x(transportProperties.lookup("x"));
// system/fvSolutions
dictionary piso(mesh.solutionDict().subDict("PISO"));
bool b = piso.lookupOrDefault("b", true);
label n = piso.lookupOrDefault("n", 0);
직접 딕셔너리를 작성
IOdictionary myDict
(
IOobject(
"myDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
시간 |
const word &t = mesh.time().timeName();
scalar t = runTime.timeOutputValue();
scalar t = mesh.time().timeOutputValue();
scalar deltaT = mesh.time().deltaTValue();
{
...
}
격자 |
격자
|
polyMesh |
fvMesh (polyMesh 계승) |
셀 |
cells |
- |
면 |
faces |
- |
점 |
points |
- |
면 소유 셀 |
faceOwner |
owner (내부 면) |
면 접근 셀 |
faceNeighbour |
neighbour |
셀 중심 |
cellCentres |
C |
면 중심 |
faceCenteres |
Cf (내부 면) |
셀 체적 |
cellVolumes |
V |
면 면적 |
faceAreas |
Sf, magSf (내부 면) |
경계 격자 |
boundaryMesh |
boundary |
셀 존 |
cellZones |
- |
면 존 |
faceZones |
- |
경계 격자
|
polyBoundaryMesh |
fvBoundaryMesh |
polyPatch |
operator[] |
patch |
fvPatch |
- |
operator[] |
패치
|
polyMesh |
fvPatch |
이름 |
name |
name |
타입 |
type |
type |
물리타입 |
physicalType |
- |
면 |
operator[] |
- |
셀 ID |
faceCells |
faceCells |
면 중심 |
faceCentres |
Cf |
셀 중심 |
faceCellCentres |
Cn |
면 면적 |
faceAreas |
Sf, mag Sf |
polyPatch |
|
patch |
{
const cell &c = mesh.cells()[cid];
...
}
forAll(mesh.cells(), cid)
{
const cell &c = mesh.cells()[cid];
forAll(c, cfid)
{
label fid = c[cfid];
...
}
}
forAll(mesh.cells(), cid)
{
const cell &c = mesh.cells()[cid];
forAll(mesh.cellPoints()[cid], cpid)
{
label pid = mesh.cellPoints()[cid][cpid];
...
}
}
// 면 별
forAll(mesh.faces(), fid)
{
const face &f = mesh.faces()[fid];
forAll(f, fpid)
{
label pid = f[fpid];
...
}
}
{
const cell &c = mesh.cells()[cid];
forAll(mesh.cellCells()[cid], ccid)
{
label ncid = mesh.cellCells()[cid][ccid];
...
}
}
// 면 별
forAll(mesh.cells(), cid)
{
const cell &c = mesh.cells()[cid];
forAll(c, cfid)
{
label fid = c[cfid];
if (!mesh.isInternalFace(fid)) continue;
label ncid = mesh.faceNeighbour()[fid];
...
}
}
forAll(mesh.faces(), fid)
{
const face &f = mesh.faces()[fid];
...
}
//내부 면
forAll(mesh.faces(), fid)
{
if (!mesh.isInternalFace(fid)) continue;
const face &f = mesh.faces()[fid];
...
}
{
const face &f = mesh.faces()[fid];
forAll(f, fpid)
{
label pid = f[fpid];
...
}
}
{
const point &p = mesh.points()[pid];
...
}
const vector &x = mesh.Cf()[fid]; //내부 면
const vector &S = mesh.Sf()[fid]; // 내부 면
scalar magS = mesh.magSf()[fid]; // 내부 면
label cid = mesh.owner()[fid]; // 내부 면
label cid = mesh.faceNeighbour()[fid];
label cid = mesh.neighbour()[fid];
const vector &x = p;
{
const polyPatch &patch = mesh.boundaryMesh()[bid];
...
}
forAll(mesh.boundary(), bid)
{
const polyPatch &patch = mesh.boundary()[bid].patch();
...
}
forAll(mesh.faces(), fid)
{
if (mesh.isInternalFace(fid)) continue;
const face &f = mesh.faces()[fid];
...
}
// 패치 별
forAll(mesh.boundaryMesh(), bid)
{
const polyPatch &patch = mesh.boundaryMesh()[bid];
forAll(patch, pfid)
{
const face &f = patch[pfid];
...
}
}
// empty 경계를 제외
forAll(mesh.boundary(), bid)
{
const fvPatch &patch = mesh.boundary()[bid];
forAll(patch, pfid)
{
...
}
}
// 면 별
forAll(mesh.faces(), fid)
{
if (mesh.isInternalFace(fid)) continue;
label cid = mesh.owner()[fid];
const cell &c = mesh.cells()[cid];
...
}
// 패치 별
forAll(mesh.boundaryMesh(), bid)
{
const polyPatch &patch = mesh.boundaryMesh()[bid];
forAll(patch.faceCells(), pcid)
{
label cid = patch.faceCells()[pcid];
const cell &c = mesh.cells()[cid];
...
}
}
// empty 경계를 제외
forAll(mesh.boundary(), bid)
{
const fvPatch &patch = mesh.boundary()[bid];
forAll(patch.faceCells(), pcid)
{
label cid = patch.faceCells()[pcid];
const cell &c = mesh.cells()[cid];
...
}
}
// 경계 ID 로부터
const polyPatch &patch = mesh.boundaryMesh()[bid];
const polyPatch &patch = mesh.boundary()[bid].patch();
// 패치 이름으로부터
const polyPatch &patch = mesh.boundaryMesh()[name];
const polyPatch &patch = mesh.boundary()[name].patch();
// 경계면 ID 로부터
label bid = mesh.boundaryMesh().whichPatch(fid);
const polyPatch &patch = mesh.boundaryMesh()[bid];
// fvPatch
const fvPatch &patch = mesh.boundary()[bid];
const fvPatch &patch = mesh.boundary()[name];
label pid = mesh.boundary().findPatchID(name);
const word &name = patch.name(); // 이름
const word &type = patch.type(); // 타입
const word &physicalType = patch.physicalType(); // 물리타입
const fvPatch &patch = mesh.boundary()[bid];
const word &name = patch.name(); // 이름
const word &type = patch.type(); // 타입
const vector &x = mesh.boundary()[bid].Cf()[fid];
const vector &x = mesh.boundary()[bid].Cn()[cid];
const vector &S = mesh.boundary()[bid].Sf()[fid];
const scalar magS = mesh.boundary()[bid].magSf()[fid];
const labelList& cells = mesh.cellZones()[id];
const labelList& faces = mesh.faceZones()[id];
격자 |
vector Uc = U[cid]; // volVectorField
scalar pfv = pf[fid];
surfaceVectorField Uf = fvc::interpolate(U);
vector Ufv = Uf[fid];
scalar pfv = p.boundaryField()[bid][bfid];
vector Ufv = U.boundaryField()[bid][bfid];
const polyPatch &patch = U.boundaryField()[bid].patch().patch();
const fvPatchField &pb = patch.lookupPatchField("p");
const fvPatchField &Ub = patch.lookupPatchField("U");
const volVectorField &U0 = U.prevIter(); // 이전 반복문에서의 값
각각 storeOldTimes(), storePrevIter()로 데이터를 저장해 놓아야 한다. storeOldTimes()은 이미 코드 중에 사용되어있는 경우가 있다(internalFiled() 명령어 등에서)
이미 존재하는 필드를 복사해 이름을 붇인다.
volVectorField my_U("my_U", U);
제대로 만드려면
(
IOobject
(
"my_p",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar("my_p", sqr(dimLength)/sqr(dimTime), 0.)
);
volVectorField my_U
(
IOobject
(
"my_U",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedVector("my_U", dimVelocity, vector(0., 0., 0.))
);
IOobject::NO_READ, IOobject::NO_WRITE는 필드 데이터의 입출력설정.
입력
- NO_READ : 불러오지 않는다
- MUST_READ : 필수적으로 불러온다
- READ_IF_PRESENT : 존재하면 불러온다
출력
- NO_WRITE: 출력하지 않는다
- AUTO_READ : 출력한다
NO_READ,NO_WRITE를 동시에 지정할경우, 입출력설정의 인수를 생략할 수 있다.
U.writeOpt() = IOobject::NO_WRITE; // 출력하지 않는다
forAll(fp, celli)
{
fp[celli] = ... ;
}
forAll(f.boundaryField(), patchi)
{
fvPatchScalarField &fbp = f.boundaryField()[patchi];
const fvPatch &patch = fbp.patch();
forAll(patch, facei)
{
const label owner = patch.faceCells()[facei]; // 면셀 ID (필요하다면)
fbp[facei] = ... ;
}
}
주의 : 필드 내부의 값은 직접편집가능하다, internalField()를 이용해 불러와 놓지 않으면 값의 변경을 인식하지 않는다.
대수방정식 |
volScalarField x("x", p);
fvScalarMatrix m(x, dimless);
// 4 1 0
// 2 6 1
// 0 2 5
m.diag()[0] = 4;
m.diag()[1] = 6;
m.diag()[2] = 5;
m.upper()[0] = 1;
m.upper()[1] = 1;
m.lower()[0] = 2;
m.lower()[1] = 2;
// RHS
m.source()[0] = 2;
m.source()[1] = -8;
m.source()[2] = 6;
m.solve();
// x = [1 -2 2]'
Info<< "x =" << endl;
forAll(x, i)
{
Info<< x[i] << endl;
}
3 x 1 격자의 경우, 셀이 0-1-2로 배열되어 셀 0과 셀2는 관계가 없으므로 행렬의 (0,2) 및 (2,0)의 성분은 0이 되고 그 이외의 값이 입력된다.
r = m.solve().finalResidual(); // 풀고 난 후의 Residual
m.upper()[i] = a; // cid < nid
m.lower()[i] = a; // cid > nid
병렬처리 |
필드의 평균값이나 최대,최소값 등을 계산할 경우 보통 병렬계산 시 파티션별로 계산되어 전체의 값을 계산할 수 없다. 전체의 값을 계산하기위해서 reduce()를 사용한다.
예를들면, 전체셀수를 계산할 경우, 다음과 같다.
reduce(cells, sumOp());
reduce()의 첫번째 인수는 처리하고싶은 변수, 두번째 변수는 연산의 지정으로 sumOp()이외에 아래와 같은 것이 있다.
- sumOp
- minOp
- maxOp
- andOp
- orOp
[원문출처 : http://onedayof.tistory.com/entry/OpenFOAM-기본-OpenFOAM-문법-기본]
번호 | 제목 | 작성 | 조회수 |
---|---|---|---|
29 | '넷XMS·오픈NMS·판도라FMS·자빅스' 오픈소스 관리 툴 4종 분석 | 2017-02-16 | 2454 |
28 | [OpenFOAM] 열유체의 구배방정식 (OpenFOAM 배경이론 간단정리) | 2017-02-06 | 1475 |
27 | [IT열쇳말] 라즈베리파이 file | 2017-01-06 | 1891 |
26 | [OpenFOAM] OpenFOAM 문법 기본 (OpenFOAM 기본) | 2016-12-23 | 2446 |
25 | 학교에선 알려주지 않는 오픈소스이야기 | 2016-12-06 | 1054 |
24 | ITWorld 용어풀이 | 쿠키 | 2016-12-05 | 1342 |
23 | [IT열쇳말] 소프트웨어 정의 네트워크(SDN) | 2016-11-29 | 1892 |
22 | [IT열쇳말] 유니티 | 2016-11-15 | 1507 |
21 | 마이크로소프트 애저의 오픈소스 서버 및 랙 설계 들여다 보기 | 2016-11-07 | 1115 |
20 | [IT열쇳말] 혼합현실 | 2016-11-01 | 1501 |
0개 댓글