Computation of local subdomain for block system
git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@2075 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
@@ -24,7 +24,9 @@
|
||||
#include "GoTools/trivariate/SplineVolume.h"
|
||||
|
||||
#ifdef HAS_PETSC
|
||||
#include "PETScMatrix.h"
|
||||
// RUNAR
|
||||
//#include "PETScMatrix.h"
|
||||
#include "PETScBlockMatrix.h"
|
||||
#include "petscversion.h"
|
||||
#if PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2
|
||||
#define PETSCMANGLE(x) &x
|
||||
@@ -69,6 +71,28 @@ bool SAMpatchPara::init (const ASMVec& model, int numNod)
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getEqns(IntVec& eqns, int f1, int f2) const
|
||||
{
|
||||
int nf = ndof/nnod;
|
||||
int nbf = f2-f1+1;
|
||||
int nbdof = nnod*nbf;
|
||||
|
||||
if (f1 > f2 || f1 < 0 || f2 > nf-1)
|
||||
return false;
|
||||
|
||||
eqns.resize(nbdof);
|
||||
for (int n = 0;n < nnod;n++) {
|
||||
int dof = nnod*nf + f1;
|
||||
int bdof = nnod*nbf;
|
||||
|
||||
for (int k = 0;k < nbf;k++, dof++, bdof++)
|
||||
eqns[bdof] = meqn[dof];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getNoDofCouplings (int ifirst, int ilast,
|
||||
IntVec& d_nnz, IntVec& o_nnz) const
|
||||
{
|
||||
@@ -153,6 +177,171 @@ bool SAMpatchPara::getNoDofCouplings (int ifirst, int ilast,
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SAMpatchPara::getNoDofCouplings(int ifirst, int ilast, IntVec ncomps,
|
||||
std::vector<std::vector<IntVec> >& d_nnz,
|
||||
std::vector<std::vector<IntVec> >& o_nnz) const
|
||||
{
|
||||
// Find number of dofs per row for each submatrix
|
||||
size_t nblock = ncomps.size();
|
||||
size_t nf = 0;
|
||||
for (size_t n = 0;n < nblock;n++)
|
||||
nf += ncomps[n];
|
||||
size_t nlocnode = (ilast-ifirst)/nf;
|
||||
|
||||
// Must have same number of dofs per node, i.e. not mixed
|
||||
if (ndof%nf > 0)
|
||||
return false;
|
||||
|
||||
std::vector<std::vector<std::vector<IntSet> > > d_dofc, o_dofc;
|
||||
|
||||
// Resize vectors for each submatrix
|
||||
d_dofc.resize(nblock);
|
||||
for (size_t i = 0;i < nblock;i++) {
|
||||
d_dofc[i].resize(nblock);
|
||||
for (size_t j = 0;j < nblock;j++) {
|
||||
d_dofc[i][j].resize(nnod*ncomps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PARALLEL_CODE
|
||||
o_dofc.resize(nblock);
|
||||
for (size_t i = 0;i < nblock;i++) {
|
||||
o_dofc[i].resize(nblock);
|
||||
for (size_t j = 0;j < nblock;j++)
|
||||
o_dofc[i][j].resize(nnod*ncomps[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
IntVec meenI, meenJ;
|
||||
for (int iel = 1;iel <= nel;iel++) {
|
||||
size_t if1 = 0;
|
||||
for (size_t i = 0;i < nblock;i++) {
|
||||
size_t if2 = if1 + ncomps[i];
|
||||
|
||||
this->getElmEqns(meenI,iel,if1,if2-1,true);
|
||||
|
||||
size_t jf1 = 0;
|
||||
for (size_t j = 0;j < nblock;j++) {
|
||||
size_t jf2 = jf1 + ncomps[j];
|
||||
|
||||
this->getElmEqns(meenJ,iel,jf1,jf2-1,true);
|
||||
|
||||
for (size_t k = 0;k < meenI.size();k++) {
|
||||
if (meenI[k] > 0) {
|
||||
int d_ldof = meenI[k]-1;
|
||||
int d_gdof = meqn[d_ldof]-1;
|
||||
|
||||
int d_lbdof = (d_ldof/nf)*ncomps[i] + (d_ldof%nf)-if1;
|
||||
|
||||
if (d_gdof >= ifirst && d_gdof < ilast) {
|
||||
for (size_t l = 0; l < meenJ.size(); l++)
|
||||
if (meenJ[l] > 0) {
|
||||
int o_ldof = meenJ[l]-1;
|
||||
int o_gdof = meqn[o_ldof]-1;
|
||||
|
||||
int o_lbdof = (o_ldof/nf)*ncomps[j] + (o_ldof%nf)-jf1;
|
||||
if (o_gdof >= ifirst && o_gdof < ilast)
|
||||
d_dofc[i][j][d_lbdof].insert(o_lbdof);
|
||||
else
|
||||
o_dofc[i][j][d_lbdof].insert(o_lbdof);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (size_t l = 0; l < meenJ.size(); l++)
|
||||
if (meenJ[l] > 0) {
|
||||
int o_ldof = meenJ[l]-1;
|
||||
int o_gdof = meqn[o_ldof]-1;
|
||||
|
||||
int o_lbdof = (o_ldof/nf)*ncomps[j] + (o_ldof%nf)-jf1;
|
||||
if (o_gdof >= ifirst && o_gdof < ilast)
|
||||
o_dofc[i][j][d_lbdof].insert(o_lbdof);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate nnz for diagonal blocks
|
||||
d_nnz.resize(nblock);
|
||||
size_t if1 = 0;
|
||||
for (size_t i = 0;i < nblock;i++) {
|
||||
d_nnz[i].resize(nblock);
|
||||
|
||||
for (size_t j = 0;j < nblock;j++) {
|
||||
d_nnz[i][j].resize(nlocnode*ncomps[i]);
|
||||
for (int k = 0; k < nnod; k++) {
|
||||
int bdof = k*ncomps[i];
|
||||
int dof = k*nf + if1;
|
||||
for (int l = 0;l < ncomps[i];l++, bdof++, dof++) {
|
||||
int d_gdof = meqn[dof]-1;
|
||||
int beq = (d_gdof-ifirst)/nf*ncomps[i] + l;
|
||||
if (d_gdof >= ifirst && d_gdof < ilast)
|
||||
d_nnz[i][j][beq] = d_dofc[i][j][bdof].size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if1 += ncomps[i];
|
||||
}
|
||||
|
||||
#ifdef PARALLEL_CODE
|
||||
// Generate nnz for off-diagonal block);
|
||||
o_nnz.resize(nblock);
|
||||
if1 = 0;
|
||||
for (size_t i = 0;i < nblock;i++) {
|
||||
o_nnz[i].resize(nblock);
|
||||
for (size_t j = 0;j < nblock;j++) {
|
||||
o_nnz[i][j].resize(nlocnode*ncomps[i]);
|
||||
|
||||
RealArray nnz(nnod*comps[i]);
|
||||
std::vector<PetscInt> l2g(nnod*ncomps[i]);
|
||||
|
||||
for (size_t k = 0; k < nnod; k++) {
|
||||
size_t bdof = k*ncomps[i];
|
||||
size_t dof = k*nf + f1;
|
||||
for (size_t l = 0;l < ncomps[i];l++, bdof++, dof++) {
|
||||
size_t d_gdof = meqn[dof]-1;
|
||||
if (d_gdof >= ifirst && d_gdof < ilast) {
|
||||
nnz[bdof] = d_dofc[i][j][bdof].size();
|
||||
l2g[bdof] = (d_gdof/nf)*ncomps[i] + l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t locsize = nlocnode*ncomps[i];
|
||||
size_t nldof = nnod*ncomps[i];
|
||||
|
||||
Vec x;
|
||||
VecCreate(PETSC_COMM_WORLD,&x);
|
||||
VecSetSizes(x,locsize,PETSC_DECIDE);
|
||||
VecSetFromOptions(x);
|
||||
VecSet(x,0.0);
|
||||
VecSetValues(x,nldof,&l2g[0],&(nnz[i][j][0]),ADD_VALUES);
|
||||
VecAssemblyBegin(x);
|
||||
VecAssemblyEnd(x);
|
||||
|
||||
PetscScalar* vec;
|
||||
VecGetArray(x,&vec);
|
||||
|
||||
o_nnz[i][j].resize(locsize);
|
||||
for (k = 0; k < locsize; k++)
|
||||
o_nnz[i][j][k] = ceil(vec[k]);
|
||||
|
||||
VecRestoreArray(x,&vec);
|
||||
VecDestroy(PETSCMANGLE(x));
|
||||
}
|
||||
|
||||
if1 += ncomps[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SAMpatchPara::initForAssembly (SystemVector& sysRHS,
|
||||
Vector* reactionForces) const
|
||||
{
|
||||
@@ -190,15 +379,19 @@ bool SAMpatchPara::assembleSystem (SystemVector& sysRHS,
|
||||
l2g[i] = meqn[l2g[i]]-1;
|
||||
}
|
||||
|
||||
// RUNAR
|
||||
PETScVector* pvec = dynamic_cast<PETScVector*>(&sysRHS);
|
||||
//PETScBlockVector* pvec = dynamic_cast<PETScBlockVector*>(&sysRHS);
|
||||
if (!pvec) return false;
|
||||
|
||||
std::vector<PetscInt> L2g(l2g.size());
|
||||
for (i = 0; i < l2g.size(); i++)
|
||||
L2g[i] = l2g[i];
|
||||
|
||||
// RUNAR
|
||||
// Add contributions to SV (righthand side)
|
||||
VecSetValues(pvec->getVector(),eSv.size(),&L2g[0],&eSv[0],ADD_VALUES);
|
||||
//VecSetValues(pvec->getVector(0),eSv.size(),&L2g[0],&eSv[0],ADD_VALUES);
|
||||
|
||||
// Add contributions to reaction forces
|
||||
if (reactionForces)
|
||||
@@ -244,6 +437,50 @@ bool SAMpatchPara::getElmEqns (IntVec& meen, int iel, int nedof) const
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getElmEqns (IntVec& meen, int iel, int f1, int f2, bool globalEq, int nedof) const
|
||||
{
|
||||
if (iel < 1 || iel > nel)
|
||||
{
|
||||
std::cerr <<"SAMpatchPara::getElmEqns: Element "<< iel
|
||||
<<" is out of range [1,"<< nel <<"]"<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int ip = mpmnpc[iel-1];
|
||||
int nenod = mpmnpc[iel] - ip;
|
||||
int oldof = nedof;
|
||||
if (nedof < 1) nedof = nenod*ndof/nnod;
|
||||
|
||||
int nf = ndof/nnod;
|
||||
int nbf = f2-f1+1;
|
||||
int nebdof = nenod*nbf;
|
||||
int stride = (globalEq) ? nf : nbf;
|
||||
|
||||
// Fields must be correct
|
||||
if (f2 < f1 || f1 < 0 || f2 >= nf)
|
||||
return false;
|
||||
|
||||
meen.clear();
|
||||
meen.reserve(nebdof);
|
||||
for (int i = 0; i < nenod; i++, ip++)
|
||||
{
|
||||
int node = mmnpc[ip-1];
|
||||
if (node > 0) {
|
||||
int dof = (globalEq) ? madof[node-1] : (node-1)*nbf + 1 + f1;
|
||||
for (int j = f1; j <= f2; j++, dof++)
|
||||
meen.push_back(dof);
|
||||
}
|
||||
else if (node < 0)
|
||||
meen.insert(meen.end(),f2-f1+1,0);
|
||||
}
|
||||
if ((int)meen.size() == nebdof || oldof < 1) return true;
|
||||
|
||||
std::cerr <<"SAMpatchPara::getElmEqns: Invalid element matrix dimension "
|
||||
<< nedof <<" (should have been "<< meen.size() <<")"<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::expandSolution (const SystemVector& solVec,
|
||||
Vector& dofVec, Real scaleSD) const
|
||||
{
|
||||
@@ -268,7 +505,11 @@ bool SAMpatchPara::expandSolution (const SystemVector& solVec,
|
||||
|
||||
return true;
|
||||
#else
|
||||
// RUNAR
|
||||
return this->expandVector(solVec.getRef(),dofVec,scaleSD);
|
||||
//SystemVector* sv = const_cast<SystemVector*>(&solVec);
|
||||
//PETScBlockVector* sb = dynamic_cast<PETScBlockVector*>(sv);
|
||||
//return this->expandVector(sb->getRef(0),dofVec,scaleSD);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -619,6 +860,77 @@ bool SAMpatchPara::getLocalSubdomains(std::vector<PetscIntVec>& locSubds,
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getLocalSubdomainsBlock(std::vector<PetscIntVec>& locSubds, int f1, int f2,
|
||||
int nx, int ny, int nz) const
|
||||
{
|
||||
// Define some parameters
|
||||
const int npatch = patch.size();
|
||||
const int nsd = patch[0]->getNoSpaceDim();
|
||||
|
||||
// Find min and max node for each patch on this processor
|
||||
IntVec maxNodeId, minNodeId;
|
||||
maxNodeId.resize(npatch,true);
|
||||
minNodeId.resize(npatch,true);
|
||||
|
||||
for (int n = 0;n < npatch;n++) {
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
|
||||
int min = 0;
|
||||
int max = 0;
|
||||
for (size_t i = 0;i < MLGN.size();i++) {
|
||||
if (MLGN[i] > max)
|
||||
max = MLGN[i];
|
||||
if (MLGN[i] < min)
|
||||
min = MLGN[i];
|
||||
}
|
||||
minNodeId[n] = min;
|
||||
maxNodeId[n] = max;
|
||||
}
|
||||
|
||||
minNodeId[0] = 1;
|
||||
for (int n = 1;n < npatch;n++)
|
||||
minNodeId[n] = maxNodeId[n-1] + 1;
|
||||
|
||||
#ifdef PARALLEL_PETSC
|
||||
// Adjust for parallel
|
||||
int myRank, nProc;
|
||||
MPI_Status status;
|
||||
MPI_Comm_rank(PETSC_COMM_WORLD,&myRank);
|
||||
MPI_Comm_size(PETSC_COMM_WORLD,&nProc);
|
||||
if (myRank < nProc-1)
|
||||
MPI_Send(&maxNodeId[npatch-1],1,MPI_INT,myRank+1,101,PETSC_COMM_WORLD);
|
||||
if (myRank > 0) {
|
||||
MPI_Recv(&minNodeId[0],1,MPI_INT,myRank-1,101,PETSC_COMM_WORLD,&status);
|
||||
minNodeId[0]++;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (nsd) {
|
||||
case 1:
|
||||
{
|
||||
IntVec nxVec;
|
||||
nxVec.assign(npatch,nx);
|
||||
return this->getLocalSubdomains1D(locSubds,nxVec,minNodeId,maxNodeId,f1,f2);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
IntVec nxVec(npatch); nxVec.assign(npatch,nx);
|
||||
IntVec nyVec(npatch); nyVec.assign(npatch,ny);
|
||||
return this->getLocalSubdomains2D(locSubds,nxVec,nyVec,minNodeId,maxNodeId,f1,f2);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
IntVec nxVec(npatch); nxVec.assign(npatch,nx);
|
||||
IntVec nyVec(npatch); nyVec.assign(npatch,ny);
|
||||
IntVec nzVec(npatch); nzVec.assign(npatch,nz);
|
||||
return this->getLocalSubdomains3D(locSubds,nxVec,nyVec,nzVec,minNodeId,maxNodeId,f1,f2);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getSubdomains(std::vector<PetscIntVec>& subds, int overlap,
|
||||
int nx, int ny, int nz) const
|
||||
{
|
||||
@@ -651,6 +963,38 @@ bool SAMpatchPara::getSubdomains(std::vector<PetscIntVec>& subds, int overlap,
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getSubdomainsBlock(std::vector<PetscIntVec>& subds, int f1, int f2,
|
||||
int overlap, int nx, int ny, int nz) const
|
||||
{
|
||||
// Define some parameters
|
||||
const int npatch = patch.size();
|
||||
const int nsd = patch[0]->getNoSpaceDim();
|
||||
|
||||
switch (nsd) {
|
||||
case 1:
|
||||
{
|
||||
IntVec nxVec(npatch); nxVec.assign(npatch,nx);
|
||||
return this->getSubdomains1D(subds,nxVec,overlap,f1,f2);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
IntVec nxVec(npatch); nxVec.assign(npatch,nx);
|
||||
IntVec nyVec(npatch); nyVec.assign(npatch,ny);
|
||||
return this->getSubdomains2D(subds,nxVec,nyVec,overlap,f1,f2);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
IntVec nxVec(npatch); nxVec.assign(npatch,nx);
|
||||
IntVec nyVec(npatch); nyVec.assign(npatch,ny);
|
||||
IntVec nzVec(npatch); nzVec.assign(npatch,nz);
|
||||
return this->getSubdomains3D(subds,nxVec,nyVec,nzVec,overlap,f1,f2);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getLocalSubdomains1D(IntVec& nxvec, IntVec& minNodeId, IntVec& maxNodeId,
|
||||
std::vector<PetscIntVec>& locSubds) const
|
||||
{
|
||||
@@ -1036,3 +1380,416 @@ bool SAMpatchPara::getSubdomains3D(IntVec& nxvec, IntVec& nyvec, IntVec& nzvec,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getLocalSubdomains1D(std::vector<PetscIntVec>& locSubds, IntVec& nxvec,
|
||||
IntVec& minNodeId, IntVec& maxNodeId, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod;
|
||||
ASMs1D* pch1 = dynamic_cast<ASMs1D*>(patch[n]);
|
||||
if (pch1)
|
||||
nnod = pch1->getCurve()->numCoefs();
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int n1 = nnod/nx;
|
||||
|
||||
int nfield = f2-f1+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int i1 = p1*n1;
|
||||
int i2 = (p1+1)*n1;
|
||||
if ((p1 == nx-1) && (i2 < nnod)) i2 = nnod;
|
||||
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int globNode = MLGN[i];
|
||||
|
||||
if (globNode >= minNodeId[n] && globNode <= maxNodeId[n]) {
|
||||
int nodedof = madof[globNode-1];
|
||||
int gdof = meqn[nodedof-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(i+1);
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locSubds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getLocalSubdomains2D(std::vector<PetscIntVec>& locSubds, IntVec& nxvec, IntVec& nyvec,
|
||||
IntVec& minNodeId, IntVec& maxNodeId, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch || nyvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod1, nnod2;
|
||||
ASMs2D* pch2 = dynamic_cast<ASMs2D*>(patch[n]);
|
||||
if (pch2) {
|
||||
nnod1 = pch2->getSurface()->numCoefs_u();
|
||||
nnod2 = pch2->getSurface()->numCoefs_v();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int ny = nyvec[n];
|
||||
int n1 = nnod1/nx;
|
||||
int n2 = nnod2/ny;
|
||||
|
||||
int nfield = f2-f1+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p2 = 0;p2 < ny;p2++) {
|
||||
int j1 = p2*n2;
|
||||
int j2 = (p2+1)*n2;
|
||||
if ((p2 == ny-1) && (j2 < nnod2)) j2 = nnod2;
|
||||
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int i1 = p1*n1;
|
||||
int i2 = (p1+1)*n1;
|
||||
if ((p1 == nx-1) && (i2 < nnod1)) i2 = nnod1;
|
||||
|
||||
for (int j = j1;j < j2;j++)
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int locNode = j*nnod1 + i;
|
||||
int globNode = MLGN[locNode];
|
||||
|
||||
if (globNode >= minNodeId[n] && globNode <= maxNodeId[n]) {
|
||||
int nodedof = madof[globNode-1];
|
||||
int gdof = meqn[nodedof-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(locNode+1);
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locSubds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getLocalSubdomains3D(std::vector<PetscIntVec>& locSubds, IntVec& nxvec, IntVec& nyvec, IntVec& nzvec,
|
||||
IntVec& minNodeId, IntVec& maxNodeId, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch || nyvec.size() != npatch || nzvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod1, nnod2, nnod3;
|
||||
ASMs3D* pch3 = dynamic_cast<ASMs3D*>(patch[n]);
|
||||
if (pch3) {
|
||||
nnod1 = pch3->getVolume()->numCoefs(0);
|
||||
nnod2 = pch3->getVolume()->numCoefs(1);
|
||||
nnod3 = pch3->getVolume()->numCoefs(2);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int ny = nyvec[n];
|
||||
int nz = nzvec[n];
|
||||
int n1 = nnod1/nx;
|
||||
int n2 = nnod2/ny;
|
||||
int n3 = nnod3/nz;
|
||||
|
||||
int nfield = f2-f1+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p3 = 0;p3 < nz;p3++) {
|
||||
int k1 = p3*n3;
|
||||
int k2 = (p3+1)*n3;
|
||||
if ((p3 == nz-1) && (k2 < nnod3)) k2 = nnod3;
|
||||
|
||||
for (int p2 = 0;p2 < ny;p2++) {
|
||||
int j1 = p2*n2;
|
||||
int j2 = (p2+1)*n2;
|
||||
if ((p2 == ny-1) && (j2 < nnod2)) j2 = nnod2;
|
||||
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int i1 = p1*n1;
|
||||
int i2 = (p1+1)*n1;
|
||||
if ((p1 == nx-1) && (i2 < nnod1)) i2 = nnod1;
|
||||
|
||||
for (int k = k1;k < k2;k++)
|
||||
for (int j = j1;j < j2;j++)
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int locNode = k*nnod3*nnod2 + j*nnod1 + i;
|
||||
int globNode = MLGN[locNode];
|
||||
|
||||
if (globNode >= minNodeId[n] && globNode <= maxNodeId[n]) {
|
||||
int nodedof = madof[globNode-1];
|
||||
int gdof = meqn[nodedof-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(locNode+1);
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locSubds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getSubdomains1D(std::vector<PetscIntVec>& subds, IntVec& nxvec, int overlap, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Overlap
|
||||
int olow = overlap/2;
|
||||
int ohigh = overlap/2 + overlap%2;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod;
|
||||
ASMs1D* pch1 = dynamic_cast<ASMs1D*>(patch[n]);
|
||||
if (pch1)
|
||||
nnod = pch1->getCurve()->numCoefs();
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int n1 = nnod/nx;
|
||||
|
||||
int nfield = f2-f1+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int min = 0;
|
||||
int i1 = std::max(p1*n1 - olow,min);
|
||||
int i2 = std::min((p1+1)*n1+ohigh,nnod);
|
||||
if ((p1 == nx-1) && (i2 < nnod)) i2 = nnod;
|
||||
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int globNode = MLGN[i];
|
||||
int nodedof = madof[globNode-1];
|
||||
int gdof = meqn[nodedof-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(i+1);
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
|
||||
subds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getSubdomains2D(std::vector<PetscIntVec>& subds, IntVec& nxvec, IntVec& nyvec,
|
||||
int overlap, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch || nyvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Overlap
|
||||
int olow = overlap/2;
|
||||
int ohigh = overlap/2 + overlap%2;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod1, nnod2;
|
||||
ASMs2D* pch2 = dynamic_cast<ASMs2D*>(patch[n]);
|
||||
if (pch2) {
|
||||
nnod1 = pch2->getSurface()->numCoefs_u();
|
||||
nnod2 = pch2->getSurface()->numCoefs_v();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int ny = nyvec[n];
|
||||
int n1 = nnod1/nx;
|
||||
int n2 = nnod2/ny;
|
||||
|
||||
int nfield = f2-f1+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p2 = 0;p2 < ny;p2++) {
|
||||
int jmin = 0;
|
||||
int j1 = std::max(p2*n2-olow,jmin);
|
||||
int j2 = std::min((p2+1)*n2+ohigh,nnod2);
|
||||
if ((p2 == ny-1) && (j2 < nnod2)) j2 = nnod2;
|
||||
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int imin = 0;
|
||||
int i1 = std::max(p1*n1-olow,imin);
|
||||
int i2 = std::min((p1+1)*n1+ohigh,nnod1);
|
||||
if ((p1 == nx-1) && (i2 < nnod1)) i2 = nnod1;
|
||||
|
||||
for (int j = j1;j < j2;j++)
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int locNode = j*nnod1 + i;
|
||||
int globNode = MLGN[locNode];
|
||||
|
||||
int nodedof = madof[globNode-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(locNode+1);
|
||||
|
||||
int gdof = meqn[nodedof-1];
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
|
||||
subds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SAMpatchPara::getSubdomains3D(std::vector<PetscIntVec>& subds, IntVec& nxvec, IntVec& nyvec, IntVec& nzvec,
|
||||
int overlap, int f1, int f2) const
|
||||
{
|
||||
// Define some parameters
|
||||
const size_t npatch = patch.size();
|
||||
|
||||
if (nxvec.size() != npatch || nyvec.size() != npatch || nzvec.size() != npatch)
|
||||
return false;
|
||||
|
||||
// Overlap
|
||||
int olow = overlap/2;
|
||||
int ohigh = overlap/2 + overlap%2;
|
||||
|
||||
// Split the patches into smaller subdomains
|
||||
for (size_t n = 0;n < npatch;n++) {
|
||||
int nnod1, nnod2, nnod3;
|
||||
ASMs3D* pch3 = dynamic_cast<ASMs3D*>(patch[n]);
|
||||
if (pch3) {
|
||||
nnod1 = pch3->getVolume()->numCoefs(0);
|
||||
nnod2 = pch3->getVolume()->numCoefs(1);
|
||||
nnod3 = pch3->getVolume()->numCoefs(2);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
int nx = nxvec[n];
|
||||
int ny = nyvec[n];
|
||||
int nz = nzvec[n];
|
||||
int n1 = nnod1/nx;
|
||||
int n2 = nnod2/ny;
|
||||
int n3 = nnod3/nz;
|
||||
|
||||
int nfield = f2-f2+1;
|
||||
|
||||
const IntVec& MLGN = patch[n]->getGlobalNodeNums();
|
||||
for (int p3 = 0;p3 < nz;p3++) {
|
||||
int kmin = 0;
|
||||
int k1 = std::max(p3*n3-olow,kmin);
|
||||
int k2 = std::min((p3+1)*n3+ohigh,nnod3);
|
||||
if ((p3 == nz-1) && (k2 < nnod3)) k2 = nnod3;
|
||||
|
||||
for (int p2 = 0;p2 < ny;p2++) {
|
||||
int jmin = 0;
|
||||
int j1 = std::max(p2*n2-olow,jmin);
|
||||
int j2 = std::min((p2+1)*n2+ohigh,nnod2);
|
||||
if ((p2 == ny-1) && (j2 < nnod2)) j2 = nnod2;
|
||||
|
||||
for (int p1 = 0;p1 < nx;p1++) {
|
||||
PetscIntVec subdDofs;
|
||||
|
||||
int imin = 0;
|
||||
int i1 = std::max(p1*n1-olow,imin);
|
||||
int i2 = std::min((p1+1)*n1+ohigh,nnod1);
|
||||
if ((p1 == nx-1) && (i2 < nnod1)) i2 = nnod1;
|
||||
|
||||
for (int k = k1;k < k2;k++)
|
||||
for (int j = j1;j < j2;j++)
|
||||
for (int i = i1;i < i2;i++) {
|
||||
int locNode = k*nnod3*nnod2 + j*nnod1 + i;
|
||||
int globNode = MLGN[locNode];
|
||||
|
||||
int nodedof = madof[globNode-1];
|
||||
int nnodedof = patch[n]->getNodalDOFs(locNode+1);
|
||||
|
||||
int gdof = meqn[nodedof-1];
|
||||
int gbnodedof = (gdof-1)/nnodedof;
|
||||
|
||||
for (int m = 0;m < nfield;m++) {
|
||||
PetscInt ieq = gbnodedof*nfield+m;
|
||||
if (ieq > -1)
|
||||
subdDofs.push_back(ieq);
|
||||
}
|
||||
}
|
||||
|
||||
subds.push_back(subdDofs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
//! \brief Returns the number of equations (free DOFs) on this processor.
|
||||
virtual int getNoEquations() const { return nleq; }
|
||||
|
||||
//! \brief Returns equation numbers
|
||||
virtual bool getEqns(IntVec& eqns, int f1, int f2) const;
|
||||
|
||||
//! \brief Computes number of couplings for each local dof
|
||||
//! in a distributed matrix.
|
||||
//! \param[in] ifirst Global number of first local DOF
|
||||
@@ -56,6 +59,17 @@ public:
|
||||
virtual bool getNoDofCouplings(int ifirst, int ilast,
|
||||
IntVec& d_nnz, IntVec& o_nnz) const;
|
||||
|
||||
//! \brief Computes number of couplings for each local dof
|
||||
//! in a distributed matrix.
|
||||
//! \param[in] ifirst First equation number
|
||||
//! \param[in] ilast Last equation number
|
||||
//! \param[out] d_nnz Number of diagonal couplings for each local DOF
|
||||
//! \param[out] o_nnz Number of off-diagonal couplings for each local DOF
|
||||
//! \return \e false if number of couplings is not computed, otherwise \e true
|
||||
virtual bool getNoDofCouplings(int ifirst, int ilast, IntVec ncomps,
|
||||
std::vector<std::vector<IntVec> >& d_nnz,
|
||||
std::vector<std::vector<IntVec> >& o_nnz) const;
|
||||
|
||||
//! \brief Initializes the system load vector prior to the element assembly.
|
||||
//! \param sysRHS The system right-hand-side load vector to be initialized
|
||||
//! \param reactionForces Pointer to vector of nodal reaction forces
|
||||
@@ -92,6 +106,14 @@ public:
|
||||
//! \param[in] nedof Number of degrees of freedom in the element
|
||||
//! (used for internal consistency checking, unless zero)
|
||||
virtual bool getElmEqns(IntVec& meen, int iel, int nedof = 0) const;
|
||||
//! \brief Finds the matrix of equation numbers for an element.
|
||||
//! \param[out] meen Matrix of element equation numbers
|
||||
//! \param[in] iel Identifier for the element to get the equation numbers for
|
||||
//! \param[in] f1, f2 Field numbers (extract eqn numbers for field f1 to f2
|
||||
//! \param[in] nedof Number of degrees of freedom in the element
|
||||
//! (used for internal consistency checking, unless zero)
|
||||
virtual bool getElmEqns (IntVec& meen, int iel, int f1, int f2, bool globalEq = false, int nedof = 0) const;
|
||||
|
||||
|
||||
//! \brief Updates the multi-point constraint array \a TTCC.
|
||||
//! \param[in] model All spline patches in the model
|
||||
@@ -149,6 +171,21 @@ public:
|
||||
virtual bool getSubdomains(std::vector<PetscIntVec>& locSubds, int overlap = 1,
|
||||
int nx = 1, int ny = 1, int nz = 1) const;
|
||||
|
||||
//! \brief Split the local dofs corresponding to given fields into a number of unique subdomains
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
//! \param[in] f1, f2 First and last field to extract dofs from
|
||||
//! \param[in] nx, ny, nz Number of paritionings in each direction
|
||||
virtual bool getLocalSubdomainsBlock(std::vector<PetscIntVec>& locSubds, int f1 = 0, int f2 = 0,
|
||||
int nx = 1, int ny = 1, int nz = 1) const;
|
||||
|
||||
//! \brief Split the local dofs corresponding to given fields into a number of unique subdomains
|
||||
//! \param[out] subds Global node number for each of the subdomains
|
||||
//! \param[in] f1, f2 First and last field to extract dofs from
|
||||
//! \param[in] overlap Overlap between subdomains
|
||||
//! \param[in] nx, ny, nz Number of paritionings in each direction
|
||||
virtual bool getSubdomainsBlock(std::vector<PetscIntVec>& locSubds, int f1 = 0, int f2 = 0,
|
||||
int overlap = 1, int nx = 1, int ny = 1, int nz = 1) const;
|
||||
|
||||
protected:
|
||||
//! \brief Initializes the multi-point constraint arrays
|
||||
//! \a MPMCEQ, \a MMCEQ and \a TTCC.
|
||||
@@ -215,6 +252,62 @@ private:
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getSubdomains3D(IntVec& nx, IntVec& ny, IntVec& nz, int overlap,
|
||||
std::vector<PetscIntVec>& locSubds) const;
|
||||
|
||||
//! \brief Split the local dofs into a number of unique subdomains (1D problem)
|
||||
//! \param[in] nx Split each patch in npart smaller subdomains
|
||||
//! \param[in] minNodeId Minimum node number for each patch
|
||||
//! \param[in] maxNodeId Maximum node number for each patch
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getLocalSubdomains1D(std::vector<PetscIntVec>& locSubds, IntVec& nx, IntVec& minNodeId,
|
||||
IntVec& maxNodeId, int f1, int f2) const;
|
||||
|
||||
//! \brief Split the local dofs into a number of unique subdomains (1D problem)
|
||||
//! \param[in] nx, ny Split each patch in npart smaller subdomains
|
||||
//! \param[in] minNodeId Minimum node number for each patch
|
||||
//! \param[in] maxNodeId Maximum node number for each patch
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getLocalSubdomains2D(std::vector<PetscIntVec>& locSubds, IntVec& nx, IntVec& ny,
|
||||
IntVec& minNodeId, IntVec& maxNodeId, int f1, int f2) const;
|
||||
|
||||
//! \brief Split the local dofs into a number of unique subdomains (1D problem)
|
||||
//! \param[in] nx, ny, nz Split each patch in npart smaller subdomains
|
||||
//! \param[in] minNodeId Minimum node number for each patch
|
||||
//! \param[in] maxNodeId Maximum node number for each patch
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getLocalSubdomains3D(std::vector<PetscIntVec>& locSubds, IntVec& nx, IntVec& ny, IntVec& nz,
|
||||
IntVec& minNodeId, IntVec& maxNodeId, int f1, int f2) const;
|
||||
|
||||
//! \brief Split the dofs into a number of overlapping subdomains (1D problem)
|
||||
//! \param[in] nx Split each patch in npart smaller subdomains
|
||||
//! \param[in] overlap Overlap for subdomains
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getSubdomains1D(std::vector<PetscIntVec>& locSubds, IntVec& nx, int overlap, int f1, int f2) const;
|
||||
|
||||
//! \brief Split the local dofs into a number of unique subdomains (1D problem)
|
||||
//! \param[in] nx, ny Split each patch in npart smaller subdomains
|
||||
//! \param[in] overlap Overlap for subdomains
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getSubdomains2D(std::vector<PetscIntVec>& locSubds, IntVec& nx, IntVec& ny,
|
||||
int overlap, int f1, int f2) const;
|
||||
|
||||
//! \brief Split the local dofs into a number of unique subdomains (1D problem)
|
||||
//! \param[in] nx, ny, nz Split each patch in npart smaller subdomains
|
||||
//! \param[in] overlap Overlap for subdomains
|
||||
//! \param[in] f1 First field to compute subdomains for
|
||||
//! \param[in] f2 Last field to compute subdomains for
|
||||
//! \param[out] locSubds Global node number for each of the subdomains
|
||||
bool getSubdomains3D(std::vector<PetscIntVec>& locSubds, IntVec& nx, IntVec& ny, IntVec& nz,
|
||||
int overlap, int f1, int f2) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user