본문 바로가기

OpenFOAM/소스코드 파해치기

[OpenFOAM 소스코드 파해치기] 격자

일본어 원문링크


작성일 : 2009년 12월   5일
번역일 : 2016년  2월    9일


크롬 브라우저로 보시는 것을 권장해 드립니다.


 ------ OpenFOAM 소스코드 파해치기 시리즈 ------

OpenFOAM 소스코드 파해치기 목차로 이동

 ------------------------------------------------------------

 ----- OpenFOAM 소스코드를 다루는 문법 기본 -----

OpenFOAM 소스코드를 다루는 문법 기본으로 이동

 ------------------------------------------------------------



 

  들어가기 


격자 클래스 fvMesh를 사용해 본다.



  사용 버전 


OpenFOAM 1.6

 


   파일


이전과 같이 소스디렉토리식을 작성해보자. 데릭토리를 만들고 안에 아래와 같이 준비한다.(04-mesh.tar.gz)


  • Make/files
  • Make/options
  • system/controlDict
  • system/fvSchemes
  • system/fvSolution
  • constant/polyMesh/boundary
  • constant/polyMesh/faces
  • constant/polyMesh/neighbour
  • constant/polyMesh/owner
  • constant/polyMesh/points
  • mesh.C

Make 하위는 이전과 같다.


이전과 같이,  Time 클래스를 필요로 하는 OpenFOAM 설정용 딕셔너리 파일 controlDict를 준비하여야 한다. 더불어, 이번의 fvMesh는 fvSchemes과  fvSolution를 요구한다. 해당 파일들을 튜토리얼(예를들면 icoFoam; tutorials/incompressible/icoFoam)의 icoFoam/cavity/system에서 system폴더 내의 것을 복사하도록 한다.



  격자파일


 이번에는 격자를 다루므로, 격자파일을 준비하여야 한다. 


  • constant/polyMesh/boundary
  • constant/polyMesh/faces
  • constant/polyMesh/neighbour
  • constant/polyMesh/owner
  • constant/polyMesh/points 

여기서 다루는 격자는 단순화를 위해 1개의 셀만 가지는 격자를 사용한다.


boundary

FoamFile
{
    version 2.0;
    format ascii;


    root "/home/cfd/kasuga/tankentai/04-mesh"
    case "04-mesh";
    instance "constant";
    local "polyMesh";

    class polyBoundaryMesh;
    object boundary;
}

(
left
{
    type patch;
    nFaces 1;
    startFace 0;
    physicalType wall;
}

bottom
{
    type patch;
    nFaces 1;
    startFace 1;
    physicalType wall;
}

right
{
    type patch;
    nFaces 1;
    startFace 2;
    physicalType wall;
}

top
{
    type patch;
    nFaces 1;
    startFace 3;
    physicalType wall;
}
)


위는 경계정보를 가지는 파일이다. 제일 위의 "FoamFile {...}"는 형식상 이미 결정되어있는 내용이다. 그 이하의 "(...)"가 경계의 정보에 해당한다. "경계명 {...}"라는 형식으로 적혀져 있따. 각 항목은 아래와 같다.


  • type : 경계 타입
  • nFaces : 페이스(면) 수
  • startFace : 시작 페이스(면) 번호
  • physicalType : 물리적 타입

같은 경계의 페이스(면) 번호는 순차적으로 정의되어있어야 하는것 같다.

faces (일부)

...
4
(
2(0 1)
2(1 2)
2(2 3)
2(3 0)
)

위는 페이스의 정의이다. "(...)"의 위가 페이스 수, "(...)" 내의 각행이 페이스 절점수와 절점번호리스트이다.

neighbour (일부)

...
(
)

위는 내부경계가 접하는 옆 셀의 정보이다. 이번에는 1개 셀만 가지고 있으므로 아무것도 적혀이지 않다.

owner (일부)

...
4
(
0
0
0
0
)

페이스를 소유하는 셀의 정보이다. neighbour, owner에서 페이스는 2개의 셀과 접해있는 상황에 대해 2개 셀이 페이스에 대해 서로 소유자이면서 접하는 셀이 되는것이 아닌, 어느 한 쪽이 소유자이고 어느한쪽이 접하는 셀로 구성하게 된다.

points (일부)

...

