Ejemplo n.º 1
0
 /**
  * @brief deepCopy
  * @param forceNoAllocate
  * @return
  */
 virtual IDataArray::Pointer deepCopy(bool forceNoAllocate = false)
 {
   IDataArray::Pointer daCopy = createNewArray(getNumberOfTuples(), getComponentDimensions(), getName(), m_IsAllocated);
   if(m_IsAllocated == true && forceNoAllocate == false)
   {
     T* src = getPointer(0);
     void* dest = daCopy->getVoidPointer(0);
     size_t totalBytes = (getNumberOfTuples() * getNumberOfComponents() * sizeof(T));
     ::memcpy(dest, src, totalBytes);
   }
   return daCopy;
 }
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
IDataArray::Pointer ModifiedLambertProjectionArray::deepCopy(bool forceNoAllocate)
{
  ModifiedLambertProjectionArray::Pointer daCopyPtr = ModifiedLambertProjectionArray::New();
  if(forceNoAllocate == false)
  {
    daCopyPtr->resize(getNumberOfTuples());
    ModifiedLambertProjectionArray& daCopy = *daCopyPtr;
    for(size_t i = 0; i < getNumberOfTuples(); i++)
    {
      daCopy[i] = m_ModifiedLambertProjectionArray[i];
    }
  }
  return daCopyPtr;
}
Ejemplo n.º 3
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
IDataArray::Pointer StatsDataArray::deepCopy(bool forceNoAllocate)
{
  StatsDataArray::Pointer daCopyPtr = StatsDataArray::New();
  if(forceNoAllocate == false)
  {
    daCopyPtr->resize(getNumberOfTuples());
    StatsDataArray& daCopy = *daCopyPtr;
    for(size_t i = 0; i < getNumberOfTuples(); i++)
    {
      daCopy[i] = m_StatsDataArray[i];
    }
  }
  return daCopyPtr;
}
Ejemplo n.º 4
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
IDataArray::Pointer StatsDataArray::reorderCopy(QVector<size_t> newOrderMap)
{
  if( static_cast<size_t>(newOrderMap.size()) != getNumberOfTuples())
  {
    return IDataArray::Pointer();
  }
  StatsDataArray::Pointer daCopyPtr = StatsDataArray::New();
  daCopyPtr->resize(getNumberOfTuples());
  daCopyPtr->initializeWithZeros();
  StatsDataArray& daCopy = *daCopyPtr;
  for(size_t i = 0; i < getNumberOfTuples(); i++)
  {
    daCopy[newOrderMap[i]] = m_StatsDataArray[i];
  }

  return daCopyPtr;
}
Ejemplo n.º 5
0
    /**
     *
     * @param parentId
     * @return
     */
    virtual int writeH5Data(hid_t parentId, QVector<size_t> tDims)
    {
      if (m_Array == NULL)
      { return -85648; }
#if 0
      return H5DataArrayWriter<T>::writeArray(parentId, getName(), getNumberOfTuples(), getNumberOfComponents(), getRank(), getDims(), getClassVersion(), m_Array, getFullNameOfClass());
#else
      return H5DataArrayWriter::writeDataArray<Self>(parentId, this, tDims);
#endif
    }
Ejemplo n.º 6
0
 virtual IDataArray::Pointer reorderCopy(QVector<size_t> newOrderMap)
 {
   if(newOrderMap.size() != static_cast<QVector<size_t>::size_type>(getNumberOfTuples()))
   {
     return IDataArray::NullPointer();
   }
   IDataArray::Pointer daCopy = createNewArray(getNumberOfTuples(), getComponentDimensions(), getName(), m_IsAllocated);
   if(m_IsAllocated == true)
   {
     daCopy->initializeWithZeros();
     size_t chunkSize = getNumberOfComponents() * sizeof(T);
     for(size_t i = 0; i < getNumberOfTuples(); i++)
     {
       T* src = getPointer(i * getNumberOfComponents());
       void* dest = daCopy->getVoidPointer(newOrderMap[i] * getNumberOfComponents());
       ::memcpy(dest, src, chunkSize);
     }
   }
   return daCopy;
 }
