// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #include "../general/array.hpp" #include "vector.hpp" #include "blockvector.hpp" namespace mfem { void BlockVector::SetBlocks() { for (int i = 0; i < numBlocks; ++i) { blocks[i].MakeRef(*this, blockOffsets[i], BlockSize(i)); } } BlockVector::BlockVector(): Vector(), numBlocks(0), blockOffsets(NULL), blocks(NULL) { } //! Standard constructor BlockVector::BlockVector(const Array & bOffsets): Vector(bOffsets.Last()), numBlocks(bOffsets.Size()-1), blockOffsets(bOffsets.GetData()) { blocks = new Vector[numBlocks]; SetBlocks(); } BlockVector::BlockVector(const Array & bOffsets, MemoryType mt) : Vector(bOffsets.Last(), mt), numBlocks(bOffsets.Size()-1), blockOffsets(bOffsets.GetData()) { blocks = new Vector[numBlocks]; SetBlocks(); } //! Copy constructor BlockVector::BlockVector(const BlockVector & v): Vector(v), numBlocks(v.numBlocks), blockOffsets(v.blockOffsets) { blocks = new Vector[numBlocks]; SetBlocks(); } //! View constructor BlockVector::BlockVector(double *data, const Array & bOffsets): Vector(data, bOffsets.Last()), numBlocks(bOffsets.Size()-1), blockOffsets(bOffsets.GetData()) { blocks = new Vector[numBlocks]; SetBlocks(); } BlockVector::BlockVector(Vector &v, const Array &bOffsets) : Vector(), numBlocks(bOffsets.Size()-1), blockOffsets(bOffsets.GetData()) { MakeRef(v, 0, blockOffsets[numBlocks]); blocks = new Vector[numBlocks]; SetBlocks(); } BlockVector::BlockVector(Vector &v, int offset, const Array &bOffsets) : Vector(), numBlocks(bOffsets.Size()-1), blockOffsets(bOffsets.GetData()) { MakeRef(v, offset, blockOffsets[numBlocks]); blocks = new Vector[numBlocks]; SetBlocks(); } void BlockVector::Update(double *data, const Array & bOffsets) { NewDataAndSize(data, bOffsets.Last()); blockOffsets = bOffsets.GetData(); if (numBlocks != bOffsets.Size()-1) { delete [] blocks; numBlocks = bOffsets.Size()-1; blocks = new Vector[numBlocks]; } SetBlocks(); } void BlockVector::Update(Vector & data, const Array & bOffsets) { blockOffsets = bOffsets.GetData(); if (numBlocks != bOffsets.Size()-1) { delete [] blocks; numBlocks = bOffsets.Size()-1; blocks = new Vector[numBlocks]; } for (int i = 0; i < numBlocks; ++i) { blocks[i].MakeRef(data, blockOffsets[i], BlockSize(i)); } MakeRef(data, 0, blockOffsets[numBlocks]); } void BlockVector::Update(const Array &bOffsets) { Update(bOffsets, data.GetMemoryType()); } void BlockVector::Update(const Array &bOffsets, MemoryType mt) { blockOffsets = bOffsets.GetData(); if (OwnsData() && data.GetMemoryType() == mt) { // check if 'bOffsets' agree with the 'blocks' if (bOffsets.Size() == numBlocks+1) { if (numBlocks == 0) { return; } if (Size() == bOffsets.Last()) { for (int i = numBlocks - 1; true; i--) { if (i < 0) { return; } if (blocks[i].Size() != bOffsets[i+1] - bOffsets[i]) { break; } MFEM_ASSERT(blocks[i].GetData() == data + bOffsets[i], "invalid blocks[" << i << ']'); } } } } else { Destroy(); } SetSize(bOffsets.Last(), mt); if (numBlocks != bOffsets.Size()-1) { delete [] blocks; numBlocks = bOffsets.Size()-1; blocks = new Vector[numBlocks]; } SetBlocks(); } BlockVector & BlockVector::operator=(const BlockVector & original) { if (numBlocks!=original.numBlocks) { mfem_error("Number of Blocks don't match in BlockVector::operator="); } for (int i(0); i <= numBlocks; ++i) { if (blockOffsets[i]!=original.blockOffsets[i]) { mfem_error("Size of Blocks don't match in BlockVector::operator="); } } Vector::operator=(original); return *this; } BlockVector & BlockVector::operator=(double val) { Vector::operator=(val); return *this; } //! Destructor BlockVector::~BlockVector() { delete [] blocks; } void BlockVector::GetBlockView(int i, Vector & blockView) { blockView.MakeRef(*this, blockOffsets[i], BlockSize(i)); } void BlockVector::SyncToBlocks() const { for (int i = 0; i < numBlocks; ++i) { blocks[i].SyncMemory(*this); } } void BlockVector::SyncFromBlocks() const { for (int i = 0; i < numBlocks; ++i) { blocks[i].SyncAliasMemory(*this); } } }