24#ifndef ANALYTICAL_F_HH
25#define ANALYTICAL_F_HH
43#define M_PI 3.14159265358979323846
49template <
unsigned D,
typename T,
typename S>
54 throw std::length_error(
"D does not match with f.size().");
62template <
unsigned D,
typename T,
typename S>
65 for (
unsigned int i=0; i<D; ++i) {
66 T outputTmp[_f[i].get().getTargetDim()];
67 _f[i].get()(outputTmp,x);
68 output[i]=outputTmp[0];
74template <
unsigned D,
typename T,
typename S>
81template <
unsigned D,
typename T,
typename S>
89template <
unsigned D,
typename T,
typename S>
98template <
unsigned D,
typename T,
typename S>
102 _c.push_back(value0);
103 _c.push_back(value1);
104 _c.push_back(value2);
108template <
unsigned D,
typename T,
typename S>
113 _c.push_back(value[0]);
114 _c.push_back(value[1]);
118template <
unsigned D,
typename T,
typename S>
123 _c.push_back(value[0]);
124 _c.push_back(value[1]);
125 _c.push_back(value[2]);
129template <
unsigned D,
typename T,
typename S>
132 for (
unsigned i = 0; i < _c.size(); ++i) {
139template <
unsigned D,
typename T,
typename S>
141 :
AnalyticalF<D,T,S>(1), _mean(mean), _stdDev(stdDev)
146template <
unsigned D,
typename T,
typename S>
150 for (
unsigned i = 0; i < D; ++i) {
151 r2 += (x[i] - _mean[i]) * (x[i] - _mean[i]);
158template <
unsigned D,
typename T,
typename S>
166template <
unsigned D,
typename T,
typename S,
unsigned seed>
171 this->
getName() =
"randomSeeded";
174template <
unsigned D,
typename T,
typename S>
177 distro{minVal, maxVal}
180template <
unsigned D,
typename T,
typename S>
183 output[0] = distro(this->gen);
188template <
unsigned D,
typename T,
typename S>
194template <
unsigned D,
typename T,
typename S>
197 output[0] = distro(this->gen);
201template <
unsigned D,
typename T,
typename S,
unsigned seed>
207template <
unsigned D,
typename T,
typename S,
unsigned seed>
210 output[0] = distro(this->gen);
215template <
unsigned D,
typename T,
typename S>
218 _min(mean - n*stdDev),
219 _max(mean + n*stdDev)
222template <
unsigned D,
typename T,
typename S>
226 output[0] = this->distro(this->gen);
228 while (output[0] < _min || output[0] > _max);
233template <
unsigned D,
typename T,
typename S>
237#ifdef PARALLEL_MODE_MPI
238 int nameLen, numProcs, myID;
239 char processorName[MPI_MAX_PROCESSOR_NAME];
240 MPI_Comm_rank(MPI_COMM_WORLD,&myID);
241 MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
242 MPI_Get_processor_name(processorName,&nameLen);
243 srand(time(0)+myID*numProcs + nameLen);
245 srand(time(
nullptr));
250template <
unsigned D,
typename T,
typename S>
253 output[0]=(rand()%RAND_MAX)/(T)RAND_MAX;
258template <
typename T,
typename S,
typename DESCRIPTOR>
266 _angularVelocity(angularVelocity)
268 this->
getName() =
"EccentricVelocityField";
271template <
typename T,
typename S,
typename DESCRIPTOR>
274 constexpr unsigned D = DESCRIPTOR::d;
277 for (
unsigned iDim=0; iDim<D; ++iDim) {
278 output[iDim] = localVel[iDim];
284template <
typename T,
typename S,
typename DESCRIPTOR>
293 _angularVelocity(angularVelocity),
294 _converter(converter)
296 this->
getName() =
"EccentricLatticeVelocityField";
299template <
typename T,
typename S,
typename DESCRIPTOR>
302 constexpr unsigned D = DESCRIPTOR::d;
305 for (
unsigned iDim=0; iDim<D; ++iDim) {
306 output[iDim] = _converter.getLatticeVelocity( localVel[iDim] );
313template <
unsigned D,
typename T,
typename S>
315 T period, T amplitude, T difference)
317 _amplitude(amplitude), _difference(difference)
320template <
unsigned D,
typename T,
typename S>
324 output[0] = _amplitude;
327 output[0] = - _amplitude;
333template <
unsigned D,
typename T,
typename S>
335 T period, T amplitude, T difference, T epsilon)
339 OLB_ASSERT(epsilon < difference,
"Smoothing region is to large for given phase difference");
342template <
unsigned D,
typename T,
typename S>
348 else if (
util::fmod_pos(x[0],this->_period) <= this->_difference * this->_period - 0.5 * _epsilon ) {
349 output[0] = this->_amplitude;
351 else if (
util::fmod_pos(x[0],this->_period) <= this->_difference * this->_period + 0.5 * _epsilon ) {
352 output[0] = - this->_amplitude
355 else if (
util::fmod_pos(x[0],this->_period) <= this->_period - 0.5 * _epsilon ) {
356 output[0] = - this->_amplitude;
359 output[0] = this->_amplitude
371template <
typename T,
typename S>
378template <
typename T,
typename S>
383 std::cout <<
"Error: x1-x2=0" << std::endl;
386 _a = ( v1-v0 ) / ( x1-x0 );
392template <
typename T,
typename S>
395 output[0]=_a*x[0] + _b;
400template <
typename T,
typename S>
407template <
typename T,
typename S>
410 output[0]=_maxi*(1-(x[0]-_cp) * (x[0]-_cp) / (T)_r / (T)_r);
417template <
typename T,
typename S>
419 :
AnalyticalF1D<T,S>(1), _numTimeSteps(numTimeSteps), _maxValue(maxValue)
421 this->
getName() =
"polyStartScale";
424template <
typename T,
typename S>
427 output[0]=(T) x[0] / (T) _numTimeSteps;
428 output[0]=_maxValue * output[0]*output[0]*output[0] * ( 10.0 + output[0] * (6.0*output[0] - 15.0) );
433template <
typename T,
typename S>
435 :
AnalyticalF1D<T,S>(1), _numTimeSteps(numTimeSteps), _maxValue(maxValue)
437 this->
getName() =
"sinusStartScale";
440template <
typename T,
typename S>
443 output[0]=(_maxValue * (
util::sin(-
M_PI / 2.0 + (T)x[0] / (T)_numTimeSteps *
M_PI) + 1.0)) / 2.0;
448template <
typename T,
typename S>
450 :
AnalyticalF1D<T,S>(1), _period(period), _amplitude(amplitude)
455template <
typename T,
typename S>
458 output[0] = _amplitude *
util::sin((x[0] / _period) * 2 *
M_PI);
463template <
typename T,
typename S>
467 _amplitude(amplitude)
472template <
typename T,
typename S>
475 output[0] = _amplitude *
util::cos((x[0] / _period) * T(2) *
M_PI);
479template <
typename T,
typename S>
483 _difference(difference),
484 _amplitude(amplitude)
486 this->
getName() =
"CosinusComposite";
489template <
typename T,
typename S>
493 output[0] = _amplitude
495 / (_difference * _period)) *
M_PI);
498 output[0] = _amplitude
500 / (_period - (_difference * _period))) *
M_PI +
M_PI);
509template <
typename T,
typename S>
516template <
typename T,
typename S>
518 T v1, S x2, S y2, T v2)
522 T n2= (x1-x0)*(y2-y0) - (y1-y0)*(x2-x0);
524 std::cout <<
"Error function" << std::endl;
527 T n0 = (y1-y0)*(v2-v0) - (v1-v0)*(y2-y0);
528 T n1 = (v1-v0)*(x2-x0) - (x1-x0)*(v2-v0);
531 _c = (x0*n0 + y0*n1 + v0*n2) / n2;
535template <
typename T,
typename S>
538 output[0]=_a*x[0] + _b*x[1] + _c;
542template <
typename T,
typename S>
547 this->
getName() =
"particleAdsorptionLinear2D";
550template <
typename T,
typename S>
553 T dist =
util::sqrt((input[0]-_center[0])*(input[0]-_center[0]) + (input[1]-_center[1])*(input[1]-_center[1]));
555 if (dist > _radius) {
561 output[0] = _maxValue*(T(1) - dist/_radius)*(_center[0]-input[0])/_radius;
562 output[1] = _maxValue*(T(1) - dist/_radius)*(_center[1]-input[1])/_radius;
570template <
typename T,
typename S>
577template <
typename T,
typename S>
579 S y1, S z1, T v1, S x2, S y2, S z2, T v2, S x3, S y3, S z3, T v3)
583 T n = ( (y3-y0)*(x1-x0)-(x3-x0)*(y1-y0) ) * ( (x2-x0)*(z1-z0)-(z2-z0)*(x1-x0) )
584 +( (z3-z0)*(x1-x0)-(x3-x0)*(z1-z0) ) * ( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) );
586 std::cout <<
"Error function" << std::endl;
589 T w = ( (y1-y0)*(x3-x0)-(x1-x0)*(y3-y0) ) * ( (v2-v0)-(x2-x0)*(v1-v0) / (x1-x0) )
590 /( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) ) + (v3-v0) - (x3-x0)*(v1-v0) / (x1-x0);
591 T zx = (y1-y0)*( (x2-x0)*(z1-z0)-(z2-z0)*(x1-x0) )
592 -(z1-z0)*( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) );
593 T rx = (v1-v0)/(x1-x0) - (y1-y0)*(v2-v0) / ( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) )
594 +(y1-y0)*(x2-x0)*(v1-v0) / ( (y2-y0)*(x1-x0)*(x1-x0)-(x2-x0)*(y1-y0)*(x1-x0) );
595 T zy = (x1-x0)*( (x2-x0)*(z1-z0)-(z2-z0)*(x1-x0) );
596 T ry = ( (x1-x0)*(v2-v0)-(x2-x0)*(v1-v0) ) / ( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) );
597 T zz = (x1-x0)*( (y2-y0)*(x1-x0)-(x2-x0)*(y1-y0) );
606template <
typename T,
typename S>
609 output[0]=_a*x[0] + _b*x[1] + _c*x[2] + _d;
614template <
typename T,
typename S>
621template <
typename T,
typename S>
624 T outputTmp[_f.getTargetDim()];
626 for (
int iDim = 0; iDim < this->getTargetDim(); ++iDim) {
627 output[iDim] = _scale*outputTmp[iDim];
634template <
typename T,
typename S,
typename DESCRIPTOR>
637 _physSigmaEff(util::sqrt( converter.getPhysAbsorption() / converter.getPhysDiffusion() )),
638 _physDiffusionCoefficient(converter.getPhysDiffusion())
640 this->
getName() =
"PLSsolution3D";
643template <
typename T,
typename S,
typename DESCRIPTOR>
646 double r =
util::sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] );
647 output[0] = 1. / (4.0*
M_PI*_physDiffusionCoefficient*r) *
util::exp(-_physSigmaEff * r);
652template <
typename T,
typename S,
typename DESCRIPTOR>
655 _physSigmaEff(util::sqrt( converter.getPhysAbsorption() / converter.getPhysDiffusion() )),
656 _physDiffusionCoefficient(converter.getPhysDiffusion()),
659 this->
getName() =
"LightSourceCylindrical3D";
662template <
typename T,
typename S,
typename DESCRIPTOR>
665 double r =
util::sqrt( (x[0]-_center[0])*(x[0]-_center[0]) + (x[1]-_center[1])*(x[1]-_center[1]) );
667 std::cout <<
"Warning: evaluation of \"LightSourceCylindrical3D\" functor close to singularity." << std::endl;
669 output[0] = 1. / (4.0*
M_PI*_physDiffusionCoefficient*r) *
util::exp(-_physSigmaEff * r);
674template <
typename T,
typename S>
676 :
AnalyticalF3D<T,S>(1), _position(position), _orientation(direction[0]/
norm(direction), direction[1]/
norm(direction), direction[2]/
norm(direction)), _falloff(falloff)
681template <
typename T,
typename S>
684 Vector<T,3> w(x[0] -_position[0], x[1] -_position[1], x[2] -_position[2]);
686 T cosPhi = w*_orientation;
692template <
typename T,
typename S>
694 :
AnalyticalF2D<T,S>(1), _sigma(sigma), _x0(x0[0],x0[1]), _c0(c0)
696 this->
getName() =
"GaussianHill";
699template <
typename T,
typename S>
702 output[0] = _c0 *
util::exp(- ((x[0]-_x0[0])*(x[0]-_x0[0]) + (x[1]-_x0[1])*(x[1]-_x0[1])) / (2*_sigma*_sigma) );
707template <
typename T,
typename S>
709 :
AnalyticalF2D<T,S>(1), _sigma02(sigma0*sigma0), _D(D), _t(t), _x0(x0[0],x0[1]), _u(u[0],u[1]), _c0(c0)
711 this->
getName() =
"GaussianHillTimeEvolution";
714template <
typename T,
typename S>
717 output[0] = _sigma02 / (_sigma02+2*_D*_t) * _c0 *
util::exp(- ((x[0]-_x0[0]-_u[0]*_t)*(x[0]-_x0[0]-_u[0]*_t) + (x[1]-_x0[1]-_u[1]*_t)*(x[1]-_x0[1]-_u[1]*_t)) / (2*(_sigma02+2*_D*_t) ));
Some arithmetic helper functions.
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalComposed(AnalyticalF< D, T, S > &f0, AnalyticalF< D, T, S > &f1)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalF are applications from DD to XD, where X is set by the constructor.
bool operator()(T output[], const S x[]) override
returns line _a*x + _b
AnalyticalLinear1D(T a, T b)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalLinear2D(T a, T b, T c)
AnalyticalLinear3D(T a, T b, T c, T d)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalNormal(std::vector< T > mean, T stdDev)
bool operator()(T output[], const S x[])
has to be implemented for 'every' derived class
AnalyticalParticleAdsorptionLinear2D(T center[], T radius, T maxValue)
AnalyticalRandomBase: virtual base class for all the random functionals.
AnalyticalRandomNormal: DD -> 1D with random image in (0,1)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalRandomNormal(T mean=0., T stdDev=1.)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalRamdomSeededBase: alternative version with seed specification.
AnalyticalRandomSeededBase()
AnalyticalRandomSeededNormal(T mean=0., T stdDev=1.)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalRandomTruncatedNormal(T mean=0., T stdDev=1., T n=3.)
AnalyticalScaled3D(AnalyticalF3D< T, S > &f, T scale)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalSmoothedSquareWave(T period=1, T amplitude=1, T difference=0.5, T epsilon=1.e-3)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalSquare1D(S cp, S r, T maxi)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
Square wave with given period length, amplitude, difference (= length of positive time / length of pe...
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
AnalyticalSquareWave(T period=1, T amplitude=1, T difference=0.5)
CosinusComposite(T period=1, T amplitude=1, T difference=1)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
Cosinus(T period=1, T amplitude=1)
EccentricLatticeVelocityField(Vector< T, DESCRIPTOR::d > position, Vector< T, DESCRIPTOR::d > velocity, Vector< T, utilities::dimensions::convert< DESCRIPTOR::d >::rotation > angularVelocity, UnitConverter< T, DESCRIPTOR > const &converter)
bool operator()(T output[], const S input[]) override
has to be implemented for 'every' derived class
bool operator()(T output[], const S input[]) override
has to be implemented for 'every' derived class
EccentricVelocityField(Vector< T, DESCRIPTOR::d > position, Vector< T, DESCRIPTOR::d > velocity, Vector< T, utilities::dimensions::convert< DESCRIPTOR::d >::rotation > angularVelocity)
bool operator()(T output[1], const S x[2]) override
GaussianHill2D(T sigma, Vector< T, 2 > x0, T c0)
bool operator()(T output[1], const S x[2]) override
GaussianHillTimeEvolution2D(T sigma0, T D, T t, Vector< T, 2 > x0, Vector< T, 2 > u, T c0)
std::string & getName()
read and write access to name
bool operator()(T output[1], const S x[3]) override
LightSourceCylindrical3D(RadiativeUnitConverter< T, DESCRIPTOR > const &converter, Vector< T, 3 > center={T(0), T(0), T(0)})
PLSsolution3D(RadiativeUnitConverter< T, DESCRIPTOR > const &converter)
bool operator()(T output[1], const S x[3]) override
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
PolynomialStartScale(S numTimeSteps=S(1), T maxValue=T(1))
Conversion between physical and lattice units, as well as discretization.
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
SinusStartScale(int numTimeSteps=1, T maxValue=1)
bool operator()(T output[], const S x[]) override
has to be implemented for 'every' derived class
Sinus(T period=1, T amplitude=1)
bool operator()(T output[1], const S x[3]) override
Spotlight(Vector< T, 3 > position, Vector< T, 3 > direction, T falloff)
Conversion between physical and lattice units, as well as discretization.
Wrapper functions that simplify the use of MPI.
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
auto fmod_pos(T a, S b)
Variant of fmod (floating point modulo) that always returns positive values.
ADf< T, DIM > sin(const ADf< T, DIM > &a)
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
constexpr Vector< T, D > calculateLocalVelocity(const Vector< T, D > &rotationCenter, const Vector< T, D > &velocity, const Vector< T, utilities::dimensions::convert< D >::rotation > &angularVelocity, const Vector< T, D > &position)
Calculate local velocity.
bool nearZero(const ADf< T, DIM > &a)
ADf< T, DIM > exp(const ADf< T, DIM > &a)
ADf< T, DIM > cos(const ADf< T, DIM > &a)
Top level namespace for all of OpenLB.
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})
#define OLB_ASSERT(COND, MESSAGE)
Unit conversion handling – header file.
Definition of singletons: global, publicly available information.
Converts dimensions by deriving from given cartesian dimension D.