Ejemplo n.º 7
0
 /**
  * @brief deepCopy
  * @param forceNoAllocate
  * @return
  */
 virtual IDataArray::Pointer deepCopy(bool forceNoAllocate = false)
 {
   StringDataArray::Pointer daCopy = StringDataArray::CreateArray(getNumberOfTuples(), getName());
   if(forceNoAllocate == false)
   {
     for(std::vector<QString>::size_type i = 0; i < m_Array.size(); ++i)
     {
       daCopy->setValue(i, m_Array[i]);
     }
   }
   return daCopy;
 }
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int ModifiedLambertProjectionArray::eraseTuples(QVector<size_t>& idxs)
{
  int err = 0;

  // If nothing is to be erased just return
  if(idxs.size() == 0)
  {
    return 0;
  }

  if (static_cast<size_t>(idxs.size()) >= getNumberOfTuples() )
  {
    resize(0);
    return 0;
  }

  // Sanity Check the Indices in the vector to make sure we are not trying to remove any indices that are
  // off the end of the array and return an error code.
  for(QVector<size_t>::size_type i = 0; i < idxs.size(); ++i)
  {
    if (idxs[i] >= static_cast<size_t>(m_ModifiedLambertProjectionArray.size()))
    {
      return -100;
    }
  }


  QVector<ModifiedLambertProjection::Pointer> replacement(m_ModifiedLambertProjectionArray.size() - idxs.size());
  qint32 idxsIndex = 0;
  size_t rIdx = 0;
  size_t count = static_cast<size_t>(m_ModifiedLambertProjectionArray.size());
  for(size_t dIdx = 0; dIdx < count; ++dIdx)
  {
    if (dIdx != idxs[idxsIndex])
    {
      replacement[rIdx] = m_ModifiedLambertProjectionArray[dIdx];
      ++rIdx;
    }
    else
    {
      ++idxsIndex;
      if (idxsIndex == idxs.size() )
      {
        idxsIndex--;
      }
    }
  }
  m_ModifiedLambertProjectionArray = replacement;
  return err;
}
Ejemplo n.º 9
0
    /**
     * @brief getInfoString
     * @return Returns a formatted string that contains general infomation about
     * the instance of the object.
     */
    virtual QString getInfoString(DREAM3D::InfoStringFormat format)
    {

      QLocale usa(QLocale::English, QLocale::UnitedStates);

      QString info;
      QTextStream ss (&info);
      if(format == DREAM3D::HtmlFormat)
      {
        ss << "<html><head></head>\n";
        ss << "<body>\n";
        ss << "<table cellpadding=\"4\" cellspacing=\"0\" border=\"0\">\n";
        ss << "<tbody>\n";
        ss << "<tr bgcolor=\"#D3D8E0\"><th colspan=2>Attribute Array Info</th></tr>";

        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Name:</th><td>" << getName() << "</td></tr>";


        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Type:</th><td> DataArray&lt;" << getTypeAsString() << "&gt;</td></tr>";
        QString numStr = usa.toString(static_cast<qlonglong>(getNumberOfTuples() ));
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Number of Tuples:</th><td>" << numStr << "</td></tr>";

        QString compDimStr = "(";
        for(int i = 0; i < m_CompDims.size(); i++)
        {
          compDimStr = compDimStr + QString::number(m_CompDims[i]);
          if(i < m_CompDims.size() - 1)
          {
            compDimStr = compDimStr + QString(", ");
          }
        }
        compDimStr = compDimStr + ")";
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Component Dimensions:</th><td>" << compDimStr << "</td></tr>";
        numStr = usa.toString(static_cast<qlonglong>(m_Size));
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Total Elements:</th><td>" << numStr << "</td></tr>";
        numStr = usa.toString(static_cast<qlonglong>(m_Size * sizeof(T)));
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Total Memory Required:</th><td>" << numStr << "</td></tr>";
        ss << "</tbody></table>\n";
        ss << "<br/>";
        ss << "</body></html>";
      }
      else
      {

      }
      return info;
    }
