Skip to content

Commit

Permalink
changed: cache L2 projection matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
akva2 committed Jun 21, 2021
1 parent 9421df2 commit 704e181
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 77 deletions.
9 changes: 9 additions & 0 deletions src/ASM/ASMbase.C
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "ASM3D.h"
#include "IFEM.h"
#include "MPC.h"
#include "SparseMatrix.h"
#include "Tensor.h"
#include "Vec3.h"
#include "Vec3Oper.h"
Expand Down Expand Up @@ -63,6 +64,7 @@ ASMbase::ASMbase (unsigned char n_p, unsigned char n_s, unsigned char n_f)
nel = nnod = 0;
idx = 0;
firstIp = 0;
glbL2_A = nullptr;
}


Expand All @@ -80,6 +82,7 @@ ASMbase::ASMbase (const ASMbase& patch, unsigned char n_f)
nnod = patch.nnod;
idx = patch.idx;
firstIp = patch.firstIp;
glbL2_A = nullptr;
// Note: Properties are _not_ copied
}

Expand All @@ -96,6 +99,7 @@ ASMbase::ASMbase (const ASMbase& patch)
nnod = patch.nnod;
idx = patch.idx;
firstIp = patch.firstIp;
glbL2_A = nullptr;

// Only copy the regular part of the FE data, leave out any extraordinaries

Expand Down Expand Up @@ -127,6 +131,8 @@ ASMbase::~ASMbase ()
{
for (MPC* mpc : mpcs)
delete mpc;

delete glbL2_A;
}


Expand Down Expand Up @@ -174,6 +180,9 @@ void ASMbase::clear (bool retainGeometry)
BCode.clear();
dCode.clear();
mpcs.clear();

delete glbL2_A;
glbL2_A = nullptr;
}


Expand Down
2 changes: 2 additions & 0 deletions src/ASM/ASMbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,8 @@ class ASMbase
static int gEl; //!< Global element counter
static int gNod; //!< Global node counter

mutable SparseMatrix* glbL2_A = nullptr; //!< Global L2-projection (mass) matrix

private:
std::vector<char> myLMTypes; //!< Type of Lagrange multiplier ('L' or 'G')
std::set<size_t> myLMs; //!< Nodal indices of the Lagrange multipliers
Expand Down
110 changes: 60 additions & 50 deletions src/ASM/GlbL2projector.C
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public:
L2Mats(GlbL2& p, size_t nen, size_t nf, LocalIntegral* q = nullptr)
: gl2Int(p), elmData(q)
{
this->resize(1,nf);
this->resize(p.pA ? 1 : 0,nf);
this->redim(nen);
}

Expand All @@ -193,7 +193,8 @@ class L2GlobalInt : public GlobalIntegral
{
public:
//! \brief The constructor initializes the system matrix references.
L2GlobalInt(SparseMatrix& A_, StdVector& B_) : A(A_), B(B_) {}
L2GlobalInt(int dim_, SparseMatrix* A_, StdVector& B_)
: dim(dim_), A(A_), B(B_) {}

//! \brief Empty destructor.
virtual ~L2GlobalInt() {}
Expand All @@ -205,41 +206,47 @@ public:
for (size_t i = 0; i < elm->mnpc.size(); i++)
{
int inod = elm->mnpc[i]+1;
for (size_t j = 0; j < elm->mnpc.size(); j++)
{
int jnod = elm->mnpc[j]+1;
A(inod,jnod) += elm->A.front()(i+1,j+1);
if (A) {
for (size_t j = 0; j < elm->mnpc.size(); j++)
{
int jnod = elm->mnpc[j]+1;
(*A)(inod,jnod) += elm->A.front()(i+1,j+1);
}
}
for (const Vector& b : elm->b)
{
B(inod) += b[i];
inod += A.dim();
inod += dim;
}
}
return true;
}

private:
SparseMatrix& A; //!< Reference to left-hand-side matrix
int dim; //!< Dimension of matrix
SparseMatrix* A; //!< Reference to left-hand-side matrix
StdVector& B; //!< Reference to right-hand-side vector
};


GlbL2::GlbL2 (IntegrandBase* p, size_t n) : problem(p)
GlbL2::GlbL2 (IntegrandBase* p, size_t n, SparseMatrix* A) :
pA(A), problem(p)
{
nrhs = p->getNoFields(2);
this->allocate(n);
}


GlbL2::GlbL2 (FunctionBase* f, size_t n) : problem(nullptr), functions({f})
GlbL2::GlbL2 (FunctionBase* f, size_t n, SparseMatrix* A) :
pA(A), problem(nullptr), functions({f})
{
nrhs = f->dim();
this->allocate(n);
}


