更新一下,偶然看到的,针对物理场特定网格内的值处理:
cellSet selectedCells(mesh, cellSetName);
labelList cells = selectedCells.toc();
forAll(cells, i)
{
p[i] = 0.0
}
其中cellSetName
是用topoSet
命令提取的区域名字。
更新一下,偶然看到的,针对物理场特定网格内的值处理:
cellSet selectedCells(mesh, cellSetName);
labelList cells = selectedCells.toc();
forAll(cells, i)
{
p[i] = 0.0
}
其中cellSetName
是用topoSet
命令提取的区域名字。
@Cr 这里面如果cellZone
区域和整体mesh
区域的cell编号不一致的的话,就得想别的办法来处理了。
@王金成
topoSet
命令可以可以提取计算域内的指定区域,执行命令后在constant/polyMesh
会生成cellZoned
的字典文件。
在求解器的主函数中用下面的语句,可以针对这个区域遍历物理场:
const cellZone& certainZone = mesh.lookupObject<cellZone>("certainZone");
forAll(certainZone.zoneMesh(), celli)
{
p[celli] = 0.0; //将压力场的certainZone区域置0
}
这只是我的想法,并且编译通过了,但我没有实际应用过。
在createFields.H
中声明一个多项式:
scalar a[8] = {k0, 1e-20, 0, 0, 0, 0, 0, 0};
Polynomial<8> timeVaryingValue(a);
在while
计算循环中的时间步进后更新该场:
permeability =timeVaryingValue.value(runTime.timeOutputValue());
@King_RVM dev(symm(tgradU()()))
改为 dev(symm(tgradU()))
,同时将sij
的类型声明为tmp<volSymmTensorField>
。
原因:tgradU()
为tmp<T>
的operator()
重载返回T
类型的引用,在这里为GeometricField
类型,GeometricField
的operator()
的重载返回GeometricField::Internal
类型,即dimensionedField<Type, GeoMesh>
,所以类型不匹配,场运算报错。
@King_RVM 这个编译错误是OpenFOAM本身源码上的bug,需要对DimensionField的源代码进行改动才可以使编译通过。OpenFOAM-v2006 bug Issues #1868
@King_RVM 这个错误还是类型不统一,sij是tmp<volTensorField>
类型, I1是一个volTensorField::Internal
或DimensionedField<tensor, volMesh>
类型,OpenFOAM没有定义两种类型的减法,我建议你将所有的vol##Type##Field::Internal
都换成vol##Type##Field
试试。
@King_RVM 对了还有,你上面的场变量都是用拷贝构造的方式生成的,他们应该都是有量纲的。例如S
的量纲来自于tgradU
。V1
的量纲来自于sij
来自于S
或divU
@King_RVM Foam::T()
是用来求张量场转置的全局函数。如果你的代码没有直接的调用该函数类似V1.T(),那就是在场运算的过程中间接调用了该函数。我试了一圈下来,下面是编译的情况
tensor I(1, 0, 0, 0, 1, 0, 0, 0, 1);
volScalarField::Internal divU(fvc::div(fvc::absolute(phi, U))()());
volTensorField::Internal sij(-0.33*I*divU);
volTensorField ss(fvc::grad(U));
DimensionedField<tensor, volMesh> y(sij);
DimensionedField<tensor, volMesh> yCopy(sij);
Foam::T(yCopy,y); //OK
//y.T(); //compiled Error, no matching function
ss.T(); //OK
//sij.T(); //compiled Error, no matching function
volTensorField::Internal
的类型实际就是DimensionedField<tensor, volMesh>
,不知道为什么他的成员函数T()编译无法通过(目前我没找到原因)。但volTensorField
的成员函数T()可以编译通过。
所以我建议你将你所有的场变量都声明称volTensorField
类型
@King_RVM 你好,我试了一下,由于divU
是一个volScalarField::Internal
类型,运算S-(1.0/3.0)*divU*(1.0)/omega_
返回的也是volScalarField::Internal
类型。
你将sij声明成volTensorField::Internal
类型,编译一下试试。
这个求解器是不可压缩的求解器,他单独求解温度方程,没有用用到热物理模型库,所以就不支持这个边界条件,fluidThermo是热物理模型库的方法。
你可以去看看buoyantPimpleFoam或buoyantSimpleFoam下面的算例,这些算例的constant文件夹下都有thermophysicalProperties这个字典,这些求解器也都用到了热物理模型库求解焓方程,并且支持这个边界条件。
报错信息显示waveAbsorptionVelocity3D这个边界条件在更新边界值时Foam::correctUphiBCs()
这个函数中出现了除0的操作,你可以尝试在主函数中用gMin(边界场)
把这个边界上的最小值输出看一看。
其他方面,这个求解器和算例及边界条件,我都不大懂。
或许可以将代码改为用不可压缩求解器求解的边界上的温度和导热率来获得,边界上的传热量。例如:
if(db().foundObject<volScalarField>("T"))
{
const volScalarField& T = db().lookupObject<volScalarField>("T");
const fvPatchScalarField& Tp = T.boundaryField()[patchi];
qDot = kappa*Tp.snGrad();
}
其中kappa
需要根据你的物性和边界上的温度场来计算获得
fvOptions是一个fv::options类型的一个对象,fv::options类继承自optionList类。
optionList类中含有一个包含所有源项的指针列表PtrList<option> 。optionList类中对operator()进行了运算符重载,函数体中遍历调用PtrList<option>中的每一个addSup函数。
相关函数体的定义在fvOptionListTemplates.C
中。
template<class Type>
Foam::tmp<Foam::fvMatrix<Type>> Foam::fv::optionList::operator()
(
GeometricField<Type, fvPatchField, volMesh>& field,
const word& fieldName
)
{
return source(field, fieldName, field.dimensions()/dimTime*dimVolume);
}
template<class Type>
Foam::tmp<Foam::fvMatrix<Type>> Foam::fv::optionList::source
(
GeometricField<Type, fvPatchField, volMesh>& field,
const word& fieldName,
const dimensionSet& ds
)
{
checkApplied();
tmp<fvMatrix<Type>> tmtx(new fvMatrix<Type>(field, ds));
fvMatrix<Type>& mtx = tmtx.ref();
forAll(*this, i)
{
option& source = this->operator[](i);
label fieldi = source.applyToField(fieldName);
if (fieldi != -1)
{
source.setApplied(fieldi);
if (source.isActive())
{
if (debug)
{
Info<< "Applying source " << source.name() << " to field "
<< fieldName << endl;
}
source.addSup(mtx, fieldi);
}
}
}
return tmtx;
}