Ejemplo n.º 10
0
    /**
     * @brief Removes Tuples from the Array. If the size of the vector is Zero nothing is done. If the size of the
     * vector is greater than or Equal to the number of Tuples then the Array is Resized to Zero. If there are
     * indices that are larger than the size of the original (before erasing operations) then an error code (-100) is
     * returned from the program.
     * @param idxs The indices to remove
     * @return error code.
     */
    virtual int eraseTuples(QVector<size_t>& idxs)
    {

      int err = 0;

      // If nothing is to be erased just return
      if(idxs.size() == 0)
      {
        return 0;
      }
      size_t idxs_size = static_cast<size_t>(idxs.size());
      if (idxs_size >= getNumberOfTuples() )
      {
        resize(0);
        return 0;
      }

      // Sanity Check the Indices in the vector to make sure we are not trying to remove any indices that are
      // off the end of the array and return an error code.
      for(QVector<size_t>::size_type i = 0; i < idxs.size(); ++i)
      {
        if (idxs[i] >= static_cast<size_t>(m_Array.size())) { return -100; }
      }


      // Create a new Array to copy into
      std::vector<QString> newArray;
      std::vector<size_t>::size_type start = 0;
      for(QVector<QString>::size_type i = 0; i < m_Array.size(); ++i)
      {
        bool keep = true;
        for(QVector<size_t>::size_type j = start; j < idxs.size(); ++j)
        {
          if (static_cast<size_t>(i) == idxs[j]) { keep = false; break;}
        }
        if (keep)
        {
          newArray.push_back(m_Array[i]);
        }
      }
      m_Array = newArray;
      return err;
    }
Ejemplo n.º 11
0
    /**
     * @brief Removes Tuples from the m_Array. If the size of the vector is Zero nothing is done. If the size of the
     * vector is greater than or Equal to the number of Tuples then the m_Array is Resized to Zero. If there are
     * indices that are larger than the size of the original (before erasing operations) then an error code (-100) is
     * returned from the program.
     * @param idxs The indices to remove
     * @return error code.
     */
    virtual int eraseTuples(QVector<size_t>& idxs)
    {

      int err = 0;

      // If nothing is to be erased just return
      if(idxs.size() == 0)
      {
        return 0;
      }
      size_t idxs_size = static_cast<size_t>(idxs.size());
      if (idxs_size >= getNumberOfTuples() )
      {
        resize(0);
        return 0;
      }

      // Sanity Check the Indices in the vector to make sure we are not trying to remove any indices that are
      // off the end of the array and return an error code.
      for(QVector<size_t>::size_type i = 0; i < idxs.size(); ++i)
      {
        if (idxs[i] * m_NumComponents > m_MaxId) { return -100; }
      }

      // Calculate the new size of the array to copy into
      size_t newSize = (getNumberOfTuples() - idxs.size()) * m_NumComponents ;

      // Create a new m_Array to copy into
      T* newArray = (T*)malloc(newSize * sizeof(T));
      // Splat AB across the array so we know if we are copying the values or not
      ::memset(newArray, 0xAB, newSize * sizeof(T));

      // Keep the current Destination Pointer
      T* currentDest = newArray;
      size_t j = 0;
      int k = 0;
      // Find the first chunk to copy by walking the idxs array until we get an
      // index that is NOT a continuous increment from the start
      for (k = 0; k < idxs.size(); ++k)
      {
        if(j == idxs[k])
        {
          ++j;
        }
        else
        {
          break;
        }
      }

      if(k == idxs.size()) // Only front elements are being dropped
      {
        T* currentSrc = m_Array + (j * m_NumComponents);
        ::memcpy(currentDest, currentSrc, (getNumberOfTuples() - idxs.size()) * m_NumComponents * sizeof(T));
        _deallocate(); // We are done copying - delete the current m_Array
        m_Size = newSize;
        m_Array = newArray;
        m_OwnsData = true;
        m_MaxId = newSize - 1;
        m_IsAllocated = true;
        return 0;
      }

      QVector<size_t> srcIdx(idxs.size() + 1);
      QVector<size_t> destIdx(idxs.size() + 1);
      QVector<size_t> copyElements(idxs.size() + 1);
      srcIdx[0] = 0;
      destIdx[0] = 0;
      copyElements[0] = (idxs[0] - 0) * m_NumComponents;

      for (int i = 1; i < srcIdx.size(); ++i)
      {
        srcIdx[i] = (idxs[i - 1] + 1) * m_NumComponents;

        if(i < srcIdx.size() - 1)
        {
          copyElements[i] = (idxs[i] - idxs[i - 1] - 1) * m_NumComponents;
        }
        else
        {
          copyElements[i] = (getNumberOfTuples() - idxs[i - 1] - 1) * m_NumComponents;
        }
        destIdx[i] = copyElements[i - 1] + destIdx[i - 1];
      }

      // Copy the data
      for (int i = 0; i < srcIdx.size(); ++i)
      {
        currentDest = newArray + destIdx[i];
        T* currentSrc = m_Array + srcIdx[i];
        size_t bytes = copyElements[i] * sizeof(T);
        ::memcpy(currentDest, currentSrc, bytes);
      }

      // We are done copying - delete the current m_Array
      _deallocate();

      // Allocation was successful.  Save it.
      m_Size = newSize;
      m_Array = newArray;
      // This object has now allocated its memory and owns it.
      m_OwnsData = true;
      m_IsAllocated = true;
      m_MaxId = newSize - 1;

      return err;
    }