GlbL2::GlbL2 (const FunctionVec& f, size_t n) : problem(nullptr), functions(f)
GlbL2::GlbL2 (const FunctionVec& f, size_t n, SparseMatrix* A) :
pA(A), problem(nullptr), functions(f)
{
nrhs = 0;
for (FunctionBase* func : f)
Expand All @@ -250,32 +257,32 @@ GlbL2::GlbL2 (const FunctionVec& f, size_t n) : problem(nullptr), functions(f)

GlbL2::~GlbL2()
{
delete pA;
delete pB;
#ifdef HAS_PETSC
delete adm;
#endif
}


void GlbL2::allocate (size_t n)
{
#ifdef HAS_PETSC
adm = nullptr;
if (GlbL2::MatrixType == LinAlg::PETSC && GlbL2::SolverParams)
{
adm = new ProcessAdm();
pA = new PETScMatrix(*adm,*GlbL2::SolverParams);
pB = new PETScVector(*adm,n*nrhs);
static ProcessAdm adm;
if (!pA) {
pA = new PETScMatrix(adm,*GlbL2::SolverParams);
pA->redim(n,n);
}

pB = new PETScVector(adm,n*nrhs);
}
else
#endif
{
pA = new SparseMatrix(SparseMatrix::SUPERLU);
if (!pA) {
pA = new SparseMatrix(SparseMatrix::SUPERLU);
pA->redim(n,n);
}
pB = new StdVector(n*nrhs);
}

pA->redim(n,n);
}


Expand Down Expand Up @@ -353,7 +360,8 @@ bool GlbL2::evalInt (LocalIntegral& elmInt,
solPt.insert(solPt.end(),funcPt.begin(),funcPt.end());
}

gl2.A.front().outer_product(fe.N,fe.N,true,fe.detJxW);
if (!gl2.A.empty())
gl2.A.front().outer_product(fe.N,fe.N,true,fe.detJxW);
for (size_t j = 0; j < solPt.size(); j++)
gl2.b[j].add(fe.N,solPt[j]*fe.detJxW);

Expand All @@ -376,7 +384,8 @@ bool GlbL2::evalIntMx (LocalIntegral& elmInt,
if (!problem->diverged(fe.iGP+1))
return false;

gl2.A.front().outer_product(fe.N,fe.N,true,fe.detJxW);
if (!gl2.A.empty())
gl2.A.front().outer_product(fe.N,fe.N,true,fe.detJxW);
for (size_t j = 0; j < solPt.size(); j++)
gl2.b[j].add(fe.N,solPt[j]*fe.detJxW);

Expand Down Expand Up @@ -418,6 +427,7 @@ bool GlbL2::solve (Matrix& sField)
#if SP_DEBUG > 1
std::cout <<"\nSolution:"<< sField;
#endif

return true;
}

Expand Down Expand Up @@ -473,24 +483,24 @@ bool ASMbase::L2projection (Matrix& sField,
const TimeDomain& time)
{
PROFILE2("ASMbase::L2projection");

GlbL2 gl2(integrand,this->getNoNodes(1));
L2GlobalInt dummy(*gl2.pA,*gl2.pB);

gl2.preAssemble(MNPC,this->getNoElms(true));
GlbL2 gl2(integrand,this->getNoNodes(1),glbL2_A);
L2GlobalInt dummy(this->getNoNodes(1),glbL2_A ? nullptr : gl2.pA,*gl2.pB);
if (!glbL2_A)
gl2.preAssemble(MNPC,this->getNoElms(true));
glbL2_A = gl2.pA;
return this->integrate(gl2,dummy,time) && gl2.solve(sField);
}


bool ASMbase::L2projection (Matrix& sField, FunctionBase* function, double t)
{
PROFILE2("ASMbase::L2projection");

GlbL2 gl2(function,this->getNoNodes(1));
L2GlobalInt dummy(*gl2.pA,*gl2.pB);
GlbL2 gl2(function,this->getNoNodes(1),glbL2_A);
L2GlobalInt dummy(this->getNoNodes(1),glbL2_A ? nullptr : gl2.pA,*gl2.pB);
if (!glbL2_A)
gl2.preAssemble(MNPC,this->getNoElms(true));
glbL2_A = gl2.pA;
TimeDomain time; time.t = t;

gl2.preAssemble(MNPC,this->getNoElms(true));
return this->integrate(gl2,dummy,time) && gl2.solve(sField);
}

Expand All @@ -499,12 +509,12 @@ bool ASMbase::L2projection (const std::vector<Matrix*>& sField,
const FunctionVec& function, double t)
{
PROFILE2("ASMbase::L2projection");

GlbL2 gl2(function,this->getNoNodes(1));
L2GlobalInt dummy(*gl2.pA,*gl2.pB);
GlbL2 gl2(function,this->getNoNodes(1),glbL2_A);
L2GlobalInt dummy(this->getNoNodes(1),glbL2_A ? nullptr : gl2.pA,*gl2.pB);
if (!glbL2_A)
gl2.preAssemble(MNPC,this->getNoElms(true));
glbL2_A = gl2.pA;
TimeDomain time; time.t = t;

gl2.preAssemble(MNPC,this->getNoElms(true));
return this->integrate(gl2,dummy,time) && gl2.solve(sField);
}

Expand All @@ -520,44 +530,45 @@ bool ASMbase::globalL2projection (Matrix& sField,
// Assemble the projection matrices
size_t i, nnod = this->getNoProjectionNodes();
size_t j, ncomp = integrand.dim();
SparseMatrix* A;
StdVector* B;
switch (GlbL2::MatrixType) {
case LinAlg::UMFPACK:
A = new SparseMatrix(SparseMatrix::UMFPACK);
if (!glbL2_A)
glbL2_A = new SparseMatrix(SparseMatrix::UMFPACK);
B = new StdVector(nnod*ncomp);
break;
#ifdef HAS_PETSC
case LinAlg::PETSC:
if (GlbL2::SolverParams)
{
A = new PETScMatrix(ProcessAdm(), *GlbL2::SolverParams);
B = new PETScVector(ProcessAdm(), nnod*ncomp);
static ProcessAdm adm;
if (!glbL2_A)
glbL2_A = new PETScMatrix(adm, *GlbL2::SolverParams);
B = new PETScVector(adm, nnod*ncomp);
break;
}
#endif
default:
A = new SparseMatrix(SparseMatrix::SUPERLU);
glbL2_A = new SparseMatrix(SparseMatrix::SUPERLU);
B = new StdVector(nnod*ncomp);
}
A->redim(nnod,nnod);
glbL2_A->redim(nnod,nnod);

if (!this->assembleL2matrices(*A,*B,integrand,continuous))
if (!this->assembleL2matrices(*glbL2_A,*B,integrand,continuous))
{
delete A;
delete B;
return false;
}

#if SP_DEBUG > 1
std::cout <<"---- Matrix A -----\n"<< *A
std::cout <<"---- Matrix A -----\n"<< *glbL2_A
<<"-------------------"<< std::endl;
std::cout <<"---- Vector B -----"<< *B
<<"-------------------"<< std::endl;
#endif

// Solve the patch-global equation system
if (!A->solve(*B)) return false;
if (!glbL2_A->solve(*B)) return false;

// Store the control-point values of the projected field
sField.resize(ncomp,nnod);
Expand All @@ -569,7 +580,6 @@ bool ASMbase::globalL2projection (Matrix& sField,
std::cout <<"- Solution Vector -"<< sField
<<"-------------------"<< std::endl;
#endif
delete A;
delete B;
return true;
}
13 changes: 6 additions & 7 deletions src/ASM/GlbL2projector.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class FunctionBase;
class LinSolParams;
class SparseMatrix;
class StdVector;
class ProcessAdm;

typedef std::vector<int> IntVec; //!< Vector of integers
typedef std::vector<size_t> uIntVec; //!< Vector of unsigned integers
Expand Down Expand Up @@ -113,15 +112,18 @@ class GlbL2 : public Integrand
//! \brief The constructor initializes the projection matrices.
//! \param[in] p The main problem integrand
//! \param[in] n Dimension of the L2-projection matrices (number of nodes)
GlbL2(IntegrandBase* p, size_t n);
//! \param[in] A Sparse matrix to use
GlbL2(IntegrandBase* p, size_t n, SparseMatrix* A);
//! \brief Alternative constructor for projection of an explicit function.
//! \param[in] f The function to do L2-projection on
//! \param[in] n Dimension of the L2-projection matrices (number of nodes)
GlbL2(FunctionBase* f, size_t n);
//! \param[in] A Sparse matrix to use
GlbL2(FunctionBase* f, size_t n, SparseMatrix* A);
//! \brief Alternative constructor for projection of explicit functions.
//! \param[in] f The functions to do L2-projection on
//! \param[in] n Dimension of the L2-projection matrices (number of nodes)
GlbL2(const FunctionVec& f, size_t n);
//! \param[in] A Sparse matrix to use
GlbL2(const FunctionVec& f, size_t n, SparseMatrix* A);
//! \brief The destructor frees the system matrix and system vector.
virtual ~GlbL2();

Expand Down Expand Up @@ -203,9 +205,6 @@ class GlbL2 : public Integrand
IntegrandBase* problem; //!< The main problem integrand
FunctionVec functions; //!< Explicit functions to L2-project
size_t nrhs; //!< Number of right-hand-size vectors
#ifdef HAS_PETSC
ProcessAdm* adm; //!< Process administrator for PETSc
#endif
};

#endif
Loading

0 comments on commit 704e181

Please sign in to comment.