본문 바로가기

OpenFOAM/소스코드 파해치기

[OpenFOAM 소스코드 파해치기] 경계조건

일본어 원문링크


작성일 : 2012년  9월  17일

번역일 : 2016년  4월   4일


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


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

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

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

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

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

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



 

  들어가기 


경계조건 (Boundary Condition)에 대해 알아보자



  사용 버전


OpenFOAM 2.1.1



  경계조건의 종류  


방정식의 경계조건은 주로 2종류로 구분할 수 있다.


  • Dirichlet boundary condiiton : 값을 지정
  • Neumann boundary condition : 구배를 지정

OpenFOAM의 경계조건 클래셍는, 기본경계조건과, 그것들로부터 도출되는(derived) 경계조건이 있다.


기본 경계조건


  • fixedValue : 값을 지정한다 (Dirichlet boundary condition)
  • fixedGradient : 구배를 지정한다 (Neumann boundary condition)
  • mixed : Dirichlet boundry condition과 Neumann boundary condition 의 혼합
  • zeroGradient : 구배 0
  • calculated : 값을 별도의 필드에서 계산



  도출되는 경계조건 (Derived boundary condition)


도출되는 경계조건 클래스는, 기본경계조건클래스를 계승하여 작성된다. 몇종류의 코드를 살펴보도록 하자.

코드는 $FOAM_SRC/finiteVolume/fields/fvPatchField/derived 에 있다.


기본 경계조건

buoyantPressure 는 interFoam 에 사용된다.
buoyangPressureFvPatchScalarField.H

class buoyantPressureFvPatchScalarField

:

public fixedGradientFvPatchScalarField


buoyantPressure 는 fixedGradient 를 기반으로 한다.

buoyantPressureFvPatchScalarField.C

