value.hpp array type_traits serif/discretization/blocks/traits.hpp serif/discretization/forms/operands.hpp src/include/serif/equations/point.hpp src/include/serif/equations/rigid_rotation.hpp src/include/serif/geometry/surface/detail/relations.hpp serif::discretization::forms::OperationValue< 0, Operation::Value > serif::discretization::forms::OperationValue< 1, Operation::Value > serif::discretization::forms::OperationValue< 1, Operation::Divergence > serif::discretization::forms::OperationValue< 0, Operation::Gradient > serif::discretization::forms::OperationValue< 1, Operation::Gradient > serif::discretization::forms::OperationValue< 1, Operation::Curl > serif::discretization::forms::OperationValue< 1, Operation::NormalTrace > serif::discretization::forms::OperandResult< OperandT > serif::discretization::forms::ValueComponents< double > serif::discretization::forms::ValueComponents< void > serif::discretization::forms::ValueComponents< std::array< Entry, Size > > serif serif::discretization serif::discretization::forms Encode compile time information about the shape (rank) and data type of the result of various Operations. Emily M. Boudreaux TodoThis should be consolidated and removed. This information could be injected into the Operation itself. #pragmaonce #include<array> #include<type_traits> #include"serif/discretization/blocks/traits.hpp" #include"serif/discretization/forms/operands.hpp" namespaceserif::discretization::forms{ usingVectorValue=std::array<double,3>; usingMatrixValue=std::array<VectorValue,3>; template<std::size_tRank,typenameOperationT> structOperationValue; template<> structOperationValue<0,Operation::Value>{ usingtype=double; }; template<> structOperationValue<1,Operation::Value>{ usingtype=VectorValue; }; template<> structOperationValue<1,Operation::Divergence>{ usingtype=double; }; template<> structOperationValue<0,Operation::Gradient>{ usingtype=VectorValue; }; template<> structOperationValue<1,Operation::Gradient>{ usingtype=MatrixValue; }; template<> structOperationValue<1,Operation::Curl>{ usingtype=VectorValue; }; template<> structOperationValue<1,Operation::NormalTrace>{ usingtype=double; }; template<typenameOperandT> structOperandResult; template<IsOperandOperandT> requiresblocks::SpatialTerm<typename OperandT::term_type> structOperandResult<OperandT>:OperationValue<blocks::SpatialTermTraits<typenameOperandT::term_type>::rank,typenameOperandT::operation_type>{}; template<IsOperandOperandT> requiresblocks::GlobalScalarTerm<typename OperandT::term_type>&&std::same_as<typenameOperandT::operation_type,Operation::Value> structOperandResult<OperandT>{ usingtype=double; }; template<IsOperandOperandT> usingOperandValue=OperandResult<OperandT>::type; template<typenameValueT> structValueComponents; template<> structValueComponents<double>:std::integral_constant<int,1>{}; //OperandValuesusesvoidtorequestvaluesinsteadofderivatives;thatbranchstoresnoderivativeentries. template<> structValueComponents<void>:std::integral_constant<int,0>{}; template<typenameEntry,std::size_tSize> structValueComponents<std::array<Entry,Size>>:std::integral_constant<int,Size*ValueComponents<Entry>::value>{}; template<typenameValueT> inlineconstexprintcomponent_count=ValueComponents<std::remove_cv_t<ValueT>>::value; template<typenameOutputT,typenameInputT> usingPartialDerivative=std::conditional_t<std::same_as<OutputT,double>,InputT,std::conditional_t<std::same_as<InputT,double>,OutputT, std::array<std::array<double,component_count<InputT>>,component_count<OutputT>>>>; template<typenameValueT> decltype(auto)component(ValueT&value,intindex){ ifconstexpr(std::same_as<std::remove_cv_t<ValueT>,double>){ return(value); }else{ usingEntry=typenamestd::remove_cv_t<ValueT>::value_type; constexprintstride=component_count<Entry>; returncomponent(value[index/stride],index%stride); } } template<typenameOutputT,typenameInputT> doublederivative_component(constPartialDerivative<OutputT, InputT>&value,intoutput,intinput){ ifconstexpr(std::same_as<OutputT,double>){ returncomponent(value,input); }elseifconstexpr(std::same_as<InputT,double>){ returncomponent(value,output); }else{ returnvalue[output][input]; } } }//namespaceserif::discretization::forms