Files
mfem/fem/fespacehierarchy.cpp
T
2020-04-18 18:07:43 -07:00

190 lines
6.2 KiB
C++

// Copyright (c) 2010-2020, 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 "fespacehierarchy.hpp"
#include "transfer.hpp"
namespace mfem
{
FiniteElementSpaceHierarchy::FiniteElementSpaceHierarchy(Mesh* mesh,
FiniteElementSpace* fespace,
bool ownM, bool ownFES)
{
meshes.Append(mesh);
fespaces.Append(fespace);
ownedMeshes.Append(ownM);
ownedFES.Append(ownFES);
}
FiniteElementSpaceHierarchy::~FiniteElementSpaceHierarchy()
{
for (int i = 0; i < meshes.Size(); ++i)
{
if (ownedFES[i])
{
delete fespaces[i];
}
if (ownedMeshes[i])
{
delete meshes[i];
}
}
for (int i = 0; i < prolongations.Size(); ++i)
{
if (ownedProlongations[i])
{
delete prolongations[i];
}
}
fespaces.DeleteAll();
meshes.DeleteAll();
prolongations.DeleteAll();
}
int FiniteElementSpaceHierarchy::GetNumLevels() const { return meshes.Size(); }
int FiniteElementSpaceHierarchy::GetFinestLevelIndex() const { return GetNumLevels() - 1; }
void FiniteElementSpaceHierarchy::AddLevel(Mesh* mesh,
FiniteElementSpace* fespace,
Operator* prolongation,
bool ownM, bool ownFES,
bool ownP)
{
meshes.Append(mesh);
fespaces.Append(fespace);
prolongations.Append(prolongation);
ownedMeshes.Append(ownM);
ownedFES.Append(ownFES);
ownedProlongations.Append(ownP);
}
void FiniteElementSpaceHierarchy::AddUniformlyRefinedLevel(int dim,
int ordering)
{
MFEM_VERIFY(GetNumLevels() > 0, "There is no level which can be refined");
Mesh* mesh = new Mesh(*GetFinestFESpace().GetMesh());
mesh->UniformRefinement();
FiniteElementSpace& coarseFEspace = GetFinestFESpace();
FiniteElementSpace* fineFEspace =
new FiniteElementSpace(mesh, coarseFEspace.FEColl(), dim, ordering);
Operator* P = new TransferOperator(coarseFEspace, *fineFEspace);
AddLevel(mesh, fineFEspace, P, true, true, true);
}
void FiniteElementSpaceHierarchy::AddOrderRefinedLevel(FiniteElementCollection*
fec, int dim,
int ordering)
{
MFEM_VERIFY(GetNumLevels() > 0, "There is no level which can be refined");
Mesh* mesh = GetFinestFESpace().GetMesh();
FiniteElementSpace* newFEspace =
new FiniteElementSpace(mesh, fec, dim, ordering);
Operator* P = new TransferOperator(GetFinestFESpace(), *newFEspace);
AddLevel(mesh, newFEspace, P, false, true, true);
}
const FiniteElementSpace& FiniteElementSpaceHierarchy::GetFESpaceAtLevel(
int level) const
{
MFEM_ASSERT(level < fespaces.Size(),
"FE space at given level does not exist.");
return *fespaces[level];
}
FiniteElementSpace& FiniteElementSpaceHierarchy::GetFESpaceAtLevel(int level)
{
MFEM_ASSERT(level < fespaces.Size(),
"FE space at given level does not exist.");
return *fespaces[level];
}
const FiniteElementSpace& FiniteElementSpaceHierarchy::GetFinestFESpace() const
{
return GetFESpaceAtLevel(GetFinestLevelIndex());
}
FiniteElementSpace& FiniteElementSpaceHierarchy::GetFinestFESpace()
{
return GetFESpaceAtLevel(GetFinestLevelIndex());
}
Operator* FiniteElementSpaceHierarchy::GetProlongationAtLevel(int level) const
{
MFEM_ASSERT(level < prolongations.Size(),
"Prolongation at given level does not exist.");
return prolongations[level];
}
#ifdef MFEM_USE_MPI
ParFiniteElementSpaceHierarchy::ParFiniteElementSpaceHierarchy(ParMesh* mesh,
ParFiniteElementSpace* fespace,
bool ownM,
bool ownFES)
: FiniteElementSpaceHierarchy(mesh, fespace, ownM, ownFES)
{
}
void ParFiniteElementSpaceHierarchy::AddUniformlyRefinedLevel(int dim,
int ordering)
{
ParMesh* mesh = new ParMesh(*GetFinestFESpace().GetParMesh());
mesh->UniformRefinement();
ParFiniteElementSpace& coarseFEspace = GetFinestFESpace();
ParFiniteElementSpace* fineFEspace =
new ParFiniteElementSpace(mesh, coarseFEspace.FEColl(), dim, ordering);
Operator* P = new TrueTransferOperator(coarseFEspace, *fineFEspace);
AddLevel(mesh, fineFEspace, P, true, true, true);
}
void ParFiniteElementSpaceHierarchy::AddOrderRefinedLevel(
FiniteElementCollection* fec,
int dim, int ordering)
{
ParMesh* mesh = GetFinestFESpace().GetParMesh();
ParFiniteElementSpace* newFEspace =
new ParFiniteElementSpace(mesh, fec, dim, ordering);
Operator* P = new TrueTransferOperator(GetFinestFESpace(), *newFEspace);
AddLevel(mesh, newFEspace, P, false, true, true);
}
const ParFiniteElementSpace&
ParFiniteElementSpaceHierarchy::GetFESpaceAtLevel(int level) const
{
return static_cast<const ParFiniteElementSpace&>(
FiniteElementSpaceHierarchy::GetFESpaceAtLevel(level));
}
ParFiniteElementSpace& ParFiniteElementSpaceHierarchy::GetFESpaceAtLevel(
int level)
{
return static_cast<ParFiniteElementSpace&>(
FiniteElementSpaceHierarchy::GetFESpaceAtLevel(level));
}
const ParFiniteElementSpace& ParFiniteElementSpaceHierarchy::GetFinestFESpace()
const
{
return GetFESpaceAtLevel(GetFinestLevelIndex());
}
ParFiniteElementSpace& ParFiniteElementSpaceHierarchy::GetFinestFESpace()
{
return GetFESpaceAtLevel(GetFinestLevelIndex());
}
#endif
} // namespace mfem