23 #ifndef COM_DAFER45_TBTK_ABSTRACT_PROPERTY
24 #define COM_DAFER45_TBTK_ABSTRACT_PROPERTY
27 #include "TBTK/Property/Property.h"
30 #include "TBTK/SpinMatrix.h"
33 #include "TBTK/json.hpp"
100 template<
typename DataType>
118 const std::vector<DataType>&
getData()
const;
191 const std::vector<Index> &targetPatterns,
192 const std::vector<Index> &newPatterns
233 unsigned int offset = 0
255 unsigned int offset = 0
267 DataType&
operator()(
const std::initializer_list<Subindex> &index);
279 const std::initializer_list<Subindex> &index
313 virtual const DataType&
operator()(
unsigned int offset)
const;
322 virtual DataType&
operator()(
unsigned int offset);
352 const DataType &targetValue,
353 const DataType &replacementValue
357 virtual std::string
toString()
const;
379 unsigned int blockSize,
391 const std::vector<int> &ranges,
392 unsigned int blockSize
406 const std::vector<int> &ranges,
407 unsigned int blockSize,
419 unsigned int blockSize
432 unsigned int blockSize,
454 const std::string &serialization,
530 unsigned int blockSize;
533 std::vector<DataType> data;
536 bool allowIndexOutOfBoundsAccess;
539 DataType defaultValue;
551 virtual void calculateDynamically(
const Index &index, DataType *block);
554 template<
typename DataType>
559 template<
typename DataType>
564 template<
typename DataType>
565 inline const std::vector<
571 template<
typename DataType>
576 template<
typename DataType>
578 return indexDescriptor.getRanges().size();
581 template<
typename DataType>
583 return indexDescriptor.getRanges();
586 template<
typename DataType>
590 return blockSize*indexDescriptor.getLinearIndex(
592 allowIndexOutOfBoundsAccess
596 template<
typename DataType>
599 return indexDescriptor;
602 template<
typename DataType>
606 return indexDescriptor.contains(index);
609 template<
typename DataType>
611 const std::vector<Index> &targetPatterns,
612 const std::vector<Index> &newPatterns
615 targetPatterns.size() == newPatterns.size(),
616 "AbstractProperty::reduce()",
617 "The size of targetPatterns '" << targetPatterns.size() <<
"'"
618 <<
" must be the same as the size of newPatterns '"
619 << newPatterns.size() <<
"'.",
624 const IndexTree &oldIndexTree = indexDescriptor.getIndexTree();
629 iterator != oldIndexTree.
cend();
633 int matchingPattern = -1;
634 for(
unsigned int n = 0; n < targetPatterns.size(); n++){
635 if(targetPatterns[n].equals(*iterator,
true)){
640 if(matchingPattern == -1)
643 Index newIndex = newPatterns[matchingPattern];
644 for(
unsigned int n = 0; n < newIndex.
getSize(); n++){
645 if(newIndex[n].isLabeledWildcard()){
658 newIndex[n] = (*iterator)[c];
666 "AbstractProperty::reduce()",
667 "Conflicting index reductions. The indices '"
668 << (*iterator).toString() <<
"' and '"
669 << reverseIndexMap.
get(newIndex).toString() <<
"' both"
670 <<
" reduce to '" << newIndex.
toString() <<
"'.",
673 indexMap.
add(newIndex, (*iterator));
674 reverseIndexMap.
add((*iterator), newIndex);
675 newIndexTree.
add(newIndex);
680 std::vector<DataType> newData;
681 for(
unsigned int n = 0; n < indexDescriptor.getSize()*blockSize; n++)
682 newData.push_back(0.);
687 iterator != indexMap.
cend();
690 const Index &oldIndex = iterator.getCurrentIndex();
691 const Index &newIndex = *iterator;
692 for(
unsigned int n = 0; n < blockSize; n++){
698 blockSize*indexDescriptor.getLinearIndex(
705 indexDescriptor = newIndexDescriptor;
709 template<
typename DataType>
712 const IndexTree &oldIndexTree = indexDescriptor.getIndexTree();
717 iterator != oldIndexTree.
cend();
720 std::vector<Index> components = (*iterator).
split();
722 components.size() == 2,
723 "AbstractProperty<DataType>::hermitianConjugate()",
724 "Invalid Index structure. Unable to performorm the"
725 <<
" Hermitian conjugation because the Index '"
726 << (*iterator).toString() <<
"' is not a compound"
727 <<
" Index with two component Indices.",
730 newIndexTree.
add({components[1], components[0]});
735 std::vector<DataType> newData;
736 for(
unsigned int n = 0; n < indexDescriptor.getSize()*blockSize; n++)
737 newData.push_back(0.);
741 iterator != oldIndexTree.
cend();
744 for(
unsigned int n = 0; n < blockSize; n++){
745 std::vector<Index> components = (*iterator).split();
748 {components[1], components[0]}
752 blockSize*indexDescriptor.getLinearIndex(
760 indexDescriptor = newIndexDescriptor;
764 template<
typename DataType>
773 std::vector<SparseMatrix<DataType>> sparseMatrices;
774 for(
unsigned int n = 0; n < blockSize; n++){
775 sparseMatrices.push_back(
783 const IndexTree &indexTree = indexDescriptor.getIndexTree();
786 iterator != indexTree.
cend();
789 std::vector<Index> components = (*iterator).
split();
791 components.size() == 2,
792 "AbstractProperty<DataType>::toSparseMatrices()",
793 "Invalid Index structure. Unable to convert to"
794 <<
"SparseMatrices because the Index '"
795 << (*iterator).toString() <<
"' is not a compound"
796 <<
" Index with two component Indices.",
804 = blockSize*indexDescriptor.getLinearIndex(*iterator);
805 for(
unsigned int n = 0; n < blockSize; n++)
806 sparseMatrices[n].add(row, column, data[offset + n]);
808 for(
unsigned int n = 0; n < blockSize; n++)
809 sparseMatrices[n].construct();
811 return sparseMatrices;
814 template<
typename DataType>
819 int indexOffset = getOffset(index);
823 return data[indexOffset + offset];
826 template<
typename DataType>
831 int indexOffset = getOffset(index);
833 static DataType defaultValueNonConst;
834 defaultValueNonConst = defaultValue;
835 return defaultValueNonConst;
838 return data[indexOffset + offset];
842 template<
typename DataType>
844 const std::initializer_list<Subindex> &index
846 return operator()(index, 0);
849 template<
typename DataType>
851 const std::initializer_list<Subindex> &index
853 return operator()(index, 0);
870 template<
typename DataType>
877 template<
typename DataType>
882 template<
typename DataType>
884 bool allowIndexOutOfBoundsAccess
886 this->allowIndexOutOfBoundsAccess = allowIndexOutOfBoundsAccess;
889 template<
typename DataType>
891 const DataType &defaultValue
893 this->defaultValue = defaultValue;
896 template<
typename DataType>
898 const DataType &targetValue,
899 const DataType &replacementValue
902 if(targetValue != targetValue){
903 for(
unsigned int n = 0; n < data.size(); n++)
904 if(data[n] != data[n])
905 data[n] = replacementValue;
910 for(
unsigned int n = 0; n < data.size(); n++)
911 if(data[n] == targetValue)
912 data[n] = replacementValue;
915 template<
typename DataType>
917 return "AbstractProperty";
920 template<
typename DataType>
926 j[
"id"] =
"AbstractProperty";
927 j[
"indexDescriptor"] = nlohmann::json::parse(
928 indexDescriptor.serialize(mode)
930 j[
"blockSize"] = blockSize;
931 for(
unsigned int n = 0; n < data.size(); n++){
941 j[
"allowIndexOutOfBoundsAccess"] = allowIndexOutOfBoundsAccess;
948 "AbstractProperty<DataType>::serialize()",
949 "Only Serializable::Mode::JSON is supported yet.",
955 template<
typename DataType>
959 allowIndexOutOfBoundsAccess =
false;
962 template<
typename DataType>
964 unsigned int blockSize
968 this->blockSize = blockSize;
970 unsigned int size = blockSize;
972 for(
unsigned int n = 0; n < size; n++)
975 allowIndexOutOfBoundsAccess =
false;
978 template<
typename DataType>
980 unsigned int blockSize,
985 this->blockSize = blockSize;
987 unsigned int size = blockSize;
988 this->data.reserve(size);
989 for(
unsigned int n = 0; n < size; n++)
990 this->data.push_back(data[n]);
992 allowIndexOutOfBoundsAccess =
false;
995 template<
typename DataType>
997 const std::vector<int> &ranges,
998 unsigned int blockSize
1000 indexDescriptor(ranges)
1002 this->blockSize = blockSize;
1004 unsigned int size = blockSize*indexDescriptor.getSize();
1006 for(
unsigned int n = 0; n < size; n++)
1007 data.push_back(DataType(0.));
1009 allowIndexOutOfBoundsAccess =
false;
1012 template<
typename DataType>
1014 const std::vector<int> &ranges,
1015 unsigned int blockSize,
1016 const DataType *data
1018 indexDescriptor(ranges)
1020 this->blockSize = blockSize;
1022 unsigned int size = blockSize*indexDescriptor.getSize();
1023 this->data.reserve(size);
1024 for(
unsigned int n = 0; n < size; n++)
1025 this->data.push_back(data[n]);
1027 allowIndexOutOfBoundsAccess =
false;
1030 template<
typename DataType>
1033 unsigned int blockSize
1035 indexDescriptor(indexTree)
1039 "AbstractProperty::AbstractProperty()",
1040 "Linear map not constructed for the IndexTree.",
1041 "Call IndexTree::generateLinearIndex() before passing the"
1042 " IndexTree to the AbstractProperty constructor."
1045 this->blockSize = blockSize;
1047 unsigned int size = blockSize*indexDescriptor.getSize();
1049 for(
unsigned int n = 0; n < size; n++)
1050 data.push_back(DataType(0.));
1052 allowIndexOutOfBoundsAccess =
false;
1055 template<
typename DataType>
1058 unsigned int blockSize,
1059 const DataType *data
1061 indexDescriptor(indexTree)
1065 "AbstractProperty::AbstractProperty()",
1066 "Linear map not constructed for the IndexTree.",
1067 "Call IndexTree::generateLinearIndex() before passing the"
1068 " IndexTree to the AbstractProperty constructor."
1071 this->blockSize = blockSize;
1073 unsigned int size = blockSize*indexDescriptor.getSize();
1074 this->data.reserve(size);
1075 for(
unsigned int n = 0; n < size; n++)
1076 this->data.push_back(data[n]);
1078 allowIndexOutOfBoundsAccess =
false;
1081 template<
typename DataType>
1085 indexDescriptor(abstractProperty.indexDescriptor)
1087 blockSize = abstractProperty.blockSize;
1089 data = abstractProperty.data;
1091 allowIndexOutOfBoundsAccess
1092 = abstractProperty.allowIndexOutOfBoundsAccess;
1095 template<
typename DataType>
1099 indexDescriptor(std::move(abstractProperty.indexDescriptor))
1101 blockSize = abstractProperty.blockSize;
1103 data = abstractProperty.data;
1105 allowIndexOutOfBoundsAccess
1106 = abstractProperty.allowIndexOutOfBoundsAccess;
1109 template<
typename DataType>
1111 const std::string &serialization,
1115 Serializable::extract(serialization, mode,
"indexDescriptor"),
1120 validate(serialization,
"AbstractProperty", mode),
1121 "AbstractProperty::AbstractProperty()",
1122 "Unable to parse string as AbstractProperty '" << serialization
1130 nlohmann::json j = nlohmann::json::parse(serialization);
1131 blockSize = j.at(
"blockSize").get<
unsigned int>();
1132 nlohmann::json d = j.at(
"data");
1134 nlohmann::json::iterator it = d.begin();
1139 Serializable::deserialize<DataType>(
1140 it->get<std::string>(),
1146 allowIndexOutOfBoundsAccess = j.at(
1147 "allowIndexOutOfBoundsAccess"
1149 defaultValue = Serializable::deserialize<DataType>(
1150 j.at(
"defaultValue").get<std::string>(),
1154 catch(nlohmann::json::exception &e){
1156 "AbstractProperty::AbstractProperty()",
1157 "Unable to parse string as AbstractProperty '"
1158 << serialization <<
"'.",
1166 "AbstractProperty::AbstractProperty()",
1167 "Only Serializable::Mode::JSON is supported yet.",
1173 template<
typename DataType>
1177 template<
typename DataType>
1182 indexDescriptor = rhs.indexDescriptor;
1184 blockSize = rhs.blockSize;
1188 allowIndexOutOfBoundsAccess = rhs.allowIndexOutOfBoundsAccess;
1194 template<
typename DataType>
1199 indexDescriptor = std::move(rhs.indexDescriptor);
1201 blockSize = rhs.blockSize;
1205 allowIndexOutOfBoundsAccess = rhs.allowIndexOutOfBoundsAccess;
1211 template<
typename DataType>
1215 indexDescriptor == rhs.indexDescriptor,
1216 "AbstractProperty::operator+=()",
1217 "Incompatible Properties. The Properties does not have the"
1218 <<
" same index structure.",
1223 blockSize == rhs.blockSize,
1224 "AbstractProperty::operator+=()",
1225 "Incompatible Properties. The Properties does not have the"
1226 <<
" same block size.",
1231 allowIndexOutOfBoundsAccess == rhs.allowIndexOutOfBoundsAccess,
1232 "AbstractProperty::operator+=()",
1233 "Incompatible Properties. The Properties differ in their"
1234 <<
" 'index out of bounds behavior'.",
1235 "Use AbstractProperty::setAllowIndexOutOfBoundsAccess() to set"
1236 <<
" the 'index out of bounds' behavior."
1239 if(allowIndexOutOfBoundsAccess){
1241 defaultValue == rhs.defaultValue,
1242 "AbstractProperty::operator+=()",
1243 "Incompatible Properties. The Properties differ in"
1244 <<
" their default values.",
1245 "Use AbstractProperty::setDefaultValue() to set the"
1246 <<
" default value."
1251 data.size() == rhs.data.size(),
1252 "AbstractProperty::operator+=()",
1253 "Incompatible Properties. The Properties have different data"
1255 "This should never happen, contact the developer."
1258 for(
unsigned int n = 0; n < data.size(); n++)
1259 data[n] += rhs.data[n];
1264 template<
typename DataType>
1270 indexDescriptor == rhs.indexDescriptor,
1271 "AbstractProperty::operator-=()",
1272 "Incompatible Properties. The Properties does not have the"
1273 <<
" same index structure.",
1278 blockSize == rhs.blockSize,
1279 "AbstractProperty::operator-=()",
1280 "Incompatible Properties. The Properties does not have the"
1281 <<
" same block size.",
1286 allowIndexOutOfBoundsAccess == rhs.allowIndexOutOfBoundsAccess,
1287 "AbstractProperty::operator-=()",
1288 "Incompatible Properties. The Properties differ in their"
1289 <<
" 'index out of bounds behavior'.",
1290 "Use AbstractProperty::setAllowIndexOutOfBoundsAccess() to set"
1291 <<
" the 'index out of bounds' behavior."
1294 if(allowIndexOutOfBoundsAccess){
1296 defaultValue == rhs.defaultValue,
1297 "AbstractProperty::operator-=()",
1298 "Incompatible Properties. The Properties differ in"
1299 <<
" their default values.",
1300 "Use AbstractProperty::setDefaultValue() to set the"
1301 <<
" default value."
1306 data.size() == rhs.data.size(),
1307 "AbstractProperty::operator-=()",
1308 "Incompatible Properties. The Properties have different data"
1310 "This should never happen, contact the developer."
1313 for(
unsigned int n = 0; n < data.size(); n++)
1314 data[n] -= rhs.data[n];
1319 template<
typename DataType>
1324 if(allowIndexOutOfBoundsAccess)
1325 defaultValue *= rhs;
1327 for(
unsigned int n = 0; n < data.size(); n++)
1333 template<
typename DataType>
1337 if(allowIndexOutOfBoundsAccess)
1338 defaultValue /= rhs;
1340 for(
unsigned int n = 0; n < data.size(); n++)
1346 template<
typename DataType>
1352 "AbstractProperty::calculateDynamically()",
1353 "This Property does not support dynamic calculation.",