Skip to content

Reply To: Issue with Implementing New Features in .h and .hh Files

OpenLB – Open Source Lattice Boltzmann Code Forums on OpenLB General Topics Issue with Implementing New Features in .h and .hh Files Reply To: Issue with Implementing New Features in .h and .hh Files

#9823

Hi Adrian
Thanks alot for replying
I’m working on modifying the Free Energy Wall Boundary implementation, and I want to introduce an indicator to distinguish between three different boundary condition models. My idea is to add an integer or an enumeration to specify which model is being used and then apply the corresponding boundary condition logic accordingly.

Here is the Error

rm -f tmp/*.* tmp/vtkData/*.* tmp/vtkData/data/*.* tmp/imageData/*.* tmp/imageData/data/*.* tmp/gnuplotData/*.* tmp/gnuplotData/data/*.*
rm -f contactAngle3d.o contactAngle3d.d contactAngle3d
make -C ../../../external
make[1]: Entering directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external’
make -C zlib
make[2]: Entering directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external/zlib’
make[2]: Nothing to be done for ‘all’.
make[2]: Leaving directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external/zlib’
cp zlib/build/libz.a lib/
make -C tinyxml
make[2]: Entering directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external/tinyxml’
make[2]: Nothing to be done for ‘all’.
make[2]: Leaving directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external/tinyxml’
cp tinyxml/build/libtinyxml.a lib/
make[1]: Leaving directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0/external’
make -C ../../.. core
make[1]: Entering directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0’
make[1]: Nothing to be done for ‘core’.
make[1]: Leaving directory ‘/local/mmp22squ/Downloads/olb-1.7r0/olb-1.7r0′
g++ -O3 -Wall -march=native -mtune=native -std=c++17 -pthread -DPLATFORM_CPU_SISD -DDEFAULT_FLOATING_POINT_TYPE=double -I../../../src -I../../../external/zlib -I../../../external/tinyxml -c -o contactAngle3d.o contactAngle3d.cpp
In file included from ../../../src/dynamics/dynamics3D.h:35,
from ../../../src/olb3D.h:5,
from contactAngle3d.cpp:36:
../../../src/dynamics/freeEnergyCoupling3D.h: In instantiation of ‘void olb::ChemicalPotentialCoupling3D::apply(CELLS&, PARAMETERS&) [with CELLS = olb::utilities::TypeIndexedTuple<olb::meta::plain_map<olb::meta::list<olb::names::A, olb::names::B>, olb::meta::list<olb::cpu::Cell<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE>, olb::Platform::CPU_SISD>, olb::cpu::Cell<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE>, olb::Platform::CPU_SISD> > > >; PARAMETERS = olb::ParametersD<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE>, olb::ChemicalPotentialCoupling3D::ALPHA, olb::ChemicalPotentialCoupling3D::KAPPA1, olb::ChemicalPotentialCoupling3D::KAPPA2, olb::ChemicalPotentialCoupling3D::KAPPA3>]’:
../../../src/core/superLatticeCoupling.h:158:5: required from ‘void olb::ConcreteBlockCouplingO<COUPLEES, PLATFORM, COUPLER, olb::OperatorScope::PerCellWithParameters>::execute(typename olb::AbstractCouplingO<COUPLEES>::LatticeR) [with COUPLER = olb::ChemicalPotentialCoupling3D; COUPLEES = olb::meta::plain_map<olb::meta::list<olb::names::A, olb::names::B>, olb::meta::list<olb::descriptors::VALUED_DESCRIPTOR<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >, olb::descriptors::VALUED_DESCRIPTOR<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> > > >; olb::Platform PLATFORM = olb::Platform::CPU_SISD; typename olb::AbstractCouplingO<COUPLEES>::LatticeR = olb::Vector<int, 3>]’
../../../src/core/superLatticeCoupling.h:199:17: required from ‘void olb::ConcreteBlockCouplingO<COUPLEES, PLATFORM, COUPLER, olb::OperatorScope::PerCellWithParameters>::execute() [with COUPLER = olb::ChemicalPotentialCoupling3D; COUPLEES = olb::meta::plain_map<olb::meta::list<olb::names::A, olb::names::B>, olb::meta::list<olb::descriptors::VALUED_DESCRIPTOR<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >, olb::descriptors::VALUED_DESCRIPTOR<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> > > >; olb::Platform PLATFORM = olb::Platform::CPU_SISD]’
../../../src/core/superLatticeCoupling.h:186:8: required from here
../../../src/dynamics/freeEnergyCoupling3D.h:69:7: warning: unused variable ‘term3’ [-Wunused-variable]
69 | V term3 = 0.;
| ^~~~~
g++ contactAngle3d.o -o contactAngle3d -lolbcore -L../../../external/lib -lpthread -lz -ltinyxml -L../../../build/lib
/usr/bin/ld: contactAngle3d.o: in function `prepareLattice(olb::SuperLattice<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >&, olb::SuperLattice<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >&, olb::UnitConverter<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >&, olb::SuperGeometry<double, 3u>&)’:
contactAngle3d.cpp:(.text+0x154d1): undefined reference to `void olb::setFreeEnergyWallBoundary<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >(olb::SuperLattice<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >&, olb::SuperGeometry<double, 3u>&, int, double, double, double, double, double, int, int)’
/usr/bin/ld: contactAngle3d.cpp:(.text+0x15521): undefined reference to `void olb::setFreeEnergyWallBoundary<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >(olb::SuperLattice<double, olb::descriptors::D3Q19<olb::descriptors::CHEM_POTENTIAL, olb::descriptors::FORCE> >&, olb::SuperGeometry<double, 3u>&, int, double, double, double, double, double, int, int)’
collect2: error: ld returned 1 exit status
make: *** [../../../default.single.mk:38: contactAngle3d] Error 1

Here is .h

namespace olb {

/// Implementation of a wetting boundary condition for the ternary free energy model, consisting of a BounceBack
/// dynamics and an FreeEnergyWall PostProcessor.
/// \param[in] alpha_ – Parameter related to the interface width. [lattice units]
/// \param[in] kappa1_ – Parameter related to surface tension. [lattice units]
/// \param[in] kappa2_ – Parameter related to surface tension. [lattice units]
/// \param[in] h1_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] h2_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] latticeNumber – determines the number of the free energy lattice to set the boundary accordingly
/// \param[in] ModelNumber

///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, SuperGeometry<T,3>& superGeometry, int material,
T alpha, T kappa1, T kappa2, T h1, T h2, int latticeNumber,int ModelNumber);

///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, FunctorPtr<SuperIndicatorF3D<T>>&& indicator,
T alpha, T kappa1, T kappa2, T h1, T h2, int latticeNumber, int ModelNumber);

/// Implementation of a wetting boundary condition for the ternary free energy model, consisting of a BounceBack
/// dynamics and an FreeEnergyWall PostProcessor.
/// \param[in] alpha_ – Parameter related to the interface width. [lattice units]
/// \param[in] kappa1_ – Parameter related to surface tension. [lattice units]
/// \param[in] kappa2_ – Parameter related to surface tension. [lattice units]
/// \param[in] kappa3_ – Parameter related to surface tension. [lattice units]
/// \param[in] h1_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] h2_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] h3_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] latticeNumber – determines the number of the free energy lattice to set the boundary accordingly
/// \param[in] ModelNumber
///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, SuperGeometry<T,3>& superGeometry, int material,
T alpha, T kappa1, T kappa2, T kappa3, T h1, T h2,T h3, int latticeNumber, int ModelNumber);

///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, FunctorPtr<SuperIndicatorF3D<T>>&& indicator,
T alpha, T kappa1, T kappa2, T kappa3, T h1, T h2, T h3, int latticeNumber, int ModelNumber);

//set FreeEnergyWallBoundary on block domain.
//This function works for the setFreeEnergyWallBoundary with h1,h2,h3 Parameters and h1,h2 Parameters
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(BlockLattice<T,DESCRIPTOR>& _block, BlockIndicatorF3D<T>& indicator,
T addend, int latticeNumber,int ModelNumber,bool includeOuterCells=false);

}//namespace olb

#endif

Here is .hh
namespace olb {

/// Implementation of a wetting boundary condition for the ternary free energy model, consisting of a BounceBack
/// dynamics and an FreeEnergyWall PostProcessor.
/// \param[in] alpha_ – Parameter related to the interface width. [lattice units]
/// \param[in] kappa1_ – Parameter related to surface tension. [lattice units]
/// \param[in] kappa2_ – Parameter related to surface tension. [lattice units]
/// \param[in] kappa3_ – Parameter related to surface tension. [lattice units]
/// \param[in] h1_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] h2_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] h3_ – Parameter related to resulting contact angle of the boundary. [lattice units]
/// \param[in] latticeNumber – determines the number of the free energy lattice to set the boundary accordingly
/// \param[in] ModelNumber
////////// SuperLattice Domain /////////////////////////////////////////

///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, SuperGeometry<T,3>& superGeometry, int material,
T alpha, T kappa1, T kappa2, T kappa3, T h1, T h2,T h3, int latticeNumber,int ModelNumber)
{
setFreeEnergyWallBoundary<T,DESCRIPTOR>(sLattice, superGeometry.getMaterialIndicator(material),
alpha, kappa1, kappa2, kappa3, h1, h2, h3, latticeNumber,ModelNumber);
}

///Initialising the Free Energy Wall Boundary on the superLattice domain
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(SuperLattice<T, DESCRIPTOR>& sLattice, FunctorPtr<SuperIndicatorF3D<T>>&& indicator,
T alpha, T kappa1, T kappa2, T kappa3, T h1, T h2, T h3, int latticeNumber,int ModelNumber)
{
OstreamManager clout(std::cout, “setFreeEnergyWallBoundary”);
bool includeOuterCells = false;
int _overlap = indicator->getSuperGeometry().getOverlap();
if (indicator->getSuperGeometry().getOverlap() == 1) {
includeOuterCells = true;
clout << “WARNING: overlap == 1, boundary conditions set on overlap despite unknown neighbor materials” << std::endl;
}
T addend = 0;
if (latticeNumber==1) {
if (ModelNumber==1){
addend = 1./(alpha*alpha) * ( (h1/kappa1) + (h2/kappa2) + (h3/kappa3) );
}
}
else if (latticeNumber==2) {
if (ModelNumber==1){
addend = 1./(alpha*alpha) * ( (h1/kappa1) + (-h2/kappa2) );
}
}
else if (latticeNumber==3) {
if (ModelNumber==1){
addend = 1./(alpha*alpha) * ( (h3/kappa3) );
}
}
for (int iCloc = 0; iCloc < sLattice.getLoadBalancer().size(); ++iCloc) {
setFreeEnergyWallBoundary<T,DESCRIPTOR>(sLattice.getBlock(iCloc),
indicator->getBlockIndicatorF(iCloc), addend, latticeNumber,includeOuterCells,ModelNumber);
}
/// Adds needed Cells to the Communicator _commBC in SuperLattice
addPoints2CommBC(sLattice, std::forward<decltype(indicator)>(indicator), _overlap);
}

////////// BlockLattice Domain /////////////////////////////////////////

//set FreeEnergyWallBoundary on block domain.
//This function works for the setFreeEnergyWallBoundary with h1,h2,h3 Parameters and h1,h2 Parameters
template<typename T, typename DESCRIPTOR>
void setFreeEnergyWallBoundary(BlockLattice<T,DESCRIPTOR>& _block, BlockIndicatorF3D<T>& indicator,
T addend, int latticeNumber, bool includeOuterCells,int ModelNumber)
{
using namespace boundaryhelper;
OstreamManager clout(std::cout, “setFreeEnergyWallBoundary”);
const auto& blockGeometryStructure = indicator.getBlockGeometry();
const int margin = includeOuterCells ? 0 : 1;
std::vector<int> discreteNormal(4, 0);
blockGeometryStructure.forSpatialLocations([&](auto iX, auto iY, auto iZ) {
if (blockGeometryStructure.getNeighborhoodRadius({iX, iY, iZ}) >= margin
&& indicator(iX, iY, iZ)) {
discreteNormal = blockGeometryStructure.getStatistics().getType(iX, iY, iZ, true);
if (discreteNormal[1]!=0 || discreteNormal[2]!=0 || discreteNormal[3]!=0) {
if (latticeNumber == 1) {
_block.template defineDynamics<BounceBackBulkDensity>({iX,iY,iZ});
}
else {
_block.template defineDynamics<FreeEnergyWallDynamics>({iX,iY,iZ});
}

_block.addPostProcessor(
typeid(stage::PostStream), {iX, iY, iZ},
olb::boundaryhelper::promisePostProcessorForNormal<T,DESCRIPTOR,FreeEnergyWallProcessor3D>(
Vector<int,3>(discreteNormal.data() + 1)));
_block.get(iX, iY, iZ).template setField<olb::descriptors::ADDEND>(addend);

if(latticeNumber == 1){
_block.addPostProcessor(
typeid(stage::PostStream), {iX, iY, iZ},
promisePostProcessorForNormal<T,DESCRIPTOR,FreeEnergyChemPotBoundaryProcessor3DA>(
Vector<int,3>(discreteNormal.data() + 1)));
} else {
_block.addPostProcessor(
typeid(stage::PostStream), {iX, iY, iZ},
promisePostProcessorForNormal<T,DESCRIPTOR,FreeEnergyChemPotBoundaryProcessor3DB>(
Vector<int,3>(discreteNormal.data() + 1)));
}

}
}
});
}
}//namespace olb

#endif

Here is the main

// Add wall boundary
setFreeEnergyWallBoundary<T,DESCRIPTOR>(sLattice1, superGeometry, 2, alpha, kappa1, kappa2, h1, h2, 1,1);
setFreeEnergyWallBoundary<T,DESCRIPTOR>(sLattice2, superGeometry, 2, alpha, kappa1, kappa2, h1, h2, 2,1);