diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp index 5521ba2b0118ae3509eb276a0b25a0bbd099eaef..9e14abe960f7972a376269446b0fa04d5816171f 100644 --- a/Solver/dgAlgorithm.cpp +++ b/Solver/dgAlgorithm.cpp @@ -16,65 +16,74 @@ \int \vec{f} \cdot \grad \phi dv */ -void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe useless here) - const dgConservationLaw &claw, // the conservation law - const dgGroupOfElements & group, - fullMatrix<double> &solution, - fullMatrix<double> &residual // the residual - ) -{ +class dgResidualVolume { + dataCacheMap _cacheMap; + const dgConservationLaw &_claw; + int _nbFields; + dataCacheElement &_cacheElement; + dataCacheDouble &_UVW, &_solutionQPe, &_gradientSolutionQPe; + dataCacheDouble *_sourceTerm, *_convectiveFlux, *_diffusiveFlux; + public: + dgResidualVolume (const dgConservationLaw &claw); + void compute1Group(dgGroupOfElements &group, fullMatrix<double> &solution, fullMatrix<double> &residual); + void computeAndMap1Group(dgGroupOfElements &group, dgDofContainer &solution, dgDofContainer &residual); +}; + +dgResidualVolume::dgResidualVolume(const dgConservationLaw &claw): + _claw(claw), + _nbFields(_claw.getNbFields()), + _cacheElement(_cacheMap.getElement()), + _UVW(_cacheMap.provideData("UVW", 1, 3)), + _solutionQPe(_cacheMap.provideData("Solution", 1, _nbFields)), + _gradientSolutionQPe(_cacheMap.provideData("SolutionGradient", 3, _nbFields)), + _sourceTerm(_claw.newSourceTerm(_cacheMap)), + _convectiveFlux(_claw.newConvectiveFlux(_cacheMap)), + _diffusiveFlux(_claw.newDiffusiveFlux(_cacheMap)) +{ +} + +void dgResidualVolume::compute1Group(dgGroupOfElements &group, fullMatrix<double> &solution, fullMatrix<double> &residual) +{ + residual.scale(0); + _cacheMap.setNbEvaluationPoints(group.getNbIntegrationPoints()); + _UVW.set(group.getIntegrationPointsMatrix()); // ----- 1 ---- get the solution at quadrature points // ----- 1.1 --- allocate a matrix of size (nbFields * nbElements, nbQuadraturePoints) - int nbFields = claw.getNbFields(); - fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),group.getNbElements() * nbFields); + fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),group.getNbElements() * _nbFields); // ----- 1.2 --- multiply the solution by the collocation matrix group.getCollocationMatrix().mult(solution , solutionQP); - // ----- 2 ---- compute all fluxes (diffusive and convective) at integration points // ----- 2.1 --- allocate elementary fluxes (compued in XYZ coordinates) - fullMatrix<double> fConv[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), nbFields ), - fullMatrix<double>( group.getNbIntegrationPoints(), nbFields ), - fullMatrix<double>( group.getNbIntegrationPoints(), nbFields )}; - fullMatrix<double> fDiff[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), nbFields ), - fullMatrix<double>( group.getNbIntegrationPoints(), nbFields ), - fullMatrix<double>( group.getNbIntegrationPoints(), nbFields )}; - fullMatrix<double> Source = fullMatrix<double> (group.getNbIntegrationPoints(),group.getNbElements() * nbFields); + fullMatrix<double> fConv[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields ), + fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields ), + fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields )}; + fullMatrix<double> fDiff[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields ), + fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields ), + fullMatrix<double>( group.getNbIntegrationPoints(), _nbFields )}; + fullMatrix<double> Source = fullMatrix<double> (group.getNbIntegrationPoints(),group.getNbElements() * _nbFields); // ----- 2.2 --- allocate parametric fluxes (computed in UVW coordinates) for all elements at all integration points - fullMatrix<double> Fuvw[3] = {fullMatrix<double> ( group.getNbIntegrationPoints(), group.getNbElements() * nbFields), - fullMatrix<double> (group.getNbIntegrationPoints(), group.getNbElements() * nbFields), - fullMatrix<double> (group.getNbIntegrationPoints(), group.getNbElements() * nbFields)}; - dataCacheMap cacheMap; - cacheMap.setNbEvaluationPoints(group.getNbIntegrationPoints()); - dataCacheElement &cacheElement = cacheMap.getElement(); - // provided dataCache - cacheMap.provideData("UVW",1,3).set(group.getIntegrationPointsMatrix()); - dataCacheDouble &solutionQPe = cacheMap.provideData("Solution",1,nbFields); - dataCacheDouble &gradientSolutionQPe = cacheMap.provideData("SolutionGradient",3,nbFields); - // needed dataCache - dataCacheDouble *sourceTerm = claw.newSourceTerm(cacheMap); - // fluxes in XYZ coordinates; - dataCacheDouble *convectiveFlux = claw.newConvectiveFlux(cacheMap); - dataCacheDouble *diffusiveFlux = claw.newDiffusiveFlux(cacheMap); - + fullMatrix<double> Fuvw[3] = {fullMatrix<double> ( group.getNbIntegrationPoints(), group.getNbElements() * _nbFields), + fullMatrix<double> (group.getNbIntegrationPoints(), group.getNbElements() * _nbFields), + fullMatrix<double> (group.getNbIntegrationPoints(), group.getNbElements() * _nbFields)}; fullMatrix<double> fuvwe; fullMatrix<double> source; fullMatrix<double> dPsiDx,dofs; // ----- 2.3 --- iterate on elements for (int iElement=0 ; iElement<group.getNbElements() ;++iElement) { // ----- 2.3.1 --- build a small object that contains elementary solution, jacobians, gmsh element - solutionQPe.setAsProxy(solutionQP, iElement*nbFields, nbFields ); - - if(gradientSolutionQPe.somethingDependOnMe()){ + _solutionQPe.setAsProxy(solutionQP, iElement*_nbFields, _nbFields ); + + if(_gradientSolutionQPe.somethingDependOnMe()){ dPsiDx.setAsProxy(group.getDPsiDx(),iElement*group.getNbNodes(),group.getNbNodes()); - dofs.setAsProxy(solution, nbFields*iElement, nbFields); - dPsiDx.mult(dofs, gradientSolutionQPe.set()); + dofs.setAsProxy(solution, _nbFields*iElement, _nbFields); + dPsiDx.mult(dofs, _gradientSolutionQPe.set()); } - cacheElement.set(group.getElement(iElement)); - if(convectiveFlux || diffusiveFlux) { + _cacheElement.set(group.getElement(iElement)); + if(_convectiveFlux || _diffusiveFlux) { // ----- 2.3.3 --- compute fluxes in UVW coordinates for (int iUVW=0;iUVW<group.getDimUVW();iUVW++) { // ----- 2.3.3.1 --- get a proxy on the big local flux matrix - fuvwe.setAsProxy(Fuvw[iUVW], iElement*nbFields,nbFields); + fuvwe.setAsProxy(Fuvw[iUVW], iElement*_nbFields,_nbFields); // ----- 2.3.3.1 --- compute \vec{f}^{UVW} =\vec{f}^{XYZ} J^{-1} and multiply bt detJ for (int iXYZ=0;iXYZ<group.getDimXYZ();iXYZ++) { for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) { @@ -84,40 +93,85 @@ void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe const double detJ = group.getDetJ (iElement, iPt); const double factor = invJ * detJ; // compute fluxes in the reference coordinate system at this integration point - for (int k=0;k<nbFields;k++){ - if(convectiveFlux) - fuvwe(iPt,k) += ( (*convectiveFlux)(iPt,iXYZ*nbFields+k)) * factor; - if(diffusiveFlux){ - fuvwe(iPt,k) += ( (*diffusiveFlux)(iPt,iXYZ*nbFields+k)) * factor; + for (int k=0;k<_nbFields;k++){ + if(_convectiveFlux) + fuvwe(iPt,k) += ( (*_convectiveFlux)(iPt,iXYZ*_nbFields+k)) * factor; + if(_diffusiveFlux){ + fuvwe(iPt,k) += ( (*_diffusiveFlux)(iPt,iXYZ*_nbFields+k)) * factor; } } } } } } - if (sourceTerm){ - source.setAsProxy(Source, iElement*claw.getNbFields(),claw.getNbFields()); + if (_sourceTerm){ + source.setAsProxy(Source, iElement*_nbFields,_nbFields); for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) { const double detJ = group.getDetJ (iElement, iPt); - for (int k=0;k<nbFields;k++){ - source(iPt,k) = (*sourceTerm)(iPt,k)*detJ; + for (int k=0;k<_nbFields;k++){ + source(iPt,k) = (*_sourceTerm)(iPt,k)*detJ; } } } } + // ----- 3 ---- do the redistribution at nodes using as many BLAS3 operations as there are local coordinates - if(convectiveFlux || diffusiveFlux){ + if(_convectiveFlux || _diffusiveFlux){ for (int iUVW=0;iUVW<group.getDimUVW();iUVW++){ residual.gemm(group.getFluxRedistributionMatrix(iUVW),Fuvw[iUVW]); } } - if(sourceTerm){ + if(_sourceTerm){ residual.gemm(group.getSourceRedistributionMatrix(),Source); } } -void dgAlgorithm::residualInterface ( //dofManager &dof, // the DOF manager (maybe useless here) - const dgConservationLaw &claw, // the conservation law +void dgResidualVolume::computeAndMap1Group(dgGroupOfElements &group, dgDofContainer &solution, dgDofContainer &residual) +{ + compute1Group (group, solution.getGroupProxy(&group), residual.getGroupProxy(&group)); +} + +class dgResidualInterface { + dataCacheMap _cacheMapLeft, _cacheMapRight; + const dgConservationLaw &_claw; + int _nbFields; + dataCacheElement &_cacheElementLeft, &_cacheElementRight; + dataCacheDouble &_uvwLeft, &_uvwRight, &_solutionQPLeft, &_solutionQPRight, &_gradientSolutionLeft, &_gradientSolutionRight; + dataCacheDouble &_normals; + dataCacheDouble *_riemannSolver, *_maximumDiffusivityLeft,*_maximumDiffusivityRight, *_diffusiveFluxLeft, *_diffusiveFluxRight; + public: + dgResidualInterface (const dgConservationLaw &claw); + void compute1Group ( //dofManager &dof, // the DOF manager (maybe useless here) + dgGroupOfFaces &group, + const fullMatrix<double> &solution, // solution !! at faces nodes + fullMatrix<double> &solutionLeft, + fullMatrix<double> &solutionRight, + fullMatrix<double> &residual // residual !! at faces nodes + ); + void computeAndMap1Group (dgGroupOfFaces &faces, dgDofContainer &solution, dgDofContainer &residual); +}; + +dgResidualInterface::dgResidualInterface (const dgConservationLaw &claw) : + _claw(claw), + _nbFields(claw.getNbFields()), + _cacheElementLeft(_cacheMapLeft.getElement()), + _cacheElementRight(_cacheMapRight.getElement()), + _uvwLeft(_cacheMapLeft.provideData("UVW",1,3)), + _uvwRight(_cacheMapRight.provideData("UVW",1,3)), + _solutionQPLeft(_cacheMapLeft.provideData("Solution",1,_nbFields)), + _solutionQPRight(_cacheMapRight.provideData("Solution",1,_nbFields)), + _gradientSolutionLeft(_cacheMapLeft.provideData("SolutionGradient",3,_nbFields)), + _gradientSolutionRight(_cacheMapRight.provideData("SolutionGradient",3,_nbFields)), + _normals(_cacheMapLeft.provideData("Normals",1,1)), + _riemannSolver(claw.newRiemannSolver(_cacheMapLeft,_cacheMapRight)), + _diffusiveFluxLeft(claw.newDiffusiveFlux(_cacheMapLeft)), + _diffusiveFluxRight(claw.newDiffusiveFlux(_cacheMapRight)), + _maximumDiffusivityLeft(claw.newMaximumDiffusivity(_cacheMapLeft)), + _maximumDiffusivityRight(claw.newMaximumDiffusivity(_cacheMapRight)) +{ +} + +void dgResidualInterface::compute1Group ( //dofManager &dof, // the DOF manager (maybe useless here) dgGroupOfFaces &group, const fullMatrix<double> &solution, // solution !! at faces nodes fullMatrix<double> &solutionLeft, @@ -127,297 +181,120 @@ void dgAlgorithm::residualInterface ( //dofManager &dof, // the DOF manager (may { // A) global operations before entering the loop over the faces // A1 ) copy locally some references from the group for the sake of lisibility - int nbFields = claw.getNbFields(); int nbNodesLeft = group.getGroupLeft().getNbNodes(); int nbNodesRight = group.getGroupRight().getNbNodes(); int nbFaces = group.getNbElements(); //get matrices needed to compute the gradient on both sides fullMatrix<double> &DPsiLeftDx = group.getDPsiLeftDxMatrix(); fullMatrix<double> &DPsiRightDx = group.getDPsiRightDxMatrix(); - // ----- 1 ---- get the solution at quadrature points - fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),nbFaces * nbFields*2); + fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),nbFaces * _nbFields*2); group.getCollocationMatrix().mult(solution, solutionQP); // needed tocompute normal fluxes at integration points - fullMatrix<double> NormalFluxQP ( group.getNbIntegrationPoints(), nbFaces*nbFields*2); - + fullMatrix<double> NormalFluxQP ( group.getNbIntegrationPoints(), nbFaces*_nbFields*2); // create one dataCache for each side - dataCacheMap cacheMapLeft; - cacheMapLeft.setNbEvaluationPoints(group.getNbIntegrationPoints()); - dataCacheMap cacheMapRight; - cacheMapRight.setNbEvaluationPoints(group.getNbIntegrationPoints()); - - // data this algorithm provide to the cache map (we can maybe move each data to a separate function but - // I think It's easier like this) - dataCacheDouble &normals = cacheMapLeft.provideData("Normals",1,1); - dataCacheElement &cacheElementLeft = cacheMapLeft.getElement(); - dataCacheElement &cacheElementRight = cacheMapRight.getElement(); - dataCacheDouble &uvwLeft = cacheMapLeft.provideData("UVW",1,3); - dataCacheDouble &uvwRight = cacheMapRight.provideData("UVW",1,3); - dataCacheDouble &solutionQPLeft = cacheMapLeft.provideData("Solution",1,nbFields); - dataCacheDouble &solutionQPRight = cacheMapRight.provideData("Solution",1,nbFields); - dataCacheDouble &gradientSolutionLeft = cacheMapLeft.provideData("SolutionGradient",3,nbFields); - dataCacheDouble &gradientSolutionRight = cacheMapRight.provideData("SolutionGradient",3,nbFields); - - // A2 ) ask the law to provide the fluxes (possibly NULL) - dataCacheDouble *riemannSolver = claw.newRiemannSolver(cacheMapLeft,cacheMapRight); - dataCacheDouble *diffusiveFluxLeft = claw.newDiffusiveFlux(cacheMapLeft); - dataCacheDouble *maximumDiffusivityLeft = claw.newMaximumDiffusivity(cacheMapLeft); - dataCacheDouble *maximumDiffusivityRight = claw.newMaximumDiffusivity(cacheMapRight); - dataCacheDouble *diffusiveFluxRight = claw.newDiffusiveFlux(cacheMapRight); + _cacheMapLeft.setNbEvaluationPoints(group.getNbIntegrationPoints()); + _cacheMapRight.setNbEvaluationPoints(group.getNbIntegrationPoints()); fullMatrix<double> dPsiLeftDx,dPsiRightDx,dofsLeft,dofsRight,normalFluxQP; - int p = group.getGroupLeft().getOrder(); int dim = group.getGroupLeft().getElement(0)->getDim(); - for (int iFace=0 ; iFace < nbFaces ; ++iFace) { // B1 ) adjust the proxies for this element // NB : the B1 section will almost completely disapear // if we write a function (from the function class) for moving proxies across big matrices // give the current elements to the dataCacheMap - cacheElementLeft.set(group.getElementLeft(iFace)); - cacheElementRight.set(group.getElementRight(iFace)); + _cacheElementLeft.set(group.getElementLeft(iFace)); + _cacheElementRight.set(group.getElementRight(iFace)); // proxies for the solution - solutionQPLeft.setAsProxy(solutionQP, iFace*2*nbFields, nbFields); - solutionQPRight.setAsProxy(solutionQP, (iFace*2+1)*nbFields, nbFields); - normals.setAsProxy(group.getNormals(), iFace*group.getNbIntegrationPoints(),group.getNbIntegrationPoints()); + _solutionQPLeft.setAsProxy(solutionQP, iFace*2*_nbFields, _nbFields); + _solutionQPRight.setAsProxy(solutionQP, (iFace*2+1)*_nbFields, _nbFields); + _normals.setAsProxy(group.getNormals(), iFace*group.getNbIntegrationPoints(),group.getNbIntegrationPoints()); // proxies needed to compute the gradient of the solution and the IP term dPsiLeftDx.setAsProxy(DPsiLeftDx,iFace*nbNodesLeft,nbNodesLeft); dPsiRightDx.setAsProxy(DPsiRightDx,iFace*nbNodesRight,nbNodesRight); - dofsLeft.setAsProxy(solutionLeft, nbFields*group.getElementLeftId(iFace), nbFields); - dofsRight.setAsProxy(solutionRight, nbFields*group.getElementRightId(iFace), nbFields); - uvwLeft.setAsProxy(group.getIntegrationOnElementLeft(iFace)); - uvwRight.setAsProxy(group.getIntegrationOnElementRight(iFace)); + dofsLeft.setAsProxy(solutionLeft, _nbFields*group.getElementLeftId(iFace), _nbFields); + dofsRight.setAsProxy(solutionRight, _nbFields*group.getElementRightId(iFace), _nbFields); + _uvwLeft.setAsProxy(group.getIntegrationOnElementLeft(iFace)); + _uvwRight.setAsProxy(group.getIntegrationOnElementRight(iFace)); // proxies for the flux - normalFluxQP.setAsProxy(NormalFluxQP, iFace*nbFields*2, nbFields*2); - + normalFluxQP.setAsProxy(NormalFluxQP, iFace*_nbFields*2, _nbFields*2); // B2 ) compute the gradient of the solution - if(gradientSolutionLeft.somethingDependOnMe()){ - dPsiLeftDx.mult(dofsLeft, gradientSolutionLeft.set()); - dPsiRightDx.mult(dofsRight, gradientSolutionRight.set()); + if(_gradientSolutionLeft.somethingDependOnMe()){ + dPsiLeftDx.mult(dofsLeft, _gradientSolutionLeft.set()); + dPsiRightDx.mult(dofsRight, _gradientSolutionRight.set()); } - // B3 ) compute fluxes - if (diffusiveFluxLeft) { + if (_diffusiveFluxLeft) { for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) { const double detJ = group.getDetJ (iFace, iPt); //just for the lisibility : - const fullMatrix<double> &dfl = (*diffusiveFluxLeft)(); - const fullMatrix<double> &dfr = (*diffusiveFluxRight)(); - for (int k=0;k<nbFields;k++) { + const fullMatrix<double> &dfl = (*_diffusiveFluxLeft)(); + const fullMatrix<double> &dfr = (*_diffusiveFluxRight)(); + for (int k=0;k<_nbFields;k++) { double meanNormalFlux = - ((dfl(iPt,k+nbFields*0 )+dfr(iPt,k+nbFields*0)) * normals(0,iPt) - +(dfl(iPt,k+nbFields*1 )+dfr(iPt,k+nbFields*1)) * normals(1,iPt) - +(dfl(iPt,k+nbFields*2 )+dfr(iPt,k+nbFields*2)) * normals(2,iPt))/2; + ((dfl(iPt,k+_nbFields*0 )+dfr(iPt,k+_nbFields*0)) * _normals(0,iPt) + +(dfl(iPt,k+_nbFields*1 )+dfr(iPt,k+_nbFields*1)) * _normals(1,iPt) + +(dfl(iPt,k+_nbFields*2 )+dfr(iPt,k+_nbFields*2)) * _normals(2,iPt))/2; double minl = std::min(group.getElementVolumeLeft(iFace), group.getElementVolumeRight(iFace) )/group.getInterfaceSurface(iFace); - double nu = std::max((*maximumDiffusivityRight)(iPt,0),(*maximumDiffusivityLeft)(iPt,0)); + double nu = std::max((*_maximumDiffusivityRight)(iPt,0),(*_maximumDiffusivityLeft)(iPt,0)); double mu = (p+1)*(p+dim)/dim*nu/minl; - double solutionJumpPenalty = (solutionQPLeft(iPt,k)-solutionQPRight(iPt,k))/2*mu; + double solutionJumpPenalty = (_solutionQPLeft(iPt,k)-_solutionQPRight(iPt,k))/2*mu; normalFluxQP(iPt,k) -= (meanNormalFlux+solutionJumpPenalty)*detJ; - normalFluxQP(iPt,k+nbFields) += (meanNormalFlux+solutionJumpPenalty)*detJ; + normalFluxQP(iPt,k+_nbFields) += (meanNormalFlux+solutionJumpPenalty)*detJ; } } } - if (riemannSolver) { + if (_riemannSolver) { for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) { const double detJ = group.getDetJ (iFace, iPt); - for (int k=0;k<nbFields*2;k++) - normalFluxQP(iPt,k) += (*riemannSolver)(iPt,k)*detJ; + for (int k=0;k<_nbFields*2;k++) + normalFluxQP(iPt,k) += (*_riemannSolver)(iPt,k)*detJ; } } } - // C ) redistribute the flux to the residual (at Faces nodes) - - if(riemannSolver || diffusiveFluxLeft) + if(_riemannSolver || _diffusiveFluxLeft) residual.gemm(group.getRedistributionMatrix(),NormalFluxQP); } -void dgAlgorithm::multAddInverseMassMatrix ( /*dofManager &dof,*/ - const dgGroupOfElements & group, - fullMatrix<double> &residu, - fullMatrix<double> &sol) + +void dgResidualInterface::computeAndMap1Group (dgGroupOfFaces &faces, dgDofContainer &solution, dgDofContainer &residual) { - fullMatrix<double> residuEl; - fullMatrix<double> solEl; - fullMatrix<double> iMassEl; - int nFields=sol.size2()/group.getNbElements(); - for(int i=0;i<group.getNbElements();i++) { - residuEl.setAsProxy(residu,i*nFields,nFields); - solEl.setAsProxy(sol,i*nFields,nFields); - iMassEl.setAsProxy(group.getInverseMassMatrix(),i*group.getNbNodes(),group.getNbNodes()); - solEl.gemm(iMassEl,residuEl); - } + fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*2*_nbFields); + fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*2*_nbFields); + faces.mapToInterface(_nbFields, solution.getGroupProxy(&faces.getGroupLeft()), solution.getGroupProxy(&faces.getGroupRight()), solInterface); + compute1Group(faces,solInterface,solution.getGroupProxy(&faces.getGroupLeft()), solution.getGroupProxy(&faces.getGroupRight()),residuInterface); + faces.mapFromInterface(_nbFields, residuInterface,residual.getGroupProxy(&faces.getGroupLeft()), residual.getGroupProxy(&faces.getGroupRight())); } +class dgResidualBoundary { + const dgConservationLaw &_claw; + public : + void compute1Group ( //dofManager &dof, // the DOF manager (maybe useless here) + dgGroupOfFaces &group, + const fullMatrix<double> &solution, // solution !! at faces nodes + fullMatrix<double> &solutionLeft, + fullMatrix<double> &residual // residual !! at faces nodes + ); + void computeAndMap1Group (dgGroupOfFaces &faces, dgDofContainer &solution, dgDofContainer &residual); + dgResidualBoundary (const dgConservationLaw &claw); +}; +dgResidualBoundary::dgResidualBoundary(const dgConservationLaw &claw):_claw(claw){ +} -/*void dgAlgorithm::multirateRungeKutta (const dgConservationLaw &claw, // conservation law - dgGroupCollection &groups, - double h, // time-step - dgDofContainer &sol, - dgDofContainer &resd, - int orderRK) // order of RK integrator - { - - // U_{n+1}=U_n+h*(SUM_i a_i*K_i) - // K_i=M^(-1)R(U_n+b_i*K_{i-1}) - - int nStages=10; -// classical RK44 -// double A[4][4]={ -// {0, 0, 0, 0}, -// {1.0/2.0, 0, 0 ,0}, -// {0, 1.0/2.0, 0, 0}, -// {0, 0, 1, 0} -// }; -// double b[4]={1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; -// double c[4]={0, 1.0/2.0, 1.0/2.0, 1}; - -// 3/8 RK44 -// double A[4][4]={ -// {0, 0, 0, 0}, -// {1.0/3.0, 0, 0 ,0}, -// {-1.0/3.0, 1.0, 0, 0}, -// {1, -1, 1, 0} -// }; -// double b[4]={1.0/8.0, 3.0/8.0, 3.0/8.0, 1.0/8.0}; -// double c[4]={0, 1.0/3.0, 2.0/3.0, 1}; - -// RK43 from Schlegel et al. JCAM 2009 -// double A[4][4]={ -// {0, 0, 0, 0}, -// {1.0/2.0, 0, 0 ,0}, -// {-1.0/6.0, 2.0/3.0, 0, 0}, -// {1.0/3.0, -1.0/3.0, 1, 0} -// }; -// double b[4]={1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; -// double c[4]={0, 1.0/2.0, 1.0/2.0, 1}; - - double A[10][10]; - double *b; - double *c; -// Small step RK43 - double A1[10][10]={ -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/4.0 ,0, 0, 0, 0, 0, 0, 0, 0, 0}, -{-1.0/12.0, 1.0/3.0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/6.0, -1.0/6.0, 1.0/2.0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, 0, 0, 0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, 0, 0, 0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, 1.0/4.0, 0, 0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, -1.0/12.0, 1.0/3.0, 0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, 1.0/6.0, -1.0/6.0, 1.0/2.0, 0, 0}, -{1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0, 1.0/12.0, 1.0/6.0, 1.0/6.0, 1.0/12.0, 0} - }; - double b1[10]={1.0/12.0, 1.0/6.0, 1.0/6.0,1.0/12.0,0,1.0/12.0, 1.0/6.0, 1.0/6.0,1.0/12.0,0}; - double c1[10]={0, 1.0/4.0, 1.0/4.0, 1.0/2.0, 1.0/2.0, 1.0/2.0, 3.0/4.0, 3.0/4.0, 1, 1 }; - -// Big step RK43 - double A2[10][10]={ -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/4.0 , 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/4.0 , 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/2.0 , 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{1.0/2.0 , 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{-1.0/6.0, 0, 0, 0, 2.0/3.0, 0, 0, 0, 0, 0}, -{1.0/12.0, 0, 0, 0, 1.0/6.0, 1.0/2.0, 0, 0, 0, 0}, -{1.0/12.0, 0, 0, 0, 1.0/6.0, 1.0/2.0, 0, 0, 0, 0}, -{1.0/3.0 , 0, 0, 0, -1.0/3.0, 1, 0, 0, 0, 0}, -{1.0/3.0 , 0, 0, 0, -1.0/3.0, 1, 0, 0, 0, 0}, - }; - double b2[10]={1.0/6.0, 0 , 0 , 0 , 1.0/3.0,1.0/3.0, 0 , 0 , 0 , 1.0/6.0}; - double c2[10]={0, 1.0/4.0, 1.0/4.0, 1.0/2.0, 1.0/2.0, 1.0/2.0, 3.0/4.0, 3.0/4.0, 1, 1 }; - - - // fullMatrix<double> K(sol); - // Current updated solution - // fullMatrix<double> Unp(sol); - fullMatrix<double> residuEl, KEl; - fullMatrix<double> iMassEl; - - int nbFields = claw.getNbFields(); - - dgDofContainer **K; - K=new dgDofContainer*[nStages]; - for(int i=0;i<nStages;i++){ - K[i]=new dgDofContainer(&groups,nbFields); - K[i]->scale(0.); - } - dgDofContainer Unp (&groups,nbFields); - dgDofContainer tmp (&groups,nbFields); - - Unp.scale(0.0); - Unp.axpy(sol); - // Case of 2 groups: first with big steps, second with small steps - for(int j=0; j<nStages;j++){ - tmp.scale(0.0); - tmp.axpy(sol); - for(int k=0;k < groups.getNbElementGroups();k++) { - if (k==0) { - for (int ii=0; ii<10; ii++) { - for (int jj=0; jj<10; jj++) { - A[ii][jj]=A2[ii][jj]; - } - } - } - else{ - for (int ii=0; ii<10; ii++) { - for (int jj=0; jj<10; jj++) { - A[ii][jj]=A1[ii][jj]; - } - } - } - for(int i=0;i<j;i++){ - if(fabs(A[j][i])>1e-12){ - tmp.getGroupProxy(k).add(K[i]->getGroupProxy(k),h*A[j][i]); - } - } - } - dgAlgorithm::residual(claw,groups,tmp,resd); - for(int k=0;k < groups.getNbElementGroups(); k++) { - if (k==0) { - b=b2; - c=c2; - } - else{ - b=b1; - c=c1; - } - - dgGroupOfElements *group = groups.getElementGroup(k); - int nbNodes = group->getNbNodes(); - for(int i=0;i<group->getNbElements();i++) { - residuEl.setAsProxy(resd.getGroupProxy(k),i*nbFields,nbFields); - KEl.setAsProxy(K[j]->getGroupProxy(k),i*nbFields,nbFields); - iMassEl.setAsProxy(group->getInverseMassMatrix(),i*nbNodes,nbNodes); - iMassEl.mult(residuEl,KEl); - } - Unp.getGroupProxy(k).add(K[j]->getGroupProxy(k),h*b[j]); - } - } - sol.scale(0.); - sol.axpy(Unp); - - for(int i=0;i<nStages;i++){ - delete K[i]; - } - delete []K; - }*/ - -void dgAlgorithm::residualBoundary ( //dofManager &dof, // the DOF manager (maybe useless here) - const dgConservationLaw &claw, // the conservation law - dgGroupOfFaces &group, - const fullMatrix<double> &solution, // solution !! at faces nodes - fullMatrix<double> &solutionLeft, - fullMatrix<double> &residual // residual !! at faces nodes - ) -{ - int nbFields = claw.getNbFields(); +void dgResidualBoundary::compute1Group( + dgGroupOfFaces &group, + const fullMatrix<double> &solution, // solution !! at faces nodes + fullMatrix<double> &solutionLeft, + fullMatrix<double> &residual // residual !! at faces nodes + ) +{ + int nbFields = _claw.getNbFields(); int nbNodesLeft = group.getGroupLeft().getNbNodes(); - const dgBoundaryCondition *boundaryCondition = claw.getBoundaryCondition(group.getBoundaryTag()); + const dgBoundaryCondition *boundaryCondition = _claw.getBoundaryCondition(group.getBoundaryTag()); // ----- 1 ---- get the solution at quadrature points fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),group.getNbElements() * nbFields); group.getCollocationMatrix().mult(solution, solutionQP); @@ -437,8 +314,8 @@ void dgAlgorithm::residualBoundary ( //dofManager &dof, // the DOF manager (mayb // inviscid dataCacheDouble *boundaryTerm = boundaryCondition->newBoundaryTerm(cacheMapLeft); // viscous - dataCacheDouble *diffusiveFluxLeft = claw.newDiffusiveFlux(cacheMapLeft); - dataCacheDouble *maximumDiffusivityLeft = claw.newMaximumDiffusivity(cacheMapLeft); + dataCacheDouble *diffusiveFluxLeft = _claw.newDiffusiveFlux(cacheMapLeft); + dataCacheDouble *maximumDiffusivityLeft = _claw.newMaximumDiffusivity(cacheMapLeft); dataCacheDouble *maximumDiffusivityOut = boundaryCondition->newMaximumDiffusivity(cacheMapLeft); dataCacheDouble *neumann = boundaryCondition->newDiffusiveNeumannBC(cacheMapLeft); dataCacheDouble *dirichlet = boundaryCondition->newDiffusiveDirichletBC(cacheMapLeft); @@ -493,56 +370,32 @@ void dgAlgorithm::residualBoundary ( //dofManager &dof, // the DOF manager (mayb residual.gemm(group.getRedistributionMatrix(),NormalFluxQP); } +void dgResidualBoundary::computeAndMap1Group(dgGroupOfFaces &faces, dgDofContainer &solution, dgDofContainer &residual) +{ + int _nbFields = _claw.getNbFields(); + fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*_nbFields); + fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*_nbFields); + faces.mapToInterface(_nbFields, solution.getGroupProxy(&faces.getGroupLeft()), solution.getGroupProxy(&faces.getGroupRight()), solInterface); + compute1Group(faces,solInterface,solution.getGroupProxy(&faces.getGroupLeft()),residuInterface); + faces.mapFromInterface(_nbFields, residuInterface, residual.getGroupProxy(&faces.getGroupLeft()), residual.getGroupProxy(&faces.getGroupRight())); +} + // works for any number of groups -void dgAlgorithm::residual( const dgConservationLaw &claw, - dgGroupCollection &groups, - dgDofContainer &solution, - dgDofContainer &residu) +void dgAlgorithm::residual( const dgConservationLaw &claw, dgGroupCollection &groups, dgDofContainer &solution, dgDofContainer &residual) { solution.scatter(); - int nbFields=claw.getNbFields(); - //volume term - for(size_t i=0;i<groups.getNbElementGroups() ; i++) { - residu.getGroupProxy(i).scale(0); - residualVolume(claw,*groups.getElementGroup(i),solution.getGroupProxy(i),residu.getGroupProxy(i)); - } - // residu[0]->print("Volume"); - //interface term - for(size_t i=0;i<groups.getNbFaceGroups() ; i++) { - dgGroupOfFaces &faces = *groups.getFaceGroup(i); - int iGroupLeft = -1, iGroupRight = -1; - for(size_t j=0;j<groups.getNbElementGroups(); j++) { - dgGroupOfElements *groupj = groups.getElementGroup(j); - if (groupj == &faces.getGroupLeft()) iGroupLeft = j; - if (groupj == &faces.getGroupRight()) iGroupRight= j; - } - for(size_t j=0;j<groups.getNbGhostGroups(); j++) { - dgGroupOfElements *groupj = groups.getGhostGroup(j); - if (groupj == &faces.getGroupLeft()) iGroupLeft = j; - if (groupj == &faces.getGroupLeft())iGroupLeft = j + groups.getNbElementGroups(); - if (groupj == &faces.getGroupRight())iGroupRight= j + groups.getNbElementGroups(); - } - fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields); - fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields); - faces.mapToInterface(nbFields, solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight), solInterface); - residualInterface(claw,faces,solInterface,solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight),residuInterface); - faces.mapFromInterface(nbFields, residuInterface,residu.getGroupProxy(iGroupLeft), residu.getGroupProxy(iGroupRight)); - } - //boundaries - for(size_t i=0;i<groups.getNbBoundaryGroups() ; i++) { - dgGroupOfFaces &faces = *groups.getBoundaryGroup(i); - int iGroupLeft = -1, iGroupRight = -1; - for(size_t j=0;j<groups.getNbElementGroups(); j++) { - dgGroupOfElements *groupj = groups.getElementGroup(j); - if (groupj == &faces.getGroupLeft())iGroupLeft = j; - if (groupj == &faces.getGroupRight())iGroupRight= j; - } - fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*nbFields); - fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*nbFields); - faces.mapToInterface(nbFields, solution.getGroupProxy(iGroupLeft), solution.getGroupProxy(iGroupRight), solInterface); - residualBoundary(claw,faces,solInterface,solution.getGroupProxy(iGroupLeft),residuInterface); - faces.mapFromInterface(nbFields, residuInterface, residu.getGroupProxy(iGroupLeft), residu.getGroupProxy(iGroupRight)); - } + + dgResidualVolume residualVolume(claw); + for (int i=0; i<groups.getNbElementGroups(); i++) + residualVolume.computeAndMap1Group(*groups.getElementGroup(i), solution, residual); + + dgResidualInterface residualInterface(claw); + for(size_t i=0;i<groups.getNbFaceGroups() ; i++) + residualInterface.computeAndMap1Group(*groups.getFaceGroup(i), solution, residual); + + dgResidualBoundary residualBoundary(claw); + for(size_t i=0;i<groups.getNbBoundaryGroups() ; i++) + residualBoundary.computeAndMap1Group(*groups.getBoundaryGroup(i), solution, residual); } void dgAlgorithm::computeElementaryTimeSteps ( //dofManager &dof, // the DOF manager (maybe useless here) @@ -590,3 +443,19 @@ void dgAlgorithm::computeElementaryTimeSteps ( //dofManager &dof, // the DOF man } } +void dgAlgorithm::multAddInverseMassMatrix ( /*dofManager &dof,*/ + const dgGroupOfElements & group, + fullMatrix<double> &residu, + fullMatrix<double> &sol) +{ + fullMatrix<double> residuEl; + fullMatrix<double> solEl; + fullMatrix<double> iMassEl; + int nFields=sol.size2()/group.getNbElements(); + for(int i=0;i<group.getNbElements();i++) { + residuEl.setAsProxy(residu,i*nFields,nFields); + solEl.setAsProxy(sol,i*nFields,nFields); + iMassEl.setAsProxy(group.getInverseMassMatrix(),i*group.getNbNodes(),group.getNbNodes()); + solEl.gemm(iMassEl,residuEl); + } +} diff --git a/Solver/dgAlgorithm.h b/Solver/dgAlgorithm.h index f970010eb839eda4a325399ef3e73ccd79e40aa1..6032f9a639f8c7323fa549fcd06ed3e5ff21ca6e 100644 --- a/Solver/dgAlgorithm.h +++ b/Solver/dgAlgorithm.h @@ -16,18 +16,6 @@ class dgSystemOfEquations; class dgAlgorithm { public : static void registerBindings(binding *b); - static void residualVolume ( //dofManager &dof, // the DOF manager (maybe useless here) - const dgConservationLaw &claw, // the conservation law - const dgGroupOfElements & group, - fullMatrix<double> &solution, - fullMatrix<double> &residual); - static void residualInterface ( //dofManager &dof, // the DOF manager (maybe useless here) - const dgConservationLaw &claw, // the conservation law - dgGroupOfFaces & group, - const fullMatrix<double> &solution, // ! at face nodes - fullMatrix<double> &solutionRight, - fullMatrix<double> &solutionLeft, - fullMatrix<double> &residual); // ! at face nodes static void residualBoundary ( //dofManager &dof, // the DOF manager (maybe useless here) const dgConservationLaw &claw, // the conservation law dgGroupOfFaces &group, diff --git a/Solver/dgConservationLawPerfectGas.cpp b/Solver/dgConservationLawPerfectGas.cpp index 1622dc7c81e69fbc787ba6e50d5a6ea44ca828a4..7dab96977826844e784de4c7e960d4854e1ca0d8 100644 --- a/Solver/dgConservationLawPerfectGas.cpp +++ b/Solver/dgConservationLawPerfectGas.cpp @@ -332,7 +332,7 @@ class dgPerfectGasLaw2d::advection : public dataCacheDouble { sol(cacheMap.get("Solution",this)) {}; void _eval () { - const int nQP = sol().size1(); + const int nQP = _value.size1(); const double GM1 = GAMMA - 1.0; for (size_t k = 0 ; k < nQP; k++ ){ const double invrho = 1./sol(k,0); diff --git a/Solver/function.cpp b/Solver/function.cpp index 62b88d983d56d8d9752ef5cb9fd1e96bb29a02d9..2fab642de27a89506e20cc5ed7477395b289b86b 100644 --- a/Solver/function.cpp +++ b/Solver/function.cpp @@ -282,8 +282,10 @@ public: }; void dataCacheMap::setNbEvaluationPoints(int nbEvaluationPoints) { _nbEvaluationPoints = nbEvaluationPoints; - for(std::map<std::string, dataCacheDouble*>::iterator it = _cacheDoubleMap.begin(); it!= _cacheDoubleMap.end(); it++) - it->second->resize(); + for(std::set<dataCacheDouble*>::iterator it = _toResize.begin(); it!= _toResize.end(); it++){ + (*it)->resize(); + (*it)->_valid = false; + } } dataCacheDouble *functionMesh2Mesh::newDataCache(dataCacheMap *m) @@ -295,6 +297,7 @@ dataCacheDouble *functionMesh2Mesh::newDataCache(dataCacheMap *m) dataCacheDouble::dataCacheDouble(dataCacheMap &map,int nRowByPoint, int nCol): dataCache(&map),_cacheMap(map),_value(nRowByPoint==0?1:nRowByPoint*map.getNbEvaluationPoints(),nCol){ _nRowByPoint=nRowByPoint; + map.addDataCacheDouble(this); }; void dataCacheDouble::resize() { _value = fullMatrix<double>(_nRowByPoint==0?1:_nRowByPoint*_cacheMap.getNbEvaluationPoints(),_value.size2()); diff --git a/Solver/function.h b/Solver/function.h index 607135a53a78b00e529b3e555dd9a68db5488755..bdfd9c64da7a4447e6402492021ad302549fa5cd 100644 --- a/Solver/function.h +++ b/Solver/function.h @@ -159,6 +159,7 @@ class dataCacheElement : public dataCache { // more explanation at the head of this file class dataCacheMap { friend class dataCache; + friend class dataCacheDouble; private: int _nbEvaluationPoints; // keep track of the current element and all the dataCaches that @@ -176,11 +177,15 @@ class dataCacheMap { } }; std::set<dataCache*> _toDelete; + std::set<dataCacheDouble*> _toResize; protected: void addDataCache(dataCache *data){ _toDelete.insert(data); } + void addDataCacheDouble(dataCacheDouble *data){ + _toResize.insert(data); + } public: // dg Part //list of dgDofContainer that have to be evaluated, this not work as a function as it depends on the algorithm