Ejemplo n.º 12
0
    /**
     * @brief getInfoString
     * @return Returns a formatted string that contains general infomation about
     * the instance of the object.
     */
    virtual QString getInfoString(DREAM3D::InfoStringFormat format)
    {
      QString info;
      QTextStream ss (&info);
      if(format == DREAM3D::HtmlFormat)
      {
        ss << "<html><head></head>\n";
        ss << "<body>\n";
        ss << "<table cellpadding=\"4\" cellspacing=\"0\" border=\"0\">\n";
        ss << "<tbody>\n";
        ss << "<tr bgcolor=\"#D3D8E0\"><th colspan=2>Attribute Array Info</th></tr>";
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Name:</th><td>" << getName() << "</td></tr>";
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Type:</th><td>" << getTypeAsString() << "</td></tr>";
        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Number of Tuples:</th><td>" << getNumberOfTuples() << "</td></tr>";

        //        QString compDimStr = "(";
        //        for(int i = 0; i < m_CompDims.size(); i++)
        //        {
        //          compDimStr = compDimStr + QString::number(m_CompDims[i]);
        //          if(i < m_CompDims.size() - 1) {
        //             compDimStr = compDimStr + QString(", ");
        //          }
        //        }
        //        compDimStr = compDimStr + ")";
        //        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Component Dimensions:</th><td>" << compDimStr << "</td></tr>";
        //        ss << "<tr bgcolor=\"#C3C8D0\"><th align=\"right\">Total Elements:</th><td>" << m_Size << "</td></tr>";

        ss << "</tbody></table>\n";
        ss << "<br/>";
        ss << "</body></html>";
      }
      else
      {

      }
      return info;
    }
