/* This file is part of the OpenLB library * * Copyright (C) 2012-2018 Lukas Baron, Tim Dornieden, Mathias J. Krause, * Albert Mink, Adrian Kummerlaender * 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. */ #ifndef ANALYTICAL_CALC_F_HH #define ANALYTICAL_CALC_F_HH #include "analyticCalcF.h" #include "analyticalF.h" #include "core/olbDebug.h" namespace olb { //////////////////////////////// AnalyticCalcF1D //////////////////////////////// template class F> AnalyticCalcF1D::AnalyticCalcF1D(FunctorPtr>&& f, FunctorPtr>&& g) : AnalyticalF1D(f->getTargetDim()), _f(std::move(f)), _g(std::move(g)) { OLB_ASSERT(g->getTargetDim() == f->getTargetDim(), "the dimensions of both functors need to be equal"); std::swap(f->_ptrCalcC, this->_ptrCalcC); this->getName() = "(" + _f->getName() + F::symbol + _g->getName() + ")"; } template class F> AnalyticCalcF1D::AnalyticCalcF1D(T scalar, FunctorPtr>&& g) : AnalyticCalcF1D( std::unique_ptr>( new AnalyticalConst1D(std::vector(g->getTargetDim(), scalar))), std::forward(g)) { } template class F> AnalyticCalcF1D::AnalyticCalcF1D(FunctorPtr>&& f, T scalar) : AnalyticCalcF1D( std::forward(f), std::unique_ptr>( new AnalyticalConst1D(std::vector(f->getTargetDim(), scalar)))) { } template class F> bool AnalyticCalcF1D::operator()(T output[], const S input[]) { T outputTmp[this->_g->getTargetDim()]; this->_g(outputTmp, input); this->_f(output, input); for (int i = 0; i < this->_f->getTargetDim(); ++i) { output[i] = F()(output[i], outputTmp[i]); } return true; } template std::shared_ptr> operator+(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus1D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator+(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcPlus1D(std::move(lhs), rhs)); } template std::shared_ptr> operator+(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus1D(lhs, std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus1D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMinus1D(std::move(lhs), rhs)); } template std::shared_ptr> operator-(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus1D(lhs, std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication1D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication1D(std::move(lhs), rhs)); } template std::shared_ptr> operator*(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication1D(lhs, std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision1D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcDivision1D(std::move(lhs), rhs)); } template std::shared_ptr> operator/(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision1D(lhs, std::move(rhs))); } /////////////////////////////////operator()/// //////////////////////////////// template AnalyticalF1D& AnalyticalF1D::operator+(AnalyticalF1D& rhs) { auto tmp = std::make_shared< AnalyticCalcPlus1D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF1D& AnalyticalF1D::operator-(AnalyticalF1D& rhs) { auto tmp = std::make_shared< AnalyticCalcMinus1D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF1D& AnalyticalF1D::operator*(AnalyticalF1D& rhs) { auto tmp = std::make_shared< AnalyticCalcMultiplication1D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF1D& AnalyticalF1D::operator/(AnalyticalF1D& rhs) { auto tmp = std::make_shared< AnalyticCalcDivision1D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } //////////////////////////////// AnalyticCalcF2D //////////////////////////////// template class F> AnalyticCalcF2D::AnalyticCalcF2D(FunctorPtr>&& f, FunctorPtr>&& g) : AnalyticalF2D(f->getTargetDim()), _f(std::move(f)), _g(std::move(g)) { OLB_ASSERT(g->getTargetDim() == f->getTargetDim(), "the dimensions of both functors need to be equal"); // pass through the shared_ptr from the first argument f to the arithmetic class itself. // used by secsessive calls: e.g. (functorA + functor B) followed by (functorA + functorC) // the result of the first operation is overwritten by the second. // equivalent operations // std::swap(f._ptrCalcC, this->_ptrCalcC); // this->_ptrCalcC = f._ptrCalcC; this->_ptrCalcC.swap(f->_ptrCalcC); this->getName() = "(" + _f->getName() + F::symbol + _g->getName() + ")"; } template class F> AnalyticCalcF2D::AnalyticCalcF2D(T scalar, FunctorPtr>&& g) : AnalyticCalcF2D( std::unique_ptr>( new AnalyticalConst2D(std::vector(g->getTargetDim(), scalar))), std::forward(g)) { } template class F> AnalyticCalcF2D::AnalyticCalcF2D(FunctorPtr>&& f, T scalar) : AnalyticCalcF2D( std::forward(f), std::unique_ptr>( new AnalyticalConst2D(std::vector(f->getTargetDim(), scalar)))) { } template class F> bool AnalyticCalcF2D::operator()(T output[], const S input[]) { T outputTmp[this->_g->getTargetDim()]; this->_g(outputTmp, input); this->_f(output, input); for (int i = 0; i < this->_f->getTargetDim(); ++i) { output[i] = F()(output[i], outputTmp[i]); } return true; } template std::shared_ptr> operator+(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus2D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator+(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcPlus2D(std::move(lhs), rhs)); } template std::shared_ptr> operator+(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus2D(lhs, std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus2D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMinus2D(std::move(lhs), rhs)); } template std::shared_ptr> operator-(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus2D(lhs, std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication2D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication2D(std::move(lhs), rhs)); } template std::shared_ptr> operator*(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication2D(lhs, std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision2D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcDivision2D(std::move(lhs), rhs)); } template std::shared_ptr> operator/(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision2D(lhs, std::move(rhs))); } /////////////////////////////////operator()//////////////////////////////////// template AnalyticalF2D& AnalyticalF2D::operator+(AnalyticalF2D& rhs) { // version 1 // AnalyticalF2D* tmp = new AnalyticCalcPlus2D(*this,rhs); // std::shared_ptr< GenericF > ptr( tmp ); // this->_ptrCalcC = ptr; // version 2 // std::shared_ptr< AnalyticalF2D > tmp = std::make_shared< AnalyticCalcPlus2D >(*this,rhs); // version 2.5 // std::shared_ptr< AnalyticCalcPlus2D > tmp( new AnalyticCalcPlus2D(*this,rhs) ); // version 3 auto tmp = std::make_shared< AnalyticCalcPlus2D >(*this,rhs); this->_ptrCalcC = tmp; // std::cout << "operator+(): " << this->_ptrCalcC.get()->getName() << std::endl; return *tmp; } template AnalyticalF2D& AnalyticalF2D::operator-(AnalyticalF2D& rhs) { auto tmp = std::make_shared< AnalyticCalcMinus2D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF2D& AnalyticalF2D::operator*(AnalyticalF2D& rhs) { auto tmp = std::make_shared< AnalyticCalcMultiplication2D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF2D& AnalyticalF2D::operator/(AnalyticalF2D& rhs) { auto tmp = std::make_shared< AnalyticCalcDivision2D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } //////////////////////////////// AnalyticCalcF3D //////////////////////////////// template class F> AnalyticCalcF3D::AnalyticCalcF3D(FunctorPtr>&& f, FunctorPtr>&& g): AnalyticalF3D(f->getTargetDim()), _f(std::move(f)), _g(std::move(g)) { OLB_ASSERT(g->getTargetDim() == f->getTargetDim(), "the dimensions of both functors need to be equal"); std::swap(f->_ptrCalcC, this->_ptrCalcC); this->getName() = "(" + _f->getName() + F::symbol + _g->getName() + ")"; } template class F> AnalyticCalcF3D::AnalyticCalcF3D(T scalar, FunctorPtr>&& g) : AnalyticCalcF3D( std::unique_ptr>( new AnalyticalConst3D(std::vector(g->getTargetDim(), scalar))), std::forward(g)) { } template class F> AnalyticCalcF3D::AnalyticCalcF3D(FunctorPtr>&& f, T scalar) : AnalyticCalcF3D( std::forward(f), std::unique_ptr>( new AnalyticalConst3D(std::vector(f->getTargetDim(), scalar)))) { } template class F> bool AnalyticCalcF3D::operator()(T output[], const S input[]) { T outputTmp[this->_g->getTargetDim()]; this->_g(outputTmp, input); this->_f(output, input); for (int i = 0; i < this->_f->getTargetDim(); ++i) { output[i] = F()(output[i], outputTmp[i]); } return true; } template std::shared_ptr> operator+(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus3D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator+(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcPlus3D(std::move(lhs), rhs)); } template std::shared_ptr> operator+(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcPlus3D(lhs, std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus3D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator-(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMinus3D(std::move(lhs), rhs)); } template std::shared_ptr> operator-(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMinus3D(lhs, std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication3D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator*(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication3D(std::move(lhs), rhs)); } template std::shared_ptr> operator*(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcMultiplication3D(lhs, std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision3D(std::move(lhs), std::move(rhs))); } template std::shared_ptr> operator/(std::shared_ptr> lhs, T rhs) { return std::shared_ptr>( new AnalyticCalcDivision3D(std::move(lhs), rhs)); } template std::shared_ptr> operator/(T lhs, std::shared_ptr> rhs) { return std::shared_ptr>( new AnalyticCalcDivision3D(lhs, std::move(rhs))); } /////////////////////////////////operator()/// //////////////////////////////// template AnalyticalF3D& AnalyticalF3D::operator+(AnalyticalF3D& rhs) { auto tmp = std::make_shared< AnalyticCalcPlus3D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF3D& AnalyticalF3D::operator-(AnalyticalF3D& rhs) { auto tmp = std::make_shared< AnalyticCalcMinus3D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF3D& AnalyticalF3D::operator*(AnalyticalF3D& rhs) { auto tmp = std::make_shared< AnalyticCalcMultiplication3D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } template AnalyticalF3D& AnalyticalF3D::operator/(AnalyticalF3D& rhs) { auto tmp = std::make_shared< AnalyticCalcDivision3D >(*this,rhs); this->_ptrCalcC = tmp; return *tmp; } } // end namespace olb #endif