4
(
(0 0 0)
(1 0 0)
(1 1 0)
(0 1 0)
)

절점에 대한 정보이다.



  프로그램 


자 이번엔 프로그램에 대한 설명이다.

mesh.C (일부)

#include "fvCFD.H"
#include "IOmanip.H"
	
	...
	
	Info << "default region: " << fvMesh::defaultRegion << endl;
	Info << "mesh sub dir: " << fvMesh::meshSubDir << endl;

	fvMesh mesh(
		IOobject(
			fvMesh::defaultRegion,
			runTime.timeName(), runTime,
			IOobject::MUST_READ
		)
	);

	Info << "mesh dir: " << mesh.meshDir() << endl;

	const pointField &p = mesh.points();

	Info << "num points: " << p.size() << endl;

	for(int i = 0; i < p.size(); i++){
		Info << "(";
		Info << setf(ios_base::scientific)
		  << setw(15) << setprecision(3)
		  << p[i][0];
		Info << ", ";
		Info << setf(ios_base::scientific)
		  << setw(15) << setprecision(3)
		  << p[i][1];
		Info << ", ";
		Info << setf(ios_base::scientific)
		  << setw(15) << setprecision(3)
		  << p[i][2];
		Info << ")" << endl;
	}

	const faceList &f = mesh.faces();

	Info << "num faces: " << f.size() << endl;

	forAll(f, i){
		Info << "(";
		Info << setw(3) << f[i][0];
		Info << setw(3) << f[i][1];
		Info << ")" << endl;
	}

	const labelList &fo = mesh.faceOwner();

	Info << "num face owner: " << fo.size() << endl;

	forAll(fo, i){
		Info << setw(3) << fo[i] << endl;
	}

	const labelList &fn = mesh.faceNeighbour();

	Info << "num face neighbour: " << fn.size() << endl;

	forAll(fn, i){
		Info << setw(3) << fn[i] << endl;
	}

	const polyBoundaryMesh &bm = mesh.boundaryMesh();

	Info << "boundary mesh: " << bm.size() << endl;

	forAll(bm, i){
		const polyPatch &patch = bm[i];
		Info << "(";
		Info << patch.name() << ", ";
		Info << patch.type() << ", ";
		Info << patch.physicalType();
		Info << ")" << endl;
	}
	...


fvMesh의 상세한 정의를 확인해보자. 해당하는 소스코드 fvMesh.H는 src의 하위에서 직접 찾아보도록 하자(Eclipse에 포팅하였따면 "Search"를 사용하면 편리하다).


fvMesh 오브젝트의 정의는, createMesh.H (src/openFOAM/include/createMesh.H)를 참고하도록 하자.


절점이나 페이스 등의 정보를 참조를 얻어 각각을 표시하고 있다. 절점표시에서는 for문, 그 외에서는 forAll문을 사용하고 있으나 어느쪽돈 같다. forAll은 OpenFOAM에서 이미 정의되어있는 문법이다.

forAll(p, i){
  ...
}


for(int i = 0; i < p.size(); i++){
  ...
}


으로 적은것과 동일하다.


처음에 인클루드한 IOmanip.H는 C++ 표준입출력스트림용의 입출력방식과 같은 것을 Info 명령어에 사용하고 있기 때문이다. setw()를 사용하기때문에 인클루드되어있다.



 컴파일


소스디렉토리내에서(Make내부가 아니다!), wmake를 실행시킨다.

$ wmake
$ ./mesh







  추가정보

 

기존의 프로그램을 약간 수정해보자(04-mesh2.tar.gz). 변경한 부분은 아래와 같다.

mesh.C (일부)


	...
	Info << "mesh dir: " << mesh.meshDir() << endl;


	// move point
	pointField pnew(mesh.points());
	pnew[0][0] = 0.01;
	mesh.movePoints(pnew);


	const pointField &p = mesh.points();
	
	...
	
	mesh.write();

	return 0;
}


절점정보에서부터  pointField 오브젝트를 만들어 절점위치를 변경하고(0번의 절점의 x좌표를 0.01으로 설정), movePoints()로 해당 변화를 격자에 적용시키고 있다. 실행경과는 paraFoam을 통해 볼수 있듯이, 절점의 위치가 변경되어 있다.


OpenFOAM 소스코드 파해치기 목차로 이동