void Foam::buoyantPressureFvPatchScalarField::updateCoeffs() { if (updated()) { return; } const uniformDimensionedVectorField& g = db().lookupObject<uniformDimensionedVectorField>("g"); const fvPatchField<scalar>& rho = patch().lookupPatchField<volScalarField, scalar>(rhoName_); // If the variable name is "p_rgh", "ph_rgh" or "pd" // assume it is p? - rho*g.h and set the gradient appropriately. // Otherwise assume the variable is the static pressure. if ( dimensionedInternalField().name() == "p_rgh" || dimensionedInternalField().name() == "ph_rgh" || dimensionedInternalField().name() == "pd" ) { gradient() = -rho.snGrad()*(g.value() & patch().Cf()); } else { gradient() = rho*(g.value() & patch().nf()); } fixedGradientFvPatchScalarField::updateCoeffs(); }


압력의 변수명을 통해 거동을 바꾸고 있는 것을 알 수 있다. "gradien() = ..."으로 구배를 지정하고 있다. 여기서 ρgh 의 구배를 주고 있다.


flowRateInletVelocity

flowRateInletVelocity는 지정한 유량으로 속도를 계산한다.
flowRateInletVelocityFvPatchVectorField.H

class flowRateInletVelocityFvPatchVectorField

:

public fixedValueFvPatchVectorField


fixedVlue 가 기반이 되어있다.

void Foam::flowRateInletVelocityFvPatchVectorField::updateCoeffs() { if (updated()) { return; } const scalar t = db().time().timeOutputValue(); // a simpler way of doing this would be nice const scalar avgU = -flowRate_->value(t)/gSum(patch().magSf()); tmp<vectorField> n = patch().nf(); const surfaceScalarField& phi = db().lookupObject<surfaceScalarField>(phiName_); if (phi.dimensions() == dimVelocity*dimArea) { // volumetric flow-rate operator==(n*avgU); } else if (phi.dimensions() == dimDensity*dimVelocity*dimArea) { if (rhoName_ == "none") { // volumetric flow-rate operator==(n*avgU); } else { // mass flow-rate const fvPatchField<scalar>& rhop = patch().lookupPatchField<volScalarField, scalar>(rhoName_); operator==(n*avgU/rhop); } } else { ... } fixedValueFvPatchField::updateCoeffs(); }


유체플럭스(flux) phi 의 단위로부터 체적유량인지 질량유량인지를 판단하고 있다. operator==() 으로 값을 지정하고 있다.


inletOutlet

inletOutlet 이 유입유출조건이다.
inletOutletFvPatchField.H

template<class Type>

class inletOutletFvPatchField

:

public mixedFvPatchField<Type>


mixed 가 기반이 된다.

inletOutletFvPatchField.C

template<class Type> Foam::inletOutletFvPatchField<Type>::inletOutletFvPatchField ( const fvPatch& p, const DimensionedField<Type, volMesh>& iF, const dictionary& dict ) : mixedFvPatchField<Type>(p, iF), phiName_(dict.lookupOrDefault<word>("phi", "phi")) { this->refValue() = Field<Type>("inletValue", dict, p.size()); if (dict.found("value")) { fvPatchField<Type>::operator= ( Field<Type>("value", dict, p.size()) ); } else { fvPatchField<Type>::operator=(this->refValue()); } this->refGrad() = pTraits<Type>::zero; this->valueFraction() = 0.0; } ... template<class Type> void Foam::inletOutletFvPatchField<Type>::updateCoeffs() { if (this->updated()) { return; } const Field<scalar>& phip = this->patch().template lookupPatchField<surfaceScalarField, scalar> ( phiName_ ); this->valueFraction() = 1.0 - pos(phip); mixedFvPatchField<Type>::updateCoeffs(); }


mixed 에서는 값지정과 구배지정을 혼합하고 있다. "this->refValue()" 로 값지정, "this->refGrad() =" 으로 구배지정을 수행하고 있다. "this->valueFraction() = "은 혼합정도를 지정하며, 0에서 1까지의 범위의 값을 가진다. 0으로 Neumann boundary condition(구배지정), 1 으로 Dirichlet boundary condition(값지정) 이 된다.

아래와 같이 되어있다.

this->valueFraction() = 1.0 - pos(phip);


pos() 는 부호를 찾아내는 함수로, 양수이면 1, 음수이면 0이 된다. phip 가 양수이면 valueFraction() 가 0, phip 가 음수부터 1 이 된다. 유체 플럭스 phip 는 유체가 흘러나올때 양수, 들어갈때가 음수이므로, 여기서 유체가 밖으로 나가면 Neumann boundary condition, 들어가면 dirichlet boundary condition 이 된다. 스칼라변수의 경계조건으로 유입일때는 값지정, 유출일때는 구배 0을 지정하므로, inletOutlet 는 유입,유출 어느쪽에도 대응하도록 유체 흘럭스의 방향에 의해 처리를 바꾸고 있다.


outletInlet

outletInlet 는 inletOutlet 과 같이 유입유출조건이다.
outletInletFvPatchField.H

template<class Type>

class outletInletFvPatchField

:

public mixedFvPatchField<Type>


outletInletFvPatchField.C

template<class Type> Foam::outletInletFvPatchField<Type>::outletInletFvPatchField ( const fvPatch& p, const DimensionedField<Type, volMesh>& iF, const dictionary& dict ) : mixedFvPatchField<Type>(p, iF), phiName_(dict.lookupOrDefault<word>("phi", "phi")) { this->refValue() = Field<Type>("outletValue", dict, p.size()); if (dict.found("value")) { fvPatchField<Type>::operator= ( Field<Type>("value", dict, p.size()) ); } else { fvPatchField<Type>::operator=(this->refValue()); } this->refGrad() = pTraits<Type>::zero; this->valueFraction() = 0.0; } ,.. template<class Type> void Foam::outletInletFvPatchField<Type>::updateCoeffs() { if (this->updated()) { return; } const fvsPatchField<scalar>& phip = this->patch().template lookupPatchField<surfaceScalarField, scalar> ( phiName_ ); this->valueFraction() = pos(phip); mixedFvPatchField<Type>::updateCoeffs(); }


outletInlet 은 inletOutlet 과 닮아있으나 Neumann 조건, Dirichlet 조건의 변환이 반대로 되어있다. 즉, 유입일때는 구배가 0, 유출일때는 값지정을 수행한다.


 


   경계조건의 커스터마이징


자신의 문제에 맞게 경계조건을 커스터마이징하고 싶을 경우, 아래와 같이 한다.

1. 사용하는 솔버의 코드를 복사한다.

2. 만들고 싶은 경계조건에 가까운 경계조건을 $FOAM_SRC/finiteVolume/fields/fvPatchFields/derived 에서 폴더를 복사한다.

3. 솔버의 Make/files 에 복사한 경계조건의 .C 파일을 경로에 추가한다. 참고로 솔버의 바이너리 경로 (EXE = ...)를 원래의 것과 같게 변경해 둔다.

4. 이 시점에서 문제가 없는지 wmake 를 실행해 본다.

5. 경계조건 파일을 커스터마이징 한다.