ASMmxBase: rename raiseBasis to adjustBasis

take an array of AdjustOps for what to do
in each parameter direction
This commit is contained in:
Arne Morten Kvarving 2023-09-07 21:35:04 +02:00
parent 5dae005582
commit 96ddcfe9d4
6 changed files with 75 additions and 43 deletions

View File

@ -133,7 +133,8 @@ ASMmxBase::SurfaceVec ASMmxBase::establishBases (Go::SplineSurface* surf,
if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2) if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2)
{ {
// basis1 should be one degree higher than basis2 and C^p-1 continuous // basis1 should be one degree higher than basis2 and C^p-1 continuous
result[0].reset(ASMmxBase::raiseBasis(surf)); result[0].reset(ASMmxBase::adjustBasis(*surf,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise}));
result[1].reset(new Go::SplineSurface(*surf)); result[1].reset(new Go::SplineSurface(*surf));
itgBasis = 2; itgBasis = 2;
} }
@ -260,7 +261,9 @@ ASMmxBase::VolumeVec ASMmxBase::establishBases(Go::SplineVolume* svol,
if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2) if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2)
{ {
// basis1 should be one degree higher than basis2 and C^p-1 continuous // basis1 should be one degree higher than basis2 and C^p-1 continuous
result[0].reset(ASMmxBase::raiseBasis(svol)); result[0].reset(ASMmxBase::adjustBasis(*svol,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise}));
result[1].reset(new Go::SplineVolume(*svol)); result[1].reset(new Go::SplineVolume(*svol));
itgBasis = 2; itgBasis = 2;
} }
@ -338,6 +341,7 @@ ASMmxBase::VolumeVec ASMmxBase::establishBases(Go::SplineVolume* svol,
} }
tmp.insertKnot(dir, extraKnots); tmp.insertKnot(dir, extraKnots);
} }
Go::BsplineBasis b1 = tmp.basis(0).extendedBasis(tmp.order(0)+1); Go::BsplineBasis b1 = tmp.basis(0).extendedBasis(tmp.order(0)+1);
Go::BsplineBasis b2 = tmp.basis(1).extendedBasis(tmp.order(1)+1); Go::BsplineBasis b2 = tmp.basis(1).extendedBasis(tmp.order(1)+1);
Go::BsplineBasis b3 = tmp.basis(2).extendedBasis(tmp.order(2)+1); Go::BsplineBasis b3 = tmp.basis(2).extendedBasis(tmp.order(2)+1);
@ -390,13 +394,15 @@ ASMmxBase::VolumeVec ASMmxBase::establishBases(Go::SplineVolume* svol,
} }
Go::SplineSurface* ASMmxBase::raiseBasis (Go::SplineSurface* surf) Go::SplineSurface* ASMmxBase::adjustBasis (const Go::SplineSurface& surf,
const std::array<SplineUtils::AdjustOp,2>& ops)
{ {
// Create a C^p-1 basis of one degree higher than *surf // Create a surface with adjusted basis from surf
// but keep lines of reduced continuity // while keeping lines of reduced continuity
using Op = SplineUtils::AdjustOp; std::array<Go::BsplineBasis,2> basis{
std::array<Go::BsplineBasis,2> basis{SplineUtils::adjustBasis(surf->basis(0),Op::Raise), SplineUtils::adjustBasis(surf.basis(0),ops[0]),
SplineUtils::adjustBasis(surf->basis(1),Op::Raise)}; SplineUtils::adjustBasis(surf.basis(1),ops[1])
};
// Compute parameter values of the Greville points // Compute parameter values of the Greville points
std::array<RealArray,2> ug; std::array<RealArray,2> ug;
@ -406,30 +412,35 @@ Go::SplineSurface* ASMmxBase::raiseBasis (Go::SplineSurface* surf)
ug[idx][i] = basis[idx].grevilleParameter(i); ug[idx][i] = basis[idx].grevilleParameter(i);
} }
int ndim = surf->dimension(); int ndim = surf.dimension();
if (surf->rational()) if (surf.rational())
{ {
std::vector<double> rCoefs(surf->rcoefs_begin(), surf->rcoefs_end()); std::vector<double> rCoefs(surf.rcoefs_begin(), surf.rcoefs_end());
// We normally would set coefs as (x*w, y*w, w). // We normally would set coefs as (x*w, y*w, w).
// However, GoTools uses this representation internally already. // However, GoTools uses this representation internally already.
// Instance a Bspline surface in ndim+1 // Instance a Bspline surface in ndim+1
Go::SplineSurface surf2(surf->basis(0), surf->basis(1), rCoefs.begin(), ndim+1, false); Go::SplineSurface surf2(surf.basis(0), surf.basis(1),
rCoefs.begin(), ndim+1, false);
// Interpolate the Bspline surface onto new basis // Interpolate the Bspline surface onto new basis
RealArray XYZ((ndim+1)*ug[0].size()*ug[1].size()); RealArray XYZ((ndim+1)*ug[0].size()*ug[1].size());
surf2.gridEvaluator(XYZ,ug[0],ug[1]); surf2.gridEvaluator(XYZ,ug[0],ug[1]);
std::unique_ptr<Go::SplineSurface> surf3(Go::SurfaceInterpolator::regularInterpolation(basis[0],basis[1],ug[0],ug[1],XYZ,ndim+1,false,XYZ)); std::unique_ptr<Go::SplineSurface> surf3(
Go::SurfaceInterpolator::regularInterpolation(basis[0],basis[1],
ug[0],ug[1],
XYZ,ndim+1,false,XYZ));
// New rational coefs are (x/w', y/w', w') // New rational coefs are (x/w', y/w', w')
// Apparently, GoTools will rescale coeffs on surface creation. // Apparently, GoTools will rescale coeffs on surface creation.
return new Go::SplineSurface(surf3->basis(0), surf3->basis(1), surf3->coefs_begin(), ndim, true); return new Go::SplineSurface(surf3->basis(0), surf3->basis(1),
surf3->coefs_begin(), ndim, true);
} }
// Evaluate the spline surface at all points // Evaluate the spline surface at all points
RealArray XYZ(ndim*ug[0].size()*ug[1].size()); RealArray XYZ(ndim*ug[0].size()*ug[1].size());
surf->gridEvaluator(XYZ,ug[0],ug[1]); surf.gridEvaluator(XYZ,ug[0],ug[1]);
// Project the coordinates onto the new basis (the 2nd XYZ is dummy here) // Project the coordinates onto the new basis (the 2nd XYZ is dummy here)
return Go::SurfaceInterpolator::regularInterpolation(basis[0],basis[1], return Go::SurfaceInterpolator::regularInterpolation(basis[0],basis[1],
@ -437,14 +448,16 @@ Go::SplineSurface* ASMmxBase::raiseBasis (Go::SplineSurface* surf)
} }
Go::SplineVolume* ASMmxBase::raiseBasis (Go::SplineVolume* svol) Go::SplineVolume* ASMmxBase::adjustBasis (const Go::SplineVolume& svol,
const std::array<SplineUtils::AdjustOp,3>& ops)
{ {
// Create a C^p-1 basis of one degree higher than *svol // Create a volume with adjusted orders from svol
// but keep lines of reduced continuity // while keeping lines of reduced continuity
using Op = SplineUtils::AdjustOp; std::array<Go::BsplineBasis,3> basis{
std::array<Go::BsplineBasis,3> basis{SplineUtils::adjustBasis(svol->basis(0),Op::Raise), SplineUtils::adjustBasis(svol.basis(0),ops[0]),
SplineUtils::adjustBasis(svol->basis(1),Op::Raise), SplineUtils::adjustBasis(svol.basis(1),ops[1]),
SplineUtils::adjustBasis(svol->basis(2),Op::Raise)}; SplineUtils::adjustBasis(svol.basis(2),ops[2])
};
// Compute parameter values of the Greville points // Compute parameter values of the Greville points
std::array<RealArray,3> ug; std::array<RealArray,3> ug;
@ -454,30 +467,37 @@ Go::SplineVolume* ASMmxBase::raiseBasis (Go::SplineVolume* svol)
ug[idx][i] = basis[idx].grevilleParameter(i); ug[idx][i] = basis[idx].grevilleParameter(i);
} }
int ndim = svol->dimension(); int ndim = svol.dimension();
if (svol->rational()) if (svol.rational())
{ {
std::vector<double> rCoefs(svol->rcoefs_begin(), svol->rcoefs_end()); std::vector<double> rCoefs(svol.rcoefs_begin(), svol.rcoefs_end());
// We normally would set coefs as (x*w, y*w, w). // We normally would set coefs as (x*w, y*w, w).
// However, GoTools use this representation internally already. // However, GoTools use this representation internally already.
// Instance a Bspline surface in ndim+1 // Instance a Bspline surface in ndim+1
Go::SplineVolume vol2(svol->basis(0), svol->basis(1), svol->basis(2), rCoefs.begin(), ndim+1, false); Go::SplineVolume vol2(svol.basis(0), svol.basis(1), svol.basis(2),
rCoefs.begin(), ndim+1, false);
// Interpolate the Bspline surface onto new basis // Interpolate the Bspline surface onto new basis
RealArray XYZ((ndim+1)*ug[0].size()*ug[1].size()*ug[2].size()); RealArray XYZ((ndim+1)*ug[0].size()*ug[1].size()*ug[2].size());
vol2.gridEvaluator(XYZ,ug[0],ug[1],ug[2]); vol2.gridEvaluator(XYZ,ug[0],ug[1],ug[2]);
std::unique_ptr<Go::SplineVolume> svol3(Go::VolumeInterpolator::regularInterpolation(basis[0],basis[1],basis[2],ug[0],ug[1],ug[2],XYZ,ndim+1,false,XYZ)); std::unique_ptr<Go::SplineVolume> svol3(
Go::VolumeInterpolator::regularInterpolation(basis[0],basis[1],basis[2],
ug[0],ug[1],ug[2],XYZ,
ndim+1,false,XYZ));
// New rational coefs are (x/w', y/w', w') // New rational coefs are (x/w', y/w', w')
// Apparently, GoTools will rescale coeffs on surface creation. // Apparently, GoTools will rescale coeffs on surface creation.
return new Go::SplineVolume(svol3->basis(0), svol3->basis(1), svol3->basis(2), svol3->coefs_begin(), ndim, true); return new Go::SplineVolume(svol3->basis(0), svol3->basis(1), svol3->basis(2),
svol3->coefs_begin(), ndim, true);
} }
RealArray XYZ(ndim*ug[0].size()*ug[1].size()*ug[2].size()); RealArray XYZ(ndim*ug[0].size()*ug[1].size()*ug[2].size());
// Evaluate the spline surface at all points // Evaluate the spline surface at all points
svol->gridEvaluator(ug[0],ug[1],ug[2],XYZ); svol.gridEvaluator(ug[0],ug[1],ug[2],XYZ);
// Project the coordinates onto the new basis (the 2nd XYZ is dummy here) // Project the coordinates onto the new basis (the 2nd XYZ is dummy here)
return Go::VolumeInterpolator::regularInterpolation(basis[0],basis[1],basis[2],ug[0],ug[1],ug[2],XYZ,ndim,false,XYZ); return Go::VolumeInterpolator::regularInterpolation(basis[0],basis[1],basis[2],
ug[0],ug[1],ug[2],
XYZ,ndim,false,XYZ);
} }

