Commit 1e362fda authored by Chris Cantwell's avatar Chris Cantwell
Browse files

Merge branch 'feature/IncNSOpt' into 'master'

Improve performance of incompressible solver

This MR contains improvements to the performance of the incompressible solver (some of the changes might also help in other cases).

I worked on these changes based on a profiling of the `Cyl.xml` example (2D, N=5, using both tris and quads). For this particular case (in serial), I got a reduction of computational cost close to 30%, although I suspect simulations with higher order or in 3D will get more modest improvements.

The main changes are:

- Use a virtual function to make UnsteadySystem skip the FwdTrans it performs after each time step, since this is completely redundant for the incompressible solver
- Introduce a parameter to choose the frequency at which the solver checks for NaNs
- Tweak the default value of the mdswitch parameter for the multilevelstaticcond, and also allow to specify it in the session file
- Include PhysDeriv in a single direction in the Collections, since we need it to compute div(u) for the pressure forcing
- Use symmetric matrices for the interior part of the static cond (whenever possible)
- Several small changes to reduce overhead costs, especially in matrix vector multiplications.


See merge request !645
parents c976e139 07a2eddc
......@@ -75,6 +75,15 @@ class BwdTrans_StdMat : public Operator
0.0, output.get(), m_stdExp->GetTotPoints());
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
DNekMatSharedPtr m_mat;
......@@ -155,6 +164,15 @@ class BwdTrans_IterPerExp : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
private:
BwdTrans_IterPerExp(
vector<StdRegions::StdExpansionSharedPtr> pCollExp,
......@@ -229,6 +247,15 @@ class BwdTrans_NoCollection : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
vector<StdRegions::StdExpansionSharedPtr> m_expList;
......@@ -310,6 +337,15 @@ class BwdTrans_SumFac_Seg : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
......@@ -406,6 +442,15 @@ class BwdTrans_SumFac_Quad : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -495,6 +540,15 @@ class BwdTrans_SumFac_Tri : public Operator
&output[0], m_nquad0);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
......@@ -596,6 +650,15 @@ class BwdTrans_SumFac_Hex : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -755,6 +818,15 @@ class BwdTrans_SumFac_Tet : public Operator
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -887,6 +959,15 @@ class BwdTrans_SumFac_Prism : public Operator
0.0, output.get(), m_nquad0);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
......
......@@ -79,6 +79,12 @@ class Collection
Array<OneD, NekDouble> &output1,
Array<OneD, NekDouble> &output2);
inline void ApplyOperator(
const OperatorType &op,
int dir,
const Array<OneD, const NekDouble> &inarray,
Array<OneD, NekDouble> &output);
inline bool HasOperator(const OperatorType &op);
protected:
......@@ -135,6 +141,19 @@ inline void Collection::ApplyOperator(
(*m_ops[op])(inarray, output0, output1, output2, wsp);
}
/**
*
*/
inline void Collection::ApplyOperator(
const OperatorType &op,
int dir,
const Array<OneD, const NekDouble> &inarray,
Array<OneD, NekDouble> &output)
{
Array<OneD, NekDouble> wsp(m_ops[op]->GetWspSize());
(*m_ops[op])(dir, inarray, output, wsp);
}
inline bool Collection::HasOperator(const OperatorType &op)
{
return (m_ops.find(op) != m_ops.end());
......
......@@ -81,6 +81,15 @@ class IProductWRTBase_StdMat : public Operator
0.0, output.get(), m_stdExp->GetNcoeffs());
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
DNekMatSharedPtr m_mat;
Array<OneD, const NekDouble> m_jac;
......@@ -170,6 +179,15 @@ class IProductWRTBase_IterPerExp : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
Array<OneD, NekDouble> m_jac;
......@@ -270,6 +288,15 @@ class IProductWRTBase_NoCollection : public Operator
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
vector<StdRegions::StdExpansionSharedPtr> m_expList;
......@@ -364,6 +391,15 @@ class IProductWRTBase_SumFac_Seg : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nmodes0;
......@@ -422,6 +458,15 @@ class IProductWRTBase_SumFac_Quad : public Operator
m_jac, input, output, wsp);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -487,6 +532,15 @@ class IProductWRTBase_SumFac_Tri : public Operator
output,wsp);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -561,6 +615,15 @@ class IProductWRTBase_SumFac_Hex : public Operator
m_jac,input,output,wsp);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -639,6 +702,15 @@ class IProductWRTBase_SumFac_Tet : public Operator
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -722,6 +794,15 @@ class IProductWRTBase_SumFac_Prism : public Operator
m_jac,input,output,wsp);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......
......@@ -124,6 +124,15 @@ class IProductWRTDerivBase_StdMat : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
Array<OneD, DNekMatSharedPtr> m_iProdWRTStdDBase;
Array<TwoD, const NekDouble> m_derivFac;
......@@ -284,6 +293,15 @@ class IProductWRTDerivBase_IterPerExp : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
Array<TwoD, const NekDouble> m_derivFac;
Array<OneD, const NekDouble> m_jac;
......@@ -403,6 +421,15 @@ class IProductWRTDerivBase_NoCollection : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
int m_dim;
int m_coordim;
......@@ -498,6 +525,15 @@ class IProductWRTDerivBase_SumFac_Seg : public Operator
&output[0], m_nmodes0);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nmodes0;
......@@ -591,6 +627,15 @@ class IProductWRTDerivBase_SumFac_Quad : public Operator
Vmath::Vadd(m_numElmt*nmodes,tmp[0],1,output,1,output,1);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -730,6 +775,15 @@ class IProductWRTDerivBase_SumFac_Tri : public Operator
Vmath::Vadd(m_numElmt*nmodes,tmp[0],1,output,1,output,1);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -890,6 +944,15 @@ class IProductWRTDerivBase_SumFac_Hex : public Operator
Vmath::Vadd(m_numElmt*nmodes,tmp[0],1,output,1,output,1);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -1077,6 +1140,15 @@ class IProductWRTDerivBase_SumFac_Tet : public Operator
Vmath::Vadd(m_numElmt*nmodes,tmp[0],1,output,1,output,1);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
const int m_nquad1;
......@@ -1284,6 +1356,15 @@ class IProductWRTDerivBase_SumFac_Prism : public Operator
Vmath::Vadd(m_numElmt*nmodes,tmp[0],1,output,1,output,1);
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
ASSERTL0(false, "Not valid for this operator.");
}
protected:
const int m_nquad0;
......
......@@ -127,6 +127,13 @@ class Operator
Array<OneD, NekDouble> &wsp
= NullNekDouble1DArray) = 0;
COLLECTIONS_EXPORT virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp
= NullNekDouble1DArray) = 0;
COLLECTIONS_EXPORT virtual ~Operator();
/// Get the size of the required workspace
......
......@@ -105,6 +105,43 @@ class PhysDeriv_StdMat : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
int nPhys = m_stdExp->GetTotPoints();
int ntot = m_numElmt*nPhys;
Array<OneD, NekDouble> tmp0,tmp1,tmp2;
Array<OneD, Array<OneD, NekDouble> > Diff(3);
for(int i = 0; i < m_dim; ++i)
{
Diff[i] = wsp + i*ntot;
}
// calculate local derivatives
for(int i = 0; i < m_dim; ++i)
{
Blas::Dgemm('N', 'N', m_derivMat[i]->GetRows(), m_numElmt,
m_derivMat[i]->GetColumns(), 1.0,
m_derivMat[i]->GetRawPtr(),
m_derivMat[i]->GetRows(), input.get(), nPhys,
0.0, &Diff[i][0],nPhys);
}
// calculate full derivative
Vmath::Zero(ntot,output,1);
for(int j = 0; j < m_dim; ++j)
{
Vmath::Vvtvp (ntot, m_derivFac[dir*m_dim+j], 1,
Diff[j], 1,
output, 1,
output, 1);
}
}
protected:
Array<OneD, DNekMatSharedPtr> m_derivMat;
Array<TwoD, const NekDouble> m_derivFac;
......@@ -240,6 +277,42 @@ class PhysDeriv_IterPerExp : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
int nPhys = m_stdExp->GetTotPoints();
int ntot = m_numElmt*nPhys;
Array<OneD, NekDouble> tmp0,tmp1,tmp2;
Array<OneD, Array<OneD, NekDouble> > Diff(3);
for(int i = 0; i < m_dim; ++i)
{
Diff[i] = wsp + i*ntot;
}
// calculate local derivatives
for (int i = 0; i < m_numElmt; ++i)
{
m_stdExp->PhysDeriv(input + i*nPhys,
tmp0 = Diff[0] + i*nPhys,
tmp1 = Diff[1] + i*nPhys,
tmp2 = Diff[2] + i*nPhys);
}
// calculate full derivative
Vmath::Vmul(ntot,m_derivFac[dir*m_dim],1,Diff[0],1,output,1);
for(int j = 1; j < m_dim; ++j)
{
Vmath::Vvtvp (ntot, m_derivFac[dir*m_dim+j], 1,
Diff[j], 1,
output, 1,
output, 1);
}
}
protected:
Array<TwoD, const NekDouble> m_derivFac;
int m_dim;
......@@ -361,6 +434,23 @@ class PhysDeriv_NoCollection : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
const int nPhys = m_expList[0]->GetTotPoints();
Array<OneD, NekDouble> tmp;
// calculate local derivatives
for (int i = 0; i < m_numElmt; ++i)
{
m_expList[i]->PhysDeriv(dir, input + i*nPhys,
tmp = output + i*nPhys);
}
}
protected:
vector<StdRegions::StdExpansionSharedPtr> m_expList;
......@@ -456,6 +546,29 @@ class PhysDeriv_SumFac_Seg : public Operator
}
}
virtual void operator()(
int dir,
const Array<OneD, const NekDouble> &input,
Array<OneD, NekDouble> &output,
Array<OneD, NekDouble> &wsp)
{
const int nqcol = m_nquad0*m_numElmt;
ASSERTL1(wsp.num_elements() == m_wspSize,
"Incorrect workspace size");
ASSERTL1(input.num_elements() >= nqcol,
"Incorrect input size");
Array<OneD, NekDouble> diff0(nqcol, wsp);
Blas::Dgemm('N', 'N', m_nquad0, m_numElmt,
m_nquad0, 1.0, m_Deriv0, m_nquad0,
input.get(), m_nquad0, 0.0,
diff0.get(), m_nquad0);
Vmath::Vmul(nqcol, m_derivFac[dir], 1, diff0, 1, output, 1);
}
protected: