/* This file is part of the OpenLB library * * Copyright (C) 2019 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 DESCRIPTOR_FIELD_H #define DESCRIPTOR_FIELD_H #include #include namespace olb { namespace descriptors { /// \defgroup descriptor //@{ /// Base of a descriptor field whose size is defined by A*D + B*Q + C template struct DESCRIPTOR_FIELD_BASE { /// Deleted constructor to enforce pure usage as type and prevent implicit narrowing conversions DESCRIPTOR_FIELD_BASE() = delete; /// Evaluates the size function /** * To be called by DESCRIPTOR_BASE **/ template static constexpr unsigned size() { return A * D + B * Q + C; } /// Returns global index from local index and provides out_of_range safety template static constexpr unsigned getLocalIndex(const unsigned localIndex) { return localIndex < (A*D+B*Q+C) ? localIndex : throw std::out_of_range("Index exceeds data field"); } }; /// \defgroup descriptor_fields Set of common descriptor fields /// \ingroup descriptor //@{ // Field types need to be distinct (i.e. not aliases) in order for `getDescriptorFieldBeginsAt` to work // (Field size parametrized by: Cs + Ds*D + Qs*Q) Cs Ds Qs struct POPULATION : public DESCRIPTOR_FIELD_BASE<0, 0, 1> { }; struct VELOCITY : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct VELOCITY2 : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct SOURCE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct FORCE : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct EXTERNAL_FORCE : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct TAU_EFF : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct CUTOFF_KIN_ENERGY : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct CUTOFF_HEAT_FLUX : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct CHEM_POTENTIAL : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct V6 : public DESCRIPTOR_FIELD_BASE<6, 0, 0> { }; struct V12 : public DESCRIPTOR_FIELD_BASE<12, 0, 0> { }; struct OMEGA : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct G : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct EPSILON : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct BODY_FORCE : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct K : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct NU : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct POROSITY : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct VELOCITY_NUMERATOR : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct VELOCITY_DENOMINATOR : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_DRAG : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct VELOCITY_SOLID : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct COORDINATE : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct F : public DESCRIPTOR_FIELD_BASE<0, 0, 1> { }; struct DJDF : public DESCRIPTOR_FIELD_BASE<0, 0, 1> { }; struct DJDALPHA : public DESCRIPTOR_FIELD_BASE<0, 1, 0> { }; struct AV_SHEAR : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct TAU_W : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct SCALAR : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct SMAGO_CONST : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct EFFECTIVE_OMEGA : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct VELO_GRAD : public DESCRIPTOR_FIELD_BASE<0, 3, 0> { }; struct FIL_RHO : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_FIL_VEL_X : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_FIL_VEL_Y : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_FIL_VEL_Z : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_AV_DISS : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_AV_TKE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_SIGMA_ADM : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct LOCAL_NU_EDDY : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct FILTERED_VEL_GRAD : public DESCRIPTOR_FIELD_BASE<0, 3, 0> { }; struct ERROR_COVARIANCE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct VARIANCE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct TAU_SGS : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct FILTERED_POPULATION : public DESCRIPTOR_FIELD_BASE<0, 0, 1> { }; struct INDICATE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct BIOGAS_INSTANT : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct BIOGAS_CUMULATIVE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct METHANE_INSTANT : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct METHANE_CUMULATIVE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct CO2_INSTANT : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct CO2_CUMULATIVE : public DESCRIPTOR_FIELD_BASE<1, 0, 0> { }; struct TENSOR { TENSOR() = delete; template static constexpr unsigned size() { return (D * (D+1)) / 2; // see `TensorVal` in `core/util.h` } template static constexpr unsigned getLocalIndex(const unsigned localIndex) { return localIndex < size() ? localIndex : throw (std::out_of_range("Index exceeds data field")); } }; //@} /// \defgroup descriptor_details Descriptor field handling /// \ingroup descriptor //@{ template < unsigned D, unsigned Q, typename WANTED_FIELD, typename CURRENT_FIELD, typename... FIELDS, // WANTED_FIELD equals the head of our field list, terminate recursion utilities::meta::enable_if_t::value, int> = 0 > constexpr unsigned getIndexFromFieldList() { return 0; } template < unsigned D, unsigned Q, typename WANTED_FIELD, typename CURRENT_FIELD, typename... FIELDS, // WANTED_FIELD doesn't equal the head of our field list utilities::meta::enable_if_t::value, int> = 0 > constexpr unsigned getIndexFromFieldList() { // Break compilation when WANTED_FIELD is not provided by list of fields static_assert(sizeof...(FIELDS) > 0, "Field not found."); // Add size of current field to implicit offset and continue search // for WANTED_FIELD in the tail of our field list return CURRENT_FIELD::template size() + getIndexFromFieldList(); } template constexpr unsigned getFieldListSize() { // Field-less descriptor base case return 0; } template constexpr unsigned getFieldListSize() { // Calculate size of CURRENT_FIELD and add it to the sum of all remaining field sizes return CURRENT_FIELD::template size() + getFieldListSize(); } //@} //@} } } #endif