Changed: Use findBoundaryElms() when setting up boundary thread groups

Fixed: Override findBoundaryElms() for ASMs2DLag and ASMs3DLag.
This commit is contained in:
Knut Morten Okstad 2023-09-24 13:36:19 +02:00
parent 038e4bbe78
commit 7c0d5e8ee6
5 changed files with 101 additions and 64 deletions

View File

@ -789,6 +789,28 @@ void ASMs2DLag::generateThreadGroups (const Integrand&, bool, bool)
}
void ASMs2DLag::findBoundaryElms (IntVec& elms, int lIndex, int) const
{
const int N1m = (nx-1)/(p1-1);
const int N2m = (ny-1)/(p2-1);
elms.clear();
switch (lIndex) {
case 1:
case 2:
elms.reserve(N2m);
for (int i = 0; i < N2m; ++i)
elms.push_back(i*N1m + (lIndex-1)*(N1m-1));
break;
case 3:
case 4:
elms.reserve(N1m);
for (int i = 0; i < N1m; ++i)
elms.push_back(i + (lIndex-3)*N1m*(N2m-1));
}
}
bool ASMs2DLag::write(std::ostream& os, int) const
{
return this->writeLagBasis(os, "quad");

View File

@ -128,6 +128,11 @@ protected:
//! \param[in] Xnod Coordinates of the node
void setCoord(size_t inod, const Vec3& Xnod);
//! \brief Finds the patch-local element numbers on a patch boundary.
//! \param[out] elms Array of element numbers
//! \param[in] lIndex Local index of the boundary edge
virtual void findBoundaryElms(IntVec& elms, int lIndex, int = 0) const;
//! \brief Find element for parameter, and optionally calculate local coordinates.
int findElement(double u, double v,
double* xi = nullptr, double* eta = nullptr) const;

View File

@ -3507,59 +3507,50 @@ void ASMs3D::generateThreadGroups (char lIndex, bool silence, bool)
{
if (threadGroupsFace.find(lIndex) != threadGroupsFace.end()) return;
const int p1 = svol->order(0);
const int p2 = svol->order(1);
const int p3 = svol->order(2);
const int p1 = svol->order(0) - 1;
const int p2 = svol->order(1) - 1;
const int p3 = svol->order(2) - 1;
const int n1 = svol->numCoefs(0);
const int n2 = svol->numCoefs(1);
const int n3 = svol->numCoefs(2);
// Find elements that are on the boundary face 'lIndex'
IntVec map; map.reserve(this->getNoBoundaryElms(lIndex,2));
int iel = 0;
for (int i3 = p3; i3 <= n3; i3++)
for (int i2 = p2; i2 <= n2; i2++)
for (int i1 = p1; i1 <= n1; i1++, iel++)
switch (lIndex)
{
case 1: if (i1 == p1) map.push_back(iel); break;
case 2: if (i1 == n1) map.push_back(iel); break;
case 3: if (i2 == p2) map.push_back(iel); break;
case 4: if (i2 == n2) map.push_back(iel); break;
case 5: if (i3 == p3) map.push_back(iel); break;
case 6: if (i3 == n3) map.push_back(iel); break;
}
// Flag the non-zero knot-spans
std::vector<bool> el1, el2, el3;
el1.reserve(n1 - p1 + 1);
el2.reserve(n2 - p2 + 1);
el3.reserve(n3 - p3 + 1);
if (lIndex > 2)
for (int i = p1-1; i < n1; i++)
if (lIndex > 2) {
el1.reserve(n1-p1);
for (int i = p1; i < n1; i++)
el1.push_back(svol->knotSpan(0,i) > 0.0);
if (lIndex < 3 || lIndex > 4)
for (int i = p2-1; i < n2; i++)
}
if (lIndex < 3 || lIndex > 4) {
el2.reserve(n2-p2);
for (int i = p2; i < n2; i++)
el2.push_back(svol->knotSpan(1,i) > 0.0);
if (lIndex < 6)
for (int i = p3-1; i < n3; i++)
}
if (lIndex < 6) {
el3.reserve(n3-p3);
for (int i = p3; i < n3; i++)
el3.push_back(svol->knotSpan(2,i) > 0.0);
}
ThreadGroups& fGrp = threadGroupsFace[lIndex];
switch (lIndex)
{
case 1:
case 2:
fGrp.calcGroups(el2,el3,p2-1,p3-1);
fGrp.calcGroups(el2,el3,p2,p3);
break;
case 3:
case 4:
fGrp.calcGroups(el1,el3,p1-1,p3-1);
fGrp.calcGroups(el1,el3,p1,p3);
break;
default:
fGrp.calcGroups(el1,el2,p1-1,p2-1);
fGrp.calcGroups(el1,el2,p1,p2);
}
// Find elements that are on the boundary face 'lIndex'
IntVec map;
this->findBoundaryElms(map,lIndex);
fGrp.applyMap(map);
if (silence || fGrp.size() < 2) return;

View File

@ -1079,45 +1079,58 @@ void ASMs3DLag::generateThreadGroups (char lIndex, bool, bool)
{
if (threadGroupsFace.find(lIndex) != threadGroupsFace.end()) return;
const int n1 = (nx-1)/(p1-1);
const int n2 = (ny-1)/(p2-1);
const int n3 = (nz-1)/(p3-1);
// Find elements that are on the boundary face 'lIndex'
IntVec map; map.reserve(this->getNoBoundaryElms(lIndex,2));
int d1, d2, iel = 0;
for (int i3 = 1; i3 <= n3; i3++)
for (int i2 = 1; i2 <= n2; i2++)
for (int i1 = 1; i1 <= n1; i1++, iel++)
switch (lIndex)
{
case 1: if (i1 == 1) map.push_back(iel); break;
case 2: if (i1 == n1) map.push_back(iel); break;
case 3: if (i2 == 1) map.push_back(iel); break;
case 4: if (i2 == n2) map.push_back(iel); break;
case 5: if (i3 == 1) map.push_back(iel); break;
case 6: if (i3 == n3) map.push_back(iel); break;
}
ThreadGroups& fGrp = threadGroupsFace[lIndex];
switch (lIndex)
{
case 1:
case 2:
d1 = n2;
d2 = n3;
fGrp.calcGroups((ny-1)/(p2-1), (nz-1)/(p3-1), 1);
break;
case 3:
case 4:
d1 = n1;
d2 = n3;
fGrp.calcGroups((nx-1)/(p1-1), (nz-1)/(p3-1), 1);
break;
default:
d1 = n1;
d2 = n2;
fGrp.calcGroups((nx-1)/(p1-1), (ny-1)/(p2-1), 1);
}
threadGroupsFace[lIndex].calcGroups(d1,d2,1);
threadGroupsFace[lIndex].applyMap(map);
// Find elements that are on the boundary face 'lIndex'
IntVec map;
this->findBoundaryElms(map,lIndex);
fGrp.applyMap(map);
}
void ASMs3DLag::findBoundaryElms (IntVec& elms, int lIndex, int) const
{
const int N1m = (nx-1)/(p1-1);
const int N2m = (ny-1)/(p2-1);
const int N3m = (nz-1)/(p3-1);
elms.clear();
switch (lIndex) {
case 1:
case 2:
elms.reserve(N2m*N3m);
for (int k = 0; k < N3m; ++k)
for (int j = 0; j < N2m; ++j)
elms.push_back(j*N1m + k*N1m*N2m + (lIndex-1)*(N1m-1));
break;
case 3:
case 4:
elms.reserve(N1m*N3m);
for (int k = 0; k < N3m; ++k)
for (int i = 0; i < N1m; ++i)
elms.push_back(i + k*N1m*N2m + (lIndex-3)*(N1m*(N2m-1)));
break;
case 5:
case 6:
elms.reserve(N1m*N2m);
for (int j = 0; j < N2m; ++j)
for (int i = 0; i < N1m; ++i)
elms.push_back(i + j*N1m + (lIndex-5)*(N1m*N2m*(N3m-1)));
}
}

View File

@ -128,17 +128,23 @@ public:
//! \param[in] nSegSpan Number of visualization segments over each knot-span
virtual bool getGridParameters(RealArray& prm, int dir, int nSegSpan) const;
//! \brief Find element for parameter, and optionally calculate local coordinates.
virtual int findElement(double u, double v, double w, double* xi = nullptr,
double* eta = nullptr, double* zeta = nullptr) const;
protected:
//! \brief Assigned global coordinates for the given node.
//! \param[in] inod 1-based node index local to current patch
//! \param[in] Xnod Coordinates of the node
void setCoord(size_t inod, const Vec3& Xnod);
//! \brief Finds the patch-local element numbers on a patch boundary.
//! \param[out] elms Array of element numbers
//! \param[in] lIndex Local index of the boundary face
virtual void findBoundaryElms(IntVec& elms, int lIndex, int = 0) const;
public:
//! \brief Find element for parameter, and optionally calculate local coordinates.
virtual int findElement(double u, double v, double w,
double* xi = nullptr, double* eta = nullptr,
double* zeta = nullptr) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);