Reputation: 33
I'm editing the source code for a Computational Fluid Dynamics program and although I'm new to C++ I cannot seem to work out where the errors are coming from. They are as follows:
Make/linux64GccDPOpt/mySTCompressibleInterFoam.o: In function `main':
mySTCompressibleInterFoam.C:(.text.startup+0x333c): undefined reference to `Foam::surfaceTension::surfaceTension(Foam::GeometricField, Foam::fvPatchField, Foam::volMesh> const&, Foam::GeometricField const&)'
mySTCompressibleInterFoam.C:(.text.startup+0x3580): undefined reference to `Foam::surfaceTension::surfaceTensionForce() const'
mySTCompressibleInterFoam.C:(.text.startup+0x3cff): undefined reference to `vtable for Foam::surfaceTension'
mySTCompressibleInterFoam.C:(.text.startup+0x8246): undefined reference to `vtable for Foam::surfaceTension'
The code structure is quite complex however I'm fairly sure that I've found the lines of code that are causing the problem but I have no idea how to fix it.
The top level file is thus:
#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;
}
// ************************************************************************* //
From the errors my understanding is that the errors are coming from the surfaceTension class and functions.
surfaceTension.H is as follows:
#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 is then
#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;
}
}
In order to calculate the surface tension at each time step the surfaceTensionForce function is called in the file UEqn.H which is as follows:
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);
}
If I remove the first line of this file the undefined referance erros do not appear and the code compiles fine. I've looked at a number of similar problems and the most common solution was that the files weren’t linked properly, I'm certain this is not the case.
Thank you in advance.
Upvotes: 3
Views: 2567
Reputation: 24508
This is pretty much the most common linker error there is. The reason as to why the error disappears when you remove the first line of your last file, is probably because that will cause a compiler error (symbol not declared), and the linker won't even run.
I can only guess, but it seems like surfaceTension
belongs to a different binary and is not properly linked when you are compiling UEqn.h
.
I am also guessing that you are trying to run an example application of OpenFOAM. Make sure, you took all the installation steps, laid out on their wiki.
Upvotes: 1