introduce support for an alternative projection basis

This commit is contained in:
Arne Morten Kvarving
2022-04-27 10:54:15 +02:00
parent 1d88adf5af
commit 459463878a
9 changed files with 107 additions and 16 deletions

View File

@@ -682,6 +682,8 @@ public:
virtual bool createProjectionBasis(bool) { return false; }
//! \brief Checks if a separate projection basis is used for this patch.
virtual bool separateProjectionBasis() const { return false; }
//! \brief Swap between main and alternative projection basis.
virtual void swapProjectionBasis() {}
// Methods for result extraction

View File

@@ -44,6 +44,12 @@ ASMs2Dmx::ASMs2Dmx (const ASMs2Dmx& patch, const CharVec& n_f)
}
ASMs2Dmx::~ASMs2Dmx ()
{
delete altProjBasis;
}
Go::SplineSurface* ASMs2Dmx::getBasis (int basis) const
{
if (basis < 1 || basis > (int)m_basis.size())
@@ -206,9 +212,10 @@ bool ASMs2Dmx::generateFEMTopology ()
ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 ||
ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
projB = proj = ASMmxBase::raiseBasis(surf);
else if (ASMmxBase::Type == ASMmxBase::SUBGRID)
else if (ASMmxBase::Type == ASMmxBase::SUBGRID) {
projB = proj = m_basis.front()->clone();
else
altProjBasis = ASMmxBase::raiseBasis(surf);
} else
projB = proj = m_basis[2-ASMmxBase::geoBasis]->clone();
}
delete surf;
@@ -1237,3 +1244,13 @@ void ASMs2Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, int basis,
for (size_t b = 1; b <= m_basis.size(); b++)
this->ASMs2D::getBoundaryNodes(lIndex, nodes, b, thick, 0, local);
}
void ASMs2Dmx::swapProjectionBasis ()
{
if (altProjBasis) {
ASMmxBase::geoBasis = ASMmxBase::geoBasis == 1 ? 2 : 1;
std::swap(proj, altProjBasis);
surf = this->getBasis(ASMmxBase::geoBasis);
}
}

View File

@@ -36,8 +36,8 @@ public:
ASMs2Dmx(unsigned char n_s, const CharVec& n_f);
//! \brief Copy constructor.
ASMs2Dmx(const ASMs2Dmx& patch, const CharVec& n_f = CharVec(2,0));
//! \brief Empty destructor.
virtual ~ASMs2Dmx() {}
//! \brief Destructor.
virtual ~ASMs2Dmx();
//! \brief Returns the spline surface representing the basis of this patch.
virtual Go::SplineSurface* getBasis(int basis = 1) const;
@@ -123,7 +123,7 @@ public:
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
virtual bool integrate(Integrand& integrand,
GlobalIntegral& glbInt, const TimeDomain& time);
GlobalIntegral& glbInt, const TimeDomain& time);
//! \brief Evaluates a boundary integral over a patch edge.
//! \param integrand Object with problem-specific data and methods
@@ -131,7 +131,7 @@ public:
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
virtual bool integrate(Integrand& integrand, int lIndex,
GlobalIntegral& glbInt, const TimeDomain& time);
GlobalIntegral& glbInt, const TimeDomain& time);
//! \brief Evaluates an integral over element interfaces in the patch.
//! \param integrand Object with problem-specific data and methods
@@ -158,7 +158,7 @@ public:
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
const IntVec& nodes) const;
using ASMs2D::evalSolution;
//! \brief Evaluates the primary solution field at the given points.
@@ -192,7 +192,10 @@ public:
//! Otherwise, we assume that it contains the \a u and \a v parameters
//! directly for each sampling point.
virtual bool evalSolution(Matrix& sField, const IntegrandBase& integrand,
const RealArray* gpar, bool regular) const;
const RealArray* gpar, bool regular) const;
//! \brief Swap between main and alternative projection basis.
virtual void swapProjectionBasis();
//! \brief Extracts nodal results for this patch from the global vector.
//! \param[in] globVec Global solution vector in DOF-order
@@ -234,6 +237,7 @@ public:
protected:
std::vector<std::shared_ptr<Go::SplineSurface>> m_basis; //!< Vector of bases
Go::SplineSurface* altProjBasis = nullptr; //!< Alternative projection basis
};
#endif

View File

@@ -50,6 +50,12 @@ ASMs3Dmx::ASMs3Dmx (const ASMs3Dmx& patch, const CharVec& n_f)
}
ASMs3Dmx::~ASMs3Dmx ()
{
delete altProjBasis;
}
Go::SplineVolume* ASMs3Dmx::getBasis (int basis) const
{
if (basis < 1 || basis > (int)m_basis.size())
@@ -207,9 +213,10 @@ bool ASMs3Dmx::generateFEMTopology ()
ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 ||
ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
projB = proj = ASMmxBase::raiseBasis(svol);
else if (ASMmxBase::Type == ASMmxBase::SUBGRID)
else if (ASMmxBase::Type == ASMmxBase::SUBGRID) {
projB = proj = m_basis.front()->clone();
else
altProjBasis = ASMmxBase::raiseBasis(svol);
} else
projB = proj = m_basis[2-ASMmxBase::geoBasis]->clone();
}
delete svol;
@@ -1359,3 +1366,13 @@ void ASMs3Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, int basis,
for (size_t b = 1; b <= m_basis.size(); b++)
this->ASMs3D::getBoundaryNodes(lIndex, nodes, b, thick, 0, local);
}
void ASMs3Dmx::swapProjectionBasis ()
{
if (altProjBasis) {
ASMmxBase::geoBasis = ASMmxBase::geoBasis == 1 ? 2 : 1;
std::swap(proj, altProjBasis);
svol = this->getBasis(ASMmxBase::geoBasis);
}
}

View File

@@ -36,8 +36,8 @@ public:
explicit ASMs3Dmx(const CharVec& n_f);
//! \brief Copy constructor.
ASMs3Dmx(const ASMs3Dmx& patch, const CharVec& n_f = CharVec(2,0));
//! \brief Empty destructor.
virtual ~ASMs3Dmx() {}
//! \brief Destructor.
virtual ~ASMs3Dmx();
//! \brief Returns the spline surface representing the basis of this patch.
virtual Go::SplineVolume* getBasis(int basis = 1) const;
@@ -116,7 +116,7 @@ public:
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
virtual bool integrate(Integrand& integrand,
GlobalIntegral& glbInt, const TimeDomain& time);
GlobalIntegral& glbInt, const TimeDomain& time);
//! \brief Evaluates a boundary integral over a patch edge.
//! \param integrand Object with problem-specific data and methods
@@ -124,7 +124,7 @@ public:
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
virtual bool integrate(Integrand& integrand, int lIndex,
GlobalIntegral& glbInt, const TimeDomain& time);
GlobalIntegral& glbInt, const TimeDomain& time);
//! \brief Evaluates an integral over element interfaces in the patch.
//! \param integrand Object with problem-specific data and methods
@@ -150,7 +150,7 @@ public:
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
const IntVec& nodes) const;
using ASMs3D::evalSolution;
//! \brief Evaluates the primary solution field at the given points.
@@ -184,7 +184,10 @@ public:
//! Otherwise, we assume that it contains the \a u, \a v and \a w parameters
//! directly for each sampling point.
virtual bool evalSolution(Matrix& sField, const IntegrandBase& integrand,
const RealArray* gpar, bool regular) const;
const RealArray* gpar, bool regular) const;
//! \brief Swap between main and alternative projection basis.
virtual void swapProjectionBasis();
//! \brief Extracts nodal results for this patch from the global vector.
//! \param[in] globVec Global solution vector in DOF-order
@@ -213,6 +216,7 @@ public:
//! \param[out] n3 Number of nodes in third (w) direction
//! \param[in] basis Which basis to return size parameters for
virtual bool getSize(int& n1, int& n2, int& n3, int basis) const;
protected:
//! \brief Returns the volume in the parameter space for an element.
//! \param[in] iel Element index
@@ -232,6 +236,7 @@ protected:
int thick, int, bool local) const;
std::vector<std::shared_ptr<Go::SplineVolume>> m_basis; //!< Vector of bases
Go::SplineVolume* altProjBasis = nullptr; //!< Alternative projection basis
};
#endif

View File

@@ -227,6 +227,7 @@ bool ASMu2Dmx::generateFEMTopology ()
refBasis.reset(new LR::LRSplineSurface(otherBasis));
if (!projBasis)
projBasis = m_basis.front();
altProjBasis = refBasis;
}
else {
if (!projBasis)
@@ -1018,6 +1019,9 @@ bool ASMu2Dmx::refine (const LR::RefineData& prm, Vectors& sol)
m_basis[0]->refineBasisFunction(elems);
}
if (altProjBasis)
altProjBasis->generateIDs();
size_t len = 0;
for (size_t j = 0; j< m_basis.size(); ++j) {
m_basis[j]->generateIDs();
@@ -1099,6 +1103,8 @@ void ASMu2Dmx::generateThreadGroups (const Integrand& integrand, bool silence,
LR::generateThreadGroups(threadGroups,threadBasis,secConstraint);
LR::generateThreadGroups(projThreadGroups,projBasis.get());
if (altProjBasis)
LR::generateThreadGroups(altProjThreadGroups,altProjBasis.get());
std::vector<const LR::LRSpline*> bases;
for (const std::shared_ptr<LR::LRSplineSurface>& basis : m_basis)
@@ -1223,3 +1229,13 @@ void ASMu2Dmx::copyRefinement (LR::LRSplineSurface* basis,
line->start_, line->stop_, mult);
}
}
void ASMu2Dmx::swapProjectionBasis ()
{
if (altProjBasis) {
ASMmxBase::geoBasis = ASMmxBase::geoBasis == 1 ? 2 : 1;
std::swap(projBasis, altProjBasis);
std::swap(projThreadGroups, altProjThreadGroups);
}
}

View File

@@ -215,6 +215,9 @@ public:
//! \param multiplicity Wanted multiplicity
void copyRefinement(LR::LRSplineSurface* basis, int multiplicity) const;
//! \brief Swap between main and alternative projection basis.
virtual void swapProjectionBasis();
protected:
using ASMu2D::generateThreadGroups;
//! \brief Generates element groups for multi-threading of interior integrals.
@@ -228,6 +231,8 @@ private:
std::vector<std::shared_ptr<LR::LRSplineSurface>> m_basis; //!< All bases
LR::LRSplineSurface* threadBasis; //!< Basis for thread groups
std::shared_ptr<LR::LRSplineSurface> refBasis; //!< Basis to refine based on
std::shared_ptr<LR::LRSplineSurface> altProjBasis; //!< Alternative projection basis
ThreadGroups altProjThreadGroups; //!< Element groups for multi-threaded assembly - alternative projection basis
};
#endif

View File

@@ -215,6 +215,7 @@ bool ASMu3Dmx::generateFEMTopology ()
refBasis.reset(new LR::LRSplineVolume(otherBasis.get()));
projBasis = m_basis.front();
refBasis->generateIDs();
altProjBasis = refBasis;
} else {
projBasis.reset(new LR::LRSplineVolume(otherBasis.get()));
refBasis = projBasis;
@@ -231,6 +232,10 @@ bool ASMu3Dmx::generateFEMTopology ()
lrspline = m_basis[geoBasis-1];
projBasis->generateIDs();
projBasis->getElementContaining(projBasis->getElement(0)->midpoint()); // to force cache generation
if (altProjBasis) {
altProjBasis->generateIDs();
altProjBasis->getElementContaining(projBasis->getElement(0)->midpoint()); // to force cache generation
}
myGeoBasis = ASMmxBase::geoBasis;
nb.resize(m_basis.size());
@@ -977,6 +982,9 @@ bool ASMu3Dmx::refine (const LR::RefineData& prm, Vectors& sol)
m_basis[0]->refineBasisFunction(elems);
}
if (altProjBasis)
altProjBasis->generateIDs();
size_t len = 0;
for (size_t j = 0; j< m_basis.size(); ++j) {
m_basis[j]->generateIDs();
@@ -1100,6 +1108,8 @@ void ASMu3Dmx::generateThreadGroups (const Integrand& integrand, bool silence,
LR::generateThreadGroups(threadGroups,threadBasis,secConstraint);
LR::generateThreadGroups(projThreadGroups,projBasis.get());
if (altProjBasis)
LR::generateThreadGroups(altProjThreadGroups,altProjBasis.get());
std::vector<const LR::LRSpline*> bases;
for (const std::shared_ptr<LR::LRSplineVolume>& basis : m_basis)
@@ -1119,3 +1129,13 @@ void ASMu3Dmx::generateThreadGroups (const Integrand& integrand, bool silence,
this->analyzeThreadGroups(threadGroups[0]);
#endif
}
void ASMu3Dmx::swapProjectionBasis ()
{
if (altProjBasis) {
ASMmxBase::geoBasis = ASMmxBase::geoBasis == 1 ? 2 : 1;
std::swap(projBasis, altProjBasis);
std::swap(projThreadGroups, altProjThreadGroups);
}
}

View File

@@ -181,6 +181,9 @@ public:
//! \param multiplicity Wanted multiplicity
void copyRefinement(LR::LRSplineVolume* basis, int multiplicity) const;
//! \brief Swap between main and alternative projection basis.
virtual void swapProjectionBasis();
protected:
//! \brief Generates element groups for multi-threading of interior integrals.
//! \param[in] integrand Object with problem-specific data and methods
@@ -192,9 +195,11 @@ protected:
private:
std::vector<std::shared_ptr<LR::LRSplineVolume>> m_basis; //!< Spline bases
std::shared_ptr<LR::LRSplineVolume> refBasis; //!< Basis to refine based on
std::shared_ptr<LR::LRSplineVolume> altProjBasis; //!< Alternative projection basis
LR::LRSplineVolume* threadBasis; //!< Basis for thread groups
const std::vector<Matrices>& bezierExtractmx; //!< Bezier extraction matrices
std::vector<Matrices> myBezierExtractmx; //!< Bezier extraction matrices
ThreadGroups altProjThreadGroups; //!< Element groups for multi-threaded assembly - alternative projection basis
};
#endif