diff --git a/Solver/TESTCASES/WavePulse.lua b/Solver/TESTCASES/WavePulse.lua index 68bd5f0dc60430c8a556650b6542f96a7f44802f..5c679629b912b28c95a275d2e820c6b2dbc5980f 100644 --- a/Solver/TESTCASES/WavePulse.lua +++ b/Solver/TESTCASES/WavePulse.lua @@ -43,10 +43,10 @@ print'*** solve ***' dt = 0.00125; N = 1000; for i=1,N do - norm = DG:RK44(dt) + norm = DG:multirateRK43(dt) print('*** ITER ***',i,norm) if (i % 10 == 0) then - DG:exportSolution(string.format("output/solution-%03d", i)) + DG:exportSolution(string.format("output/solution-%04d", i)) end end diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp index af63131bc0334574e59c71605440b37155cb4957..a376adddb593d06d722986741d61fee323d9698f 100644 --- a/Solver/dgAlgorithm.cpp +++ b/Solver/dgAlgorithm.cpp @@ -319,6 +319,140 @@ void dgAlgorithm::rungeKutta (const dgConservationLaw &claw, // conservation l } } + + +void dgAlgorithm::multirateRungeKutta (const dgConservationLaw &claw, // conservation law + std::vector<dgGroupOfElements*> &eGroups, // group of elements + std::vector<dgGroupOfFaces*> &fGroups, // group of interfacs + std::vector<dgGroupOfFaces*> &bGroups, // group of boundaries + 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}; + + +// Small step RK43 + double A[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 b[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 c[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 A[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 b[10]={1.0/6.0, 0 , 0 , 0 , 1.0/3.0,1.0/3.0, 0 , 0 , 0 , 1.0/6.0}; +// double c[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.nbFields(); + + dgDofContainer **K; + K=new dgDofContainer*[nStages]; + for(int i=0;i<nStages;i++){ + K[i]=new dgDofContainer(eGroups,claw); + K[i]->_data->scale(0.0); + } + dgDofContainer Unp (eGroups,claw); + dgDofContainer tmp (eGroups,claw); + + Unp._data->scale(0.0); + Unp._data->axpy(*(sol._data)); + + for(int j=0; j<nStages;j++){ + tmp._data->scale(0.0); + tmp._data->axpy(*(sol._data)); + for(int k=0;k < eGroups.size();k++) { + 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]); + } + } + } + this->residual(claw,eGroups,fGroups,bGroups,tmp._dataProxys,resd._dataProxys); + for(int k=0;k < eGroups.size();k++) { + int nbNodes = eGroups[k]->getNbNodes(); + for(int i=0;i<eGroups[k]->getNbElements();i++) { + residuEl.setAsProxy(*(resd._dataProxys[k]),i*nbFields,nbFields); + KEl.setAsProxy(*(K[j]->_dataProxys[k]),i*nbFields,nbFields); + iMassEl.setAsProxy(eGroups[k]->getInverseMassMatrix(),i*nbNodes,nbNodes); + iMassEl.mult(residuEl,KEl); + } + Unp.getGroupProxy(k).add(K[j]->getGroupProxy(k),h*b[j]); + } + } + + for (int i=0;i<sol._dataSize;i++){ + // printf("tempSol[%d] = %g\n",i,(*tempSol._data)(i)); + // memcp + (*sol._data)(i)=(*Unp._data)(i); + } + 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, diff --git a/Solver/dgAlgorithm.h b/Solver/dgAlgorithm.h index a8ad3eb857a5aaf0eb6fd2f9d69e6709c5f21cef..823f9af3fbbfe4a1d2d361153c6e33795c3e4735 100644 --- a/Solver/dgAlgorithm.h +++ b/Solver/dgAlgorithm.h @@ -48,6 +48,15 @@ class dgAlgorithm { dgDofContainer &residu, dgDofContainer &sol, int orderRK=4); + void multirateRungeKutta ( + const dgConservationLaw &claw, + std::vector<dgGroupOfElements*> &eGroups, //group of elements + std::vector<dgGroupOfFaces*> &fGroups, // group of interfacs + std::vector<dgGroupOfFaces*> &bGroups, // group of boundaries + double h, + dgDofContainer &residu, + dgDofContainer &sol, + int orderRK=3); static void multAddInverseMassMatrix ( /*dofManager &dof,*/ const dgGroupOfElements & group, fullMatrix<double> &residu, diff --git a/Solver/dgSystemOfEquations.cpp b/Solver/dgSystemOfEquations.cpp index 9035150742661bb60d94358b03570fdbe1dc349a..ae8357043d39a78b166aa010ba28a096a08f6d6a 100644 --- a/Solver/dgSystemOfEquations.cpp +++ b/Solver/dgSystemOfEquations.cpp @@ -49,6 +49,7 @@ methodBinding *dgSystemOfEquations::methods[]={ new methodBindingTemplate<dgSystemOfEquations,void,std::string>("exportSolution",&dgSystemOfEquations::exportSolution), new methodBindingTemplate<dgSystemOfEquations,void,std::string>("L2Projection",&dgSystemOfEquations::L2Projection), new methodBindingTemplate<dgSystemOfEquations,double,double>("RK44",&dgSystemOfEquations::RK44), + new methodBindingTemplate<dgSystemOfEquations,double,double>("multirateRK43",&dgSystemOfEquations::multirateRK43), 0}; // do a L2 projection @@ -80,6 +81,12 @@ double dgSystemOfEquations::RK44(double dt){ return _solution->_data->norm(); } + +double dgSystemOfEquations::multirateRK43(double dt){ + _algo->multirateRungeKutta(*_claw, _elementGroups, _faceGroups, _boundaryGroups, dt, *_solution, *_rightHandSide); + return _solution->_data->norm(); +} + void dgSystemOfEquations::exportSolution(std::string outputFile){ export_solution_as_is(outputFile); } diff --git a/Solver/dgSystemOfEquations.h b/Solver/dgSystemOfEquations.h index 7671f76d81383bb69f0da1959deef16d42e18084..e8cddcf7a547e23ab6e97a7c741bd90b2c08ad20 100644 --- a/Solver/dgSystemOfEquations.h +++ b/Solver/dgSystemOfEquations.h @@ -13,8 +13,10 @@ private: dgDofContainer (const dgDofContainer&); public: int _dataSize; // the full data size i.e. concerning all groups - fullVector<double> * _data; // the full data itself std::vector<fullMatrix<double> *> _dataProxys; // proxys + fullVector<double> * _data; // the full data itself + inline int getDataSize(){return _dataSize;} + inline fullMatrix<double> &getGroupProxy(int gId){ return *(_dataProxys[gId]); } dgDofContainer (std::vector<dgGroupOfElements*> &groups, const dgConservationLaw &claw); ~dgDofContainer (); }; @@ -51,6 +53,7 @@ public: void setup (); // setup the groups and allocate void exportSolution (std::string filename); // export the solution double RK44 (double dt); + double multirateRK43 (double dt); void L2Projection (std::string functionName); // assign the solution to a given function static const char className[];