Ejemplo n.º 13
0
TEST_F(InSituMesh, DISABLED_MappedMeshSourceRoundtrip)
#endif
{
    // TODO Add more comparison criteria

    ASSERT_TRUE(mesh != nullptr);
    std::string test_data_file(BaseLib::BuildInfo::tests_tmp_path + "/MappedMeshSourceRoundtrip.vtu");

    // -- Test VtkMappedMeshSource, i.e. OGS mesh to VTK mesh
    vtkNew<MeshLib::VtkMappedMeshSource> vtkSource;
    vtkSource->SetMesh(mesh);
    vtkSource->Update();
    vtkUnstructuredGrid* output = vtkSource->GetOutput();

    // Point and cell numbers
    ASSERT_EQ((subdivisions+1)*(subdivisions+1)*(subdivisions+1), output->GetNumberOfPoints());
    ASSERT_EQ(subdivisions*subdivisions*subdivisions, output->GetNumberOfCells());

    // Point data arrays
    vtkDataArray* pointDoubleArray = output->GetPointData()->GetScalars("PointDoubleProperty");
    ASSERT_EQ(pointDoubleArray->GetSize(), mesh->getNumberOfNodes());
    ASSERT_EQ(pointDoubleArray->GetComponent(0, 0), 1.0);
    double* range = pointDoubleArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1.0 + mesh->getNumberOfNodes() - 1.0);

    vtkDataArray* pointIntArray = output->GetPointData()->GetScalars("PointIntProperty");
    ASSERT_EQ(pointIntArray->GetSize(), mesh->getNumberOfNodes());
    ASSERT_EQ(pointIntArray->GetComponent(0, 0), 1.0);
    range = pointIntArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1 + mesh->getNumberOfNodes() - 1);

    vtkDataArray* pointUnsignedArray = output->GetPointData()->GetScalars("PointUnsignedProperty");
    ASSERT_EQ(pointUnsignedArray->GetSize(), mesh->getNumberOfNodes());
    ASSERT_EQ(pointUnsignedArray->GetComponent(0, 0), 1.0);
    range = pointUnsignedArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1 + mesh->getNumberOfNodes() - 1);

    // Cell data arrays
    vtkDataArray* cellDoubleArray = output->GetCellData()->GetScalars("CellDoubleProperty");
    ASSERT_EQ(cellDoubleArray->GetSize(), mesh->getNumberOfElements());
    ASSERT_EQ(cellDoubleArray->GetComponent(0, 0), 1.0);
    range = cellDoubleArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1.0 + mesh->getNumberOfElements() - 1.0);

    vtkDataArray* cellIntArray = output->GetCellData()->GetScalars("CellIntProperty");
    ASSERT_EQ(cellIntArray->GetSize(), mesh->getNumberOfElements());
    ASSERT_EQ(cellIntArray->GetComponent(0, 0), 1.0);
    range = cellIntArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1 + mesh->getNumberOfElements() - 1);

    vtkDataArray* cellUnsignedArray = output->GetCellData()->GetScalars("CellUnsignedProperty");
    ASSERT_EQ(cellUnsignedArray->GetSize(), mesh->getNumberOfElements());
    ASSERT_EQ(cellUnsignedArray->GetComponent(0, 0), 1.0);
    range = cellUnsignedArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], 1 + mesh->getNumberOfElements() - 1);

    // Field data arrays
    vtkDataArray* fieldDoubleArray = vtkDataArray::SafeDownCast(
        output->GetFieldData()->GetAbstractArray("FieldDoubleProperty"));
    ASSERT_EQ(fieldDoubleArray->GetSize(), mesh->getNumberOfElements() * 2);
    ASSERT_EQ(fieldDoubleArray->GetComponent(0, 0), 1.0);
    range = fieldDoubleArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1],  mesh->getNumberOfElements() * 2);

    vtkDataArray* fieldIntArray = vtkDataArray::SafeDownCast(
        output->GetFieldData()->GetAbstractArray("FieldIntProperty"));
    ASSERT_EQ(fieldIntArray->GetSize(), mesh->getNumberOfElements() * 2);
    ASSERT_EQ(fieldIntArray->GetComponent(0, 0), 1.0);
    range = fieldIntArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], mesh->getNumberOfElements() * 2);

    vtkDataArray* fieldUnsignedArray = vtkDataArray::SafeDownCast(
        output->GetFieldData()->GetAbstractArray("FieldUnsignedProperty"));
    ASSERT_EQ(fieldUnsignedArray->GetSize(), mesh->getNumberOfElements() * 2);
    ASSERT_EQ(fieldUnsignedArray->GetComponent(0, 0), 1.0);
    range = fieldUnsignedArray->GetRange(0);
    ASSERT_EQ(range[0], 1.0);
    ASSERT_EQ(range[1], mesh->getNumberOfElements() * 2);

    // -- Write VTK mesh to file (in all combinations of binary, appended and compressed)
    // TODO: atm vtkXMLWriter::Ascii fails
    for(int dataMode : { vtkXMLWriter::Appended, vtkXMLWriter::Binary })
    {
        for(bool compressed : { true, false })
        {
            if(dataMode == vtkXMLWriter::Ascii && compressed)
                continue;
            MeshLib::IO::VtuInterface vtuInterface(mesh, dataMode, compressed);
            ASSERT_TRUE(vtuInterface.writeToFile(test_data_file));

            // -- Read back VTK mesh
            vtkSmartPointer<vtkXMLUnstructuredGridReader> reader =
                vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
            reader->SetFileName(test_data_file.c_str());
            reader->Update();
            vtkUnstructuredGrid *vtkMesh = reader->GetOutput();

            // Both VTK meshes should be identical
            ASSERT_EQ(vtkMesh->GetNumberOfPoints(), output->GetNumberOfPoints());
            ASSERT_EQ(vtkMesh->GetNumberOfCells(), output->GetNumberOfCells());
            ASSERT_EQ(vtkMesh->GetFieldData()->GetNumberOfArrays(), output->GetFieldData()->GetNumberOfArrays());
            ASSERT_EQ(vtkMesh->GetPointData()->GetScalars("PointDoubleProperty")->GetNumberOfTuples(),
                pointDoubleArray->GetNumberOfTuples());
            ASSERT_EQ(vtkMesh->GetPointData()->GetScalars("PointIntProperty")->GetNumberOfTuples(),
                pointIntArray->GetNumberOfTuples());
            ASSERT_EQ(vtkMesh->GetPointData()->GetScalars("PointUnsignedProperty")->GetNumberOfTuples(),
                pointUnsignedArray->GetNumberOfTuples());
            ASSERT_EQ(vtkMesh->GetCellData()->GetScalars("CellDoubleProperty")->GetNumberOfTuples(),
                cellDoubleArray->GetNumberOfTuples());
            ASSERT_EQ(vtkMesh->GetCellData()->GetScalars("CellIntProperty")->GetNumberOfTuples(),
                cellIntArray->GetNumberOfTuples());
            ASSERT_EQ(vtkMesh->GetCellData()->GetScalars("CellUnsignedProperty")->GetNumberOfTuples(),
                      cellUnsignedArray->GetNumberOfTuples());

            auto get_field_data =
                [&vtkMesh](std::string const array_name) -> vtkDataArray* {
                return vtkDataArray::SafeDownCast(
                    vtkMesh->GetFieldData()->GetAbstractArray(
                        array_name.c_str()));
            };

            ASSERT_EQ(
                get_field_data("FieldDoubleProperty")->GetNumberOfTuples(),
                fieldDoubleArray->GetNumberOfTuples());
            ASSERT_EQ(get_field_data("FieldIntProperty")->GetNumberOfTuples(),
                      fieldIntArray->GetNumberOfTuples());
            ASSERT_EQ(
                get_field_data("FieldUnsignedProperty")->GetNumberOfTuples(),
                fieldUnsignedArray->GetNumberOfTuples());

            // Both OGS meshes should be identical
            auto newMesh = std::unique_ptr<MeshLib::Mesh>{MeshLib::VtkMeshConverter::convertUnstructuredGrid(vtkMesh)};
            ASSERT_EQ(mesh->getNumberOfNodes(), newMesh->getNumberOfNodes());
            ASSERT_EQ(mesh->getNumberOfElements(), newMesh->getNumberOfElements());

            // Both properties should be identical
            auto meshProperties = mesh->getProperties();
            auto newMeshProperties = newMesh->getProperties();
            ASSERT_EQ(newMeshProperties.hasPropertyVector("PointDoubleProperty"),
                meshProperties.hasPropertyVector("PointDoubleProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("PointIntProperty"),
                      meshProperties.hasPropertyVector("PointIntProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("PointUnsignedProperty"),
                meshProperties.hasPropertyVector("PointUnsignedProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("CellDoubleProperty"),
                meshProperties.hasPropertyVector("CellDoubleProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("CellIntProperty"),
                meshProperties.hasPropertyVector("CellIntProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("CellUnsignedProperty"),
                meshProperties.hasPropertyVector("CellUnsignedProperty"));

            ASSERT_EQ(newMeshProperties.hasPropertyVector("FieldDoubleProperty"),
                meshProperties.hasPropertyVector("FieldDoubleProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("FieldIntProperty"),
                meshProperties.hasPropertyVector("FieldIntProperty"));
            ASSERT_EQ(newMeshProperties.hasPropertyVector("FieldUnsignedProperty"),
                meshProperties.hasPropertyVector("FieldUnsignedProperty"));

            ASSERT_EQ(newMeshProperties.hasPropertyVector("MaterialIDs"),
                meshProperties.hasPropertyVector("MaterialIDs"));

            // Check some properties on equality
            auto const* const doubleProps =
                meshProperties.getPropertyVector<double>("PointDoubleProperty");
            auto const* const newDoubleProps =
                newMeshProperties.getPropertyVector<double>(
                    "PointDoubleProperty");
            ASSERT_EQ(newDoubleProps->getNumberOfComponents(),
                      doubleProps->getNumberOfComponents());
            ASSERT_EQ(newDoubleProps->getNumberOfTuples(),
                      doubleProps->getNumberOfTuples());
            ASSERT_EQ(newDoubleProps->size(), doubleProps->size());
            for (std::size_t i = 0; i < doubleProps->size(); i++)
                ASSERT_EQ((*newDoubleProps)[i], (*doubleProps)[i]);

            auto unsignedProps = meshProperties.getPropertyVector<unsigned>(
                "CellUnsignedProperty");
            auto newUnsignedIds = newMeshProperties.getPropertyVector<unsigned>(
                "CellUnsignedProperty");

            ASSERT_EQ(newUnsignedIds->getNumberOfComponents(),
                      unsignedProps->getNumberOfComponents());
            ASSERT_EQ(newUnsignedIds->getNumberOfTuples(),
                      unsignedProps->getNumberOfTuples());
            ASSERT_EQ(newUnsignedIds->size(), unsignedProps->size());
            for (std::size_t i = 0; i < unsignedProps->size(); i++)
                ASSERT_EQ((*newUnsignedIds)[i], (*unsignedProps)[i]);

            {   // Field data
                auto p =
                    meshProperties.getPropertyVector<int>("FieldIntProperty");
                auto new_p = newMeshProperties.getPropertyVector<int>(
                    "FieldIntProperty");

                ASSERT_EQ(new_p->getNumberOfComponents(),
                          p->getNumberOfComponents());
                ASSERT_EQ(new_p->getNumberOfTuples(), p->getNumberOfTuples());
                ASSERT_EQ(new_p->size(), p->size());
                for (std::size_t i = 0; i < unsignedProps->size(); i++)
                    ASSERT_EQ((*newUnsignedIds)[i], (*unsignedProps)[i]);
            }

            auto const* const materialIds =
                meshProperties.getPropertyVector<int>("MaterialIDs");
            auto const* const newMaterialIds =
                newMeshProperties.getPropertyVector<int>("MaterialIDs");
            ASSERT_EQ(newMaterialIds->getNumberOfComponents(),
                      materialIds->getNumberOfComponents());
            ASSERT_EQ(newMaterialIds->getNumberOfTuples(),
                      materialIds->getNumberOfTuples());
            ASSERT_EQ(newMaterialIds->size(), materialIds->size());
            for (std::size_t i = 0; i < materialIds->size(); i++)
                ASSERT_EQ((*newMaterialIds)[i], (*materialIds)[i]);
        }
    }
}