若干个 "undefined reference to" 错误

3
我正在编辑一款计算流体力学程序的源代码,虽然我对C++不是很熟悉,但我似乎无法确定错误来自哪里。以下是错误信息:
Make/linux64GccDPOpt/mySTCompressibleInterFoam.o: 在函数 `main' 中: mySTCompressibleInterFoam.C:(.text.startup+0x333c): 对 `Foam::surfaceTension::surfaceTension(Foam::GeometricField, Foam::fvPatchField, Foam::volMesh> const&, Foam::GeometricField const&)' 未定义的引用 mySTCompressibleInterFoam.C:(.text.startup+0x3580): 对 `Foam::surfaceTension::surfaceTensionForce() const' 未定义的引用 mySTCompressibleInterFoam.C:(.text.startup+0x3cff): 对 `Foam::surfaceTension' 的虚表未定义的引用 mySTCompressibleInterFoam.C:(.text.startup+0x8246): 对 `Foam::surfaceTension' 的虚表未定义的引用
代码结构相当复杂,但我相当确定已经找到了引起问题的代码行,但我不知道如何解决它。
顶层文件如下:
  #include "fvCFD.H"
  #include "MULES.H"
  #include "subCycle.H"
  #include "rhoThermo.H"
  #include "interfaceProperties.H"
  #include "twoPhaseMixture.H"
  #include "twoPhaseMixtureThermo.H"
  #include "surfaceTension.H"
  #include "turbulenceModel.H"
  #include "pimpleControl.H"

  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
#include "readGravitationalAcceleration.H"

pimpleControl pimple(mesh);

#include "readControls.H"
#include "initContinuityErrs.H"
#include "createFields.H"
#include "CourantNo.H"
#include "setInitialDeltaT.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

Info<< "\nStarting time loop\n" << endl;

while (runTime.run())
{
    #include "readControls.H"
    #include "CourantNo.H"
    #include "alphaCourantNo.H"
    #include "setDeltaT.H"

    runTime++;

    Info<< "Time = " << runTime.timeName() << nl << endl;

    // --- Pressure-velocity PIMPLE corrector loop
    while (pimple.loop())
    {
        #include "alphaEqnsSubCycle.H"

        // correct interface on first PIMPLE corrector
        if (pimple.corr() == 1)
        {
            interface.correct();
        }

        solve(fvm::ddt(rho) + fvc::div(rhoPhi));

        #include "UEqn.H"
        #include "TEqn.H"

        // --- Pressure corrector loop
        while (pimple.correct())
        {
            #include "pEqn.H"
        }

        if (pimple.turbCorr())
        {
            turbulence->correct();
        }
    }

    runTime.write();

    Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
        << "  ClockTime = " << runTime.elapsedClockTime() << " s"
        << nl << endl;
}

Info<< "End\n" << endl;

return 0;
}


// ************************************************************************* //

根据错误信息,我的理解是错误来自于surfaceTension类和函数。

surfaceTension.H 如下:

#ifndef surfaceTension_H
#define surfaceTension_H

#include "incompressible/transportModel/transportModel.H"
#include "phase.H"
#include "PtrDictionary.H"
#include "volFields.H"
#include "surfaceFields.H"


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

/*---------------------------------------------------------------------------*\
                  Class surfaceTension Declaration
\*---------------------------------------------------------------------------*/

class surfaceTension
:
public transportModel
{
public:

class interfacePair
:
    public Pair<word>
{
public:

    class hash
    :
        public Hash<interfacePair>
    {
    public:

        hash()
        {}

        label operator()(const interfacePair& key) const
        {
            return word::hash()(key.first()) + word::hash()(key.second());
        }
    };


    // Constructors

        interfacePair()
        {}

        interfacePair(const word& alpha1Name, const word& alpha2Name)
        :
            Pair<word>(alpha1Name, alpha2Name)
        {}

        interfacePair(const phase& alpha1, const phase& alpha2)
        :
            Pair<word>(alpha1.name(), alpha2.name())
        {}


    // Friend Operators

        friend bool operator==
        (
            const interfacePair& a,
            const interfacePair& b
        )
        {
            return
            (
                ((a.first() == b.first()) && (a.second() == b.second()))
             || ((a.first() == b.second()) && (a.second() == b.first()))
            );
        }

        friend bool operator!=
        (
            const interfacePair& a,
            const interfacePair& b
        )
        {
            return (!(a == b));
        }
};


private:

// Private data

    //- Dictionary of phases
    PtrDictionary<phase> phases_;

    const fvMesh& mesh_;
    const volVectorField& U_;
    const surfaceScalarField& phi_;

    surfaceScalarField rhoPhi_;

    volScalarField alphas_;

    typedef HashTable<scalar, interfacePair, interfacePair::hash>
        sigmaTable;

    sigmaTable sigmas_;
    dimensionSet dimSigma_;

    //- Stabilisation for normalisation of the interface normal
    const dimensionedScalar deltaN_;

    //- Conversion factor for degrees into radians
    static const scalar convertToRad;


// Private member functions

    tmp<surfaceVectorField> nHatfv
    (
        const volScalarField& alpha1,
        const volScalarField& alpha2
    ) const;

    tmp<surfaceScalarField> nHatf
    (
        const volScalarField& alpha1,
        const volScalarField& alpha2
    ) const;

    void correctContactAngle
    (
        const phase& alpha1,
        const phase& alpha2,
        surfaceVectorField::GeometricBoundaryField& nHatb
    ) const;

    tmp<volScalarField> nabla
    (
        const phase& alpha1,
        const phase& alpha2
    ) const;


 public:

// Constructors

    //- Construct from components
    surfaceTension
    (
        const volVectorField& U,
        const surfaceScalarField& phi
    );


//- Destructor
virtual ~surfaceTension()
{}    


// Member Functions

    //- Return the phases
    const PtrDictionary<phase>& phases() const
    {
        return phases_;
    }

    //- Return the velocity
    const volVectorField& U() const
    {
        return U_;
    }

    //- Return the volumetric flux
    const surfaceScalarField& phi() const
    {
        return phi_;
    }

    const surfaceScalarField& rhoPhi() const
    {
        return rhoPhi_;
    }

    //- Return the mixture density
    tmp<volScalarField> rho() const;

    //- Return the dynamic laminar viscosity
    tmp<volScalarField> mu() const;

    //- Return the kinematic laminar viscosity
    tmp<volScalarField> nu() const;

    //- Return surface Tension Force

    tmp<surfaceScalarField> surfaceTensionForce() const;

    //- Correct the mixture properties
    void correct();

    //- Read base transportProperties dictionary
    bool read();

};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //

