/* This file is part of the OpenLB library
*
* Copyright (C) 2017 Max Gaedtke, Albert Mink
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/** \file
* Unit conversion handling -- header file.
*/
#ifndef UNITCONVERTER_H
#define UNITCONVERTER_H
#include
#include "io/ostreamManager.h"
#include "core/util.h"
#include "io/xmlReader.h"
// known design issues
// 1. How can we prevent abuse of constructur by mixing up parameters?
// 2. physical problems may have different names for viscosity, e.g. diffusity, temperature conductivity
// 4. Feedback about stability or comment the chosen discretization
// 5. Explain why Desctiptor as template
// 6. Is it worth to introduce invConversionDensity to avoid division
/// All OpenLB code is contained in this namespace.
namespace olb {
/** Conversion between physical and lattice units, as well as discretization.
* Be aware of the nomenclature:
* We distingish between physical (dimensioned) and lattice (dimensionless) values.
* A specific conversion factor maps the two different scopes,
* e.g. __physLength = conversionLength * latticeLength__
*
* For pressure and temperature we first shift the physical values by a characteristic value to asure a lattice pressure and lattice temperature between 0 and 1, e.g. __physPressure - charPhysPressure = conversionPressure * latticePressure__
*
* \param latticeRelaxationTime relaxation time, have to be greater than 0.5!
* - - -
* \param physViscosity physical kinematic viscosity in __m^2 / s__
* \param physDensity physical density in __kg / m^3__
* - - -
* \param conversionLength conversion factor for length __m__
* \param conversionTime conversion factor for time __s__
* \param conversionMass conversion factor for mass __kg__
* - - -
* \param conversionVelocity conversion velocity __m / s__
* \param conversionViscosity conversion kinematic viscosity __m^2 / s__
* \param conversionDensity conversion density __kg / m^3__
* \param conversionForce conversion force __kg m / s^2__
* \param conversionPressure conversion pressure __kg / m s^2__
* - - -
* \param resolution number of grid points per charPhysLength
* - - -
* \param charLatticeVelocity
*/
template
class UnitConverter {
public:
/** Documentation of constructor:
* \param physDeltaX spacing between two lattice cells in __m__
* \param physDeltaT time step in __s__
* \param charPhysLength reference/characteristic length of simulation geometry in __m__
* \param charPhysVelocity maximal or highest expected velocity during simulation in __m / s__
* \param physViscosity physical kinematic viscosity in __m^2 / s__
* \param physDensity physical density in __kg / m^3__
* \param charPhysPressure reference/characteristic physical pressure in Pa = kg / m s^2
*/
constexpr UnitConverter( T physDeltaX, T physDeltaT, T charPhysLength, T charPhysVelocity,
T physViscosity, T physDensity, T charPhysPressure = 0 )
: _conversionLength(physDeltaX),
_conversionTime(physDeltaT),
_conversionVelocity(_conversionLength / _conversionTime),
_conversionDensity(physDensity),
_conversionMass( _conversionDensity * pow(_conversionLength, 3) ),
_conversionViscosity(_conversionLength * _conversionLength / _conversionTime),
_conversionForce( _conversionMass * _conversionLength / (_conversionTime * _conversionTime) ),
_conversionPressure( _conversionForce / pow(_conversionLength, 2) ),
_charPhysLength(charPhysLength),
_charPhysVelocity(charPhysVelocity),
_physViscosity(physViscosity),
_physDensity(physDensity),
_charPhysPressure(charPhysPressure),
_resolution((int)(_charPhysLength / _conversionLength + 0.5)),
_latticeRelaxationTime( (_physViscosity / _conversionViscosity * descriptors::invCs2()) + 0.5 ),
_charLatticeVelocity( _charPhysVelocity / _conversionVelocity ),
clout(std::cout,"UnitConverter")
{
}
virtual ~UnitConverter() = default;
/// return resolution
constexpr int getResolution( ) const
{
return _resolution;
}
/// return relaxation time in lattice units
constexpr T getLatticeRelaxationTime( ) const
{
return _latticeRelaxationTime;
}
/// return relaxation frequency in lattice units
constexpr T getLatticeRelaxationFrequency( ) const
{
return 1./_latticeRelaxationTime;
}
/// return relaxation frequency in lattice units computed from given physical diffusivity in __m^2 / s__
template
constexpr T getLatticeRelaxationFrequencyFromDiffusivity( const T physDiffusivity ) const
{
T latticeDiffusivity = physDiffusivity / _conversionViscosity;
return 1.0 / ( latticeDiffusivity * descriptors::invCs2() + 0.5 );
}
/// return characteristic length in physical units
constexpr T getCharPhysLength( ) const
{
return _charPhysLength;
}
/// return characteristic velocity in physical units
constexpr T getCharPhysVelocity( ) const
{
return _charPhysVelocity;
}
/// return characteristic velocity in lattice units
constexpr T getCharLatticeVelocity( ) const
{
return _charLatticeVelocity;
}
/// return viscosity in physical units
constexpr T getPhysViscosity( ) const
{
return _physViscosity;
}
/// return density in physical units
constexpr T getPhysDensity( ) const
{
return _physDensity;
}
/// return characteristic pressure in physical units
constexpr T getCharPhysPressure( ) const
{
return _charPhysPressure;
}
/// return Reynolds number
constexpr T getReynoldsNumber( ) const
{
return _charPhysVelocity * _charPhysLength / _physViscosity;
}
/// return Mach number
constexpr T getMachNumber( ) const
{
return getCharLatticeVelocity() * std::sqrt(descriptors::invCs2());
}
/// return Knudsen number
constexpr T getKnudsenNumber( ) const
{
// This calculates the lattice Knudsen number.
// See e.g. (7.22) in "The Lattice Boltzmann Method: Principles and Practice" [kruger2017lattice].
return getMachNumber() / getReynoldsNumber();
}
/// conversion from lattice to physical length
constexpr T getPhysLength( int latticeLength ) const
{
return _conversionLength * latticeLength;
}
/// conversion from physical to lattice length, returns number of voxels for given physical length
constexpr int getLatticeLength( T physLength ) const
{
return int( physLength / _conversionLength + 0.5 );
}
/// access (read-only) to private member variable
constexpr T getConversionFactorLength() const
{
return _conversionLength;
}
/// returns grid spacing (voxel length) in __m__
constexpr T getPhysDeltaX() const
{
return _conversionLength;
}
/// conversion from lattice to physical time
constexpr T getPhysTime( int latticeTime ) const
{
return _conversionTime * latticeTime;
}
/// conversion from physical to lattice time
constexpr int getLatticeTime( T physTime ) const
{
return int(physTime / _conversionTime + 0.5);
}
/// access (read-only) to private member variable
constexpr T getConversionFactorTime() const
{
return _conversionTime;
}
/// returns time spacing (timestep length) in __s__
constexpr T getPhysDeltaT() const
{
return _conversionTime;
}
/// conversion from lattice to physical velocity
constexpr T getPhysVelocity( T latticeVelocity ) const
{
return _conversionVelocity * latticeVelocity;
}
/// conversion from physical to lattice velocity
constexpr T getLatticeVelocity( T physVelocity ) const
{
return physVelocity / _conversionVelocity;
}
/// access (read-only) to private member variable
constexpr T getConversionFactorVelocity() const
{
return _conversionVelocity;
}
/// conversion from lattice to physical density
constexpr T getPhysDensity( T latticeDensity ) const
{
return _conversionDensity * latticeDensity;
}
/// conversion from physical to lattice density
constexpr T getLatticeDensity( T physDensity ) const
{
return physDensity / _conversionDensity;
}
constexpr T getLatticeDensityFromPhysPressure( T physPressure ) const
{
T latticePressure = getLatticePressure( physPressure );
return util::densityFromPressure( latticePressure);
}
/// access (read-only) to private member variable
constexpr T getConversionFactorDensity() const
{
return _conversionDensity;
}
/// conversion from lattice to physical mass
constexpr T getPhysMass( T latticeMass ) const
{
return _conversionMass * latticeMass;
}
/// conversion from physical to lattice mass
constexpr T getLatticeMass( T physMass ) const
{
return physMass / _conversionMass;
}
/// access (read-only) to private member variable
constexpr T getConversionFactorMass() const
{
return _conversionMass;
}
/// conversion from lattice to physical viscosity
constexpr T getPhysViscosity( T latticeViscosity ) const
{
return _conversionViscosity * latticeViscosity;
}
/// conversion from physical to lattice viscosity
constexpr T getLatticeViscosity( ) const
{
return _physViscosity / _conversionViscosity;
}
/// access (read-only) to private member variable
constexpr T getConversionFactorViscosity() const
{
return _conversionViscosity;
}
/// conversion from lattice to physical force
constexpr T getPhysForce( T latticeForce ) const
{
return _conversionForce * latticeForce;
}
/// conversion from physical to lattice force
constexpr T getLatticeForce( T physForce ) const
{
return physForce / _conversionForce;
}
/// access (read-only) to private member variable
constexpr T getConversionFactorForce() const
{
return _conversionForce;
}
/// conversion from lattice to physical pressure
constexpr T getPhysPressure( T latticePressure ) const
{
return _conversionPressure * latticePressure + _charPhysPressure;
}
/// conversion from physical to lattice pressure
constexpr T getLatticePressure( T physPressure ) const
{
return ( physPressure - _charPhysPressure ) / _conversionPressure;
}
/// access (read-only) to private member variable
constexpr T getConversionFactorPressure() const
{
return _conversionPressure;
}
/// nice terminal output for conversion factors, characteristical and physical data
virtual void print() const;
void write(std::string const& fileName = "unitConverter") const;
protected:
// conversion factors
const T _conversionLength; // m
const T _conversionTime; // s
const T _conversionVelocity; // m / s
const T _conversionDensity; // kg / m^3
const T _conversionMass; // kg
const T _conversionViscosity; // m^2 / s
const T _conversionForce; // kg m / s^2
const T _conversionPressure; // kg / m s^2
// physical units, e.g characteristic or reference values
const T _charPhysLength; // m
const T _charPhysVelocity; // m / s
const T _physViscosity; // m^2 / s
const T _physDensity; // kg / m^3
const T _charPhysPressure; // kg / m s^2
// lattice units, discretization parameters
const int _resolution;
const T _latticeRelaxationTime;
const T _charLatticeVelocity; //
private:
mutable OstreamManager clout;
};
/// creator function with data given by a XML file
template
UnitConverter* createUnitConverter(XMLreader const& params);
template
class UnitConverterFromResolutionAndRelaxationTime : public UnitConverter {
public:
constexpr UnitConverterFromResolutionAndRelaxationTime(
int resolution,
T latticeRelaxationTime,
T charPhysLength,
T charPhysVelocity,
T physViscosity,
T physDensity,
T charPhysPressure = 0) : UnitConverter(
(charPhysLength/resolution),
(latticeRelaxationTime - 0.5) / descriptors::invCs2() * pow((charPhysLength/resolution),2) / physViscosity,
charPhysLength,
charPhysVelocity,
physViscosity,
physDensity,
charPhysPressure)
{
}
};
template
class UnitConverterFromResolutionAndLatticeVelocity : public UnitConverter {
public:
constexpr UnitConverterFromResolutionAndLatticeVelocity(
int resolution,
T charLatticeVelocity,
T charPhysLength,
T charPhysVelocity,
T physViscosity,
T physDensity,
T charPhysPressure = 0) : UnitConverter(
(charPhysLength/resolution),
(charLatticeVelocity / charPhysVelocity * charPhysLength / resolution),
charPhysLength,
charPhysVelocity,
physViscosity,
physDensity,
charPhysPressure)
{
}
};
template
class UnitConverterFromRelaxationTimeAndLatticeVelocity : public UnitConverter {
public:
constexpr UnitConverterFromRelaxationTimeAndLatticeVelocity(
T latticeRelaxationTime,
T charLatticeVelocity,
T charPhysLength,
T charPhysVelocity,
T physViscosity,
T physDensity,
T charPhysPressure = 0) : UnitConverter(
(physViscosity * charLatticeVelocity / charPhysVelocity * descriptors::invCs2() / (latticeRelaxationTime - 0.5)),
(physViscosity * charLatticeVelocity * charLatticeVelocity / charPhysVelocity / charPhysVelocity * descriptors::invCs2() / (latticeRelaxationTime - 0.5)),
charPhysLength,
charPhysVelocity,
physViscosity,
physDensity,
charPhysPressure)
{
}
};
} // namespace olb
#include "thermalUnitConverter.h"
#endif