operands.hpp concepts type_traits serif/discretization/blocks/concepts.hpp src/compile_time_checks/serif/discretization/forms/operands.cpp src/include/serif/backend/mfem/discretization/quadrature/mfem_static_order.hpp src/include/serif/backend/mfem/discretization/quadrature/order.hpp src/include/serif/discretization/forms/forms.hpp src/include/serif/discretization/forms/value.hpp src/include/serif/equations/contributions.hpp serif::discretization::forms::Operation serif::discretization::forms::Operation::Value serif::discretization::forms::Operation::Gradient serif::discretization::forms::Operation::Divergence serif::discretization::forms::Operation::Curl serif::discretization::forms::Operation::NormalTrace serif::discretization::forms::Operand serif serif::discretization serif::discretization::forms This file defines the Operand type, which represents a term and an operation to be applied to that term in the context of a form. Emily M. Boudreaux An Operand is a compile-time type that encapsulates a term and an operation to be applied to that term. The operation can be one of several predefined operations, such as value, gradient, divergence, curl, or normal trace. The Operand type is used in the definition of forms to specify the terms and operations involved in the form. #pragmaonce #include<concepts> #include<type_traits> #include"serif/discretization/blocks/concepts.hpp" namespaceserif::discretization::forms{ structOperation{ structValue{}; structGradient{}; structDivergence{}; structCurl{}; structNormalTrace{}; }; template<typenameOperationCandidate> conceptIsOperation= std::same_as<std::remove_cvref_t<OperationCandidate>,Operation::Value>|| std::same_as<std::remove_cvref_t<OperationCandidate>,Operation::Gradient>|| std::same_as<std::remove_cvref_t<OperationCandidate>,Operation::Divergence>|| std::same_as<std::remove_cvref_t<OperationCandidate>,Operation::Curl>|| std::same_as<std::remove_cvref_t<OperationCandidate>,Operation::NormalTrace>; template<blocks::TermTermT,IsOperationOperationT=Operation::Value>//Wechoosetodefaulttothevalueoperationbecauseitisthemostcommon. structOperandfinal{ usingterm_type=TermT; usingoperation_type=OperationT; }; template<typenameOperandCandidate> conceptIsOperand=requires{//Recallthatrequiresexpressionsarenotevaluated.Whatthischecksisthatitisvalidsyntaxgiventhetypetorequiresthetermtypeandoperationtype.Itdoesnotcheckthatthetermtypeisavalidtermorthattheoperationtypeisavalidoperation. typenamestd::remove_cvref_t<OperandCandidate>::term_type; typenamestd::remove_cvref_t<OperandCandidate>::operation_type;}&& blocks::Term<typename std::remove_cvref_t<OperandCandidate>::term_type>&&//Thenhere,nowthatweknowwecansafelyaskforthetermtypewevalidateitisactuallyavalidterm IsOperation<typename std::remove_cvref_t<OperandCandidate>::operation_type>;//Andherewevalidatethattheoperationtypeisactuallyavalidoperation };