接下来是SurfaceTension.c文件

#include "surfaceTension.H"
#include "alphaContactAngleFvPatchScalarField.H"
#include "Time.H"
#include "subCycle.H"
#include "MULES.H"
#include "fvcSnGrad.H"
#include "fvcFlux.H"

// * * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * //

const Foam::scalar Foam::surfaceTension::convertToRad =
Foam::constant::mathematical::pi/180.0;

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::surfaceTension::surfaceTension
(
const volVectorField& U,
const surfaceScalarField& phi
)
:
transportModel(U, phi),
phases_(lookup("phases"), phase::iNew(U, phi)),

mesh_(U.mesh()),
U_(U),
phi_(phi),

rhoPhi_
(
    IOobject
    (
        "rho*phi",
        mesh_.time().timeName(),
        mesh_,
        IOobject::NO_READ,
        IOobject::NO_WRITE
    ),
    mesh_,
    dimensionedScalar("rho*phi", dimMass/dimTime, 0.0)
),

alphas_
(
    IOobject
    (
        "alphas",
        mesh_.time().timeName(),
        mesh_,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE
    ),
    mesh_,
    dimensionedScalar("alphas", dimless, 0.0),
    zeroGradientFvPatchScalarField::typeName
),

sigmas_(lookup("sigmas")),
dimSigma_(1, 0, -2, 0, 0),
deltaN_
(
    "deltaN",
    1e-8/pow(average(mesh_.V()), 1.0/3.0)
)

{
}

// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //

Foam::tmp<Foam::volScalarField> Foam::surfaceTension::nu() const
{
return mu()/rho();
}

Foam::tmp<Foam::surfaceScalarField>
Foam::surfaceTension::surfaceTensionForce() const
{
tmp<surfaceScalarField> tstf
(
    new surfaceScalarField
    (
        IOobject
        (
            "surfaceTensionForce",
            mesh_.time().timeName(),
            mesh_
        ),
        mesh_,
        dimensionedScalar
        (
            "surfaceTensionForce",
            dimensionSet(1, -2, -2, 0, 0),
            0.0
        )
    )
);

surfaceScalarField& stf = tstf();

forAllConstIter(PtrDictionary<phase>, phases_, iter1)
{
    const phase& alpha1 = iter1();

    PtrDictionary<phase>::const_iterator iter2 = iter1;
    ++iter2;

    for (; iter2 != phases_.end(); ++iter2)
    {
        const phase& alpha2 = iter2();

        sigmaTable::const_iterator sigma =
            sigmas_.find(interfacePair(alpha1, alpha2));

        if (sigma == sigmas_.end())
        {
            FatalErrorIn("surfaceTension::surfaceTensionForce() const")
                << "Cannot find interface " << interfacePair(alpha1, alpha2)
                << " in list of sigma values"
                << exit(FatalError);
        }

        stf += dimensionedScalar("sigma", dimSigma_, sigma())
           *fvc::interpolate(nabla(alpha1, alpha2))*
            (
                fvc::interpolate(alpha2)*fvc::snGrad(alpha1)
              - fvc::interpolate(alpha1)*fvc::snGrad(alpha2)
            );
    }
}

return tstf;
}

void Foam::surfaceTension::correct()
{}

Foam::tmp<Foam::surfaceVectorField> Foam::surfaceTension::nHatfv
(
const volScalarField& alpha1,
const volScalarField& alpha2
) const
{

surfaceVectorField gradAlphaf
(
    fvc::interpolate(alpha2)*fvc::interpolate(fvc::grad(alpha1))
  - fvc::interpolate(alpha1)*fvc::interpolate(fvc::grad(alpha2))
);

// Face unit interface normal
return gradAlphaf/(mag(gradAlphaf) + deltaN_);
}

Foam::tmp<Foam::surfaceScalarField> Foam::surfaceTension::nHatf
(
const volScalarField& alpha1,
const volScalarField& alpha2
) const
{
// Face unit interface normal flux
return nHatfv(alpha1, alpha2) & mesh_.Sf();
}

Foam::tmp<Foam::volScalarField> Foam::surfaceTension::nabla
(
const phase& alpha1,
const phase& alpha2
) const
{
tmp<surfaceVectorField> tnHatfv = nHatfv(alpha1, alpha2);

correctContactAngle(alpha1, alpha2, tnHatfv().boundaryField());

    // Simple expression for curvature
return -fvc::div(tnHatfv & mesh_.Sf());
}

bool Foam::surfaceTension::read()
{
if (transportModel::read())
{
    bool readOK = true;

    PtrList<entry> phaseData(lookup("phases"));
    label phasei = 0;

    forAllIter(PtrDictionary<phase>, phases_, iter)
    {
        readOK &= iter().read(phaseData[phasei++].dict());
    }

    lookup("sigmas") >> sigmas_;

    return readOK;
}
else
{
    return false;
}
}

为了在每个时间步骤计算表面张力,需要在UEqn.H文件中调用surfaceTensionForce函数,其代码如下:
surfaceTension mixture(U, phi);

fvVectorMatrix UEqn
(
    fvm::ddt(rho, U)
  + fvm::div(rhoPhi, U)
  + turbulence->divDevRhoReff(U)
);

UEqn.relax();

if (pimple.momentumPredictor())
{
    solve
    (
        UEqn
     ==
        fvc::reconstruct
        (
            (
                mixture.surfaceTensionForce()
              - ghf*fvc::snGrad(rho)
              - fvc::snGrad(p_rgh)
            ) * mesh.magSf()
        )
    );

//        K = 0.5*magSqr(U);
}

如果我删除这个文件的第一行,未定义引用错误就不会出现,代码可以编译成功。我看过很多类似的问题,最常见的解决方案是文件链接不正确,但我确信这不是问题所在。
提前感谢您的帮助。

1
当您创建surfaceTension对象时,是否忘记了命名空间? - Nik
展示你的最小自包含可执行示例。这段代码太长了,难以调试。 - Lightness Races in Orbit
哇,这些包简直要了我的命。你为什么要做这样的事情? - zoska
感谢您的评论,@Nik如果我理解正确,那么命名空间前缀为“Foam :: surfaceTension :: surfaceTension”的对象。 - jd210
@Lightness Races in Orbit,我会精简代码并编辑我的帖子。 - jd210
@zoska 我正在攻读博士学位,所以我正在模拟一些从未被模拟过的东西,这些仅仅是表面的探索! - jd210
1个回答

1
这基本上是最常见的链接错误。当您删除最后一个文件的第一行时,错误消失的原因可能是因为这会导致编译器错误(符号未声明),并且链接器甚至不会运行。
我只能猜测,但似乎surfaceTension属于不同的二进制文件,并且在编译UEqn.h时没有正确链接。
我还猜测你正在尝试运行OpenFOAM的示例应用程序。请确保按照其维基上列出的所有安装步骤进行操作

是的,我怀疑你是对的。最初,surfaceTension析构函数也出现了相同的错误,但是通过正确定义它来解决了这个问题(在快速搜索后,我发现这是一个常见错误),因此似乎它已经正确链接,因为我所做的更改影响了错误。我将尝试一种不同的链接方式,看看是否有效。是的,我确实在使用OpenFOAM。 - jd210
这是官方的还是外部的OpenFOAM示例应用程序? - Domi
它是外部的,但所有存在的代码都是官方代码。基本上,目前我正在将一个应用程序的一部分添加到另一个应用程序中。 - jd210
好的,那么你的问题就在这里:你不能只是复制代码并希望它能够工作。你还必须更新编译和链接选项。这是因为OpenFOAM由多个库组成,并不是所有OpenFOAM应用程序都使用所有库。我不确定OpenFOAM在Linux上是如何工作的,但我猜每个示例应用程序都有某种Makefile,它定义了它所使用的所有外部库。确保更改后的应用程序也链接到它需要的库(可能是通过从你正在复制代码的程序中复制它们)。 - Domi
是的,我认为这可能是问题所在,因为我正在创建一个新的共享库,我添加的链接器并不完全正确,我做了一些可能不太好的实践,但似乎可以工作。我把我的新共享库从我的主目录(建议放置位置)移动到根拥有的 OpenFOAM 安装目录。现在我有不同的“未定义引用”错误,但我将去调查它们。 - jd210

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接