View File

@ -22,6 +22,10 @@ namespace Go {
class SplineVolume; class SplineVolume;
} }
namespace SplineUtils {
enum class AdjustOp;
}
/*! /*!
\brief Base class for spline-based mixed finite element assembly drivers. \brief Base class for spline-based mixed finite element assembly drivers.
@ -92,9 +96,11 @@ protected:
static VolumeVec establishBases(Go::SplineVolume* svol, MixedType type); static VolumeVec establishBases(Go::SplineVolume* svol, MixedType type);
//! \brief Returns a C^p-1 basis of one degree higher than \a *surf. //! \brief Returns a C^p-1 basis of one degree higher than \a *surf.
static Go::SplineSurface* raiseBasis(Go::SplineSurface* surf); static Go::SplineSurface* adjustBasis(const Go::SplineSurface& surf,
const std::array<SplineUtils::AdjustOp,2>& ops);
//! \brief Returns a C^p-1 basis of one degree higher than \a *svol. //! \brief Returns a C^p-1 basis of one degree higher than \a *svol.
static Go::SplineVolume* raiseBasis(Go::SplineVolume* svol); static Go::SplineVolume* adjustBasis(const Go::SplineVolume& svol,
const std::array<SplineUtils::AdjustOp,3>& ops);
private: private:
std::vector<int> MADOF; //!< Matrix of accumulated DOFs for this patch std::vector<int> MADOF; //!< Matrix of accumulated DOFs for this patch

View File

@ -213,7 +213,8 @@ bool ASMs2Dmx::generateFEMTopology ()
if (ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS1 || if (ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS1 ||
ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 || ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 ||
ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE) ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
projB = ASMmxBase::raiseBasis(surf); projB = ASMmxBase::adjustBasis(*surf,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise});
else if (ASMmxBase::Type == ASMmxBase::SUBGRID) else if (ASMmxBase::Type == ASMmxBase::SUBGRID)
projB = m_basis.front().get(); projB = m_basis.front().get();
else // FULL_CONT_RAISE_BASISx else // FULL_CONT_RAISE_BASISx
@ -221,7 +222,8 @@ bool ASMs2Dmx::generateFEMTopology ()
} }
if (ASMmxBase::Type == ASMmxBase::SUBGRID) { if (ASMmxBase::Type == ASMmxBase::SUBGRID) {
projB2 = ASMmxBase::raiseBasis(surf); projB2 = ASMmxBase::adjustBasis(*surf,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise});
geomB = m_basis[1].get(); geomB = m_basis[1].get();
} else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE) } else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
geomB = projB; geomB = projB;

View File

@ -211,7 +211,9 @@ bool ASMs3Dmx::generateFEMTopology ()
if (ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS1 || if (ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS1 ||
ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 || ASMmxBase::Type == ASMmxBase::REDUCED_CONT_RAISE_BASIS2 ||
ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE) ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
projB = ASMmxBase::raiseBasis(svol); projB = ASMmxBase::adjustBasis(*svol,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise});
else if (ASMmxBase::Type == ASMmxBase::SUBGRID) else if (ASMmxBase::Type == ASMmxBase::SUBGRID)
projB = m_basis.front().get(); projB = m_basis.front().get();
else // FULL_CONT_RAISE_BASISx else // FULL_CONT_RAISE_BASISx
@ -219,7 +221,9 @@ bool ASMs3Dmx::generateFEMTopology ()
} }
if (ASMmxBase::Type == ASMmxBase::SUBGRID) { if (ASMmxBase::Type == ASMmxBase::SUBGRID) {
projB2 = ASMmxBase::raiseBasis(svol); projB2 = ASMmxBase::adjustBasis(*svol,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise});
geomB = m_basis[1].get(); geomB = m_basis[1].get();
} else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE) } else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
geomB = projB; geomB = projB;

View File

@ -209,7 +209,9 @@ bool ASMu2Dmx::generateFEMTopology ()
for (size_t b = 0; b < svec.size(); b++) for (size_t b = 0; b < svec.size(); b++)
m_basis.push_back(createLR(*svec[b])); m_basis.push_back(createLR(*svec[b]));
std::unique_ptr<Go::SplineSurface> otherBasis(ASMmxBase::raiseBasis(tensorspline)); std::unique_ptr<Go::SplineSurface> otherBasis(
ASMmxBase::adjustBasis(*tensorspline,{SplineUtils::AdjustOp::Raise,
SplineUtils::AdjustOp::Raise}));
// we need to project on something that is not one of our bases // we need to project on something that is not one of our bases
if (!projB) { if (!projB) {

View File

@ -193,12 +193,10 @@ bool ASMu3Dmx::generateFEMTopology ()
for (size_t b = 0; b < vvec.size(); b++) for (size_t b = 0; b < vvec.size(); b++)
m_basis.push_back(std::make_shared<LR::LRSplineVolume>(vvec[b].get())); m_basis.push_back(std::make_shared<LR::LRSplineVolume>(vvec[b].get()));
// make a backup as establishBases resets it std::unique_ptr<Go::SplineVolume> otherBasis(
int geoB = ASMmxBase::itgBasis; ASMmxBase::adjustBasis(*tensorspline,{SplineUtils::AdjustOp::Raise,
std::shared_ptr<Go::SplineVolume> otherBasis = SplineUtils::AdjustOp::Raise,
ASMmxBase::establishBases(tensorspline, SplineUtils::AdjustOp::Raise}));
ASMmxBase::FULL_CONT_RAISE_BASIS1).front();
itgBasis = geoB;
// we need to project on something that is not one of our bases // we need to project on something that is not one of our bases
if (!projB) { if (!projB) {