diff --git a/Solver/TESTCASES/ConvergenceMultirate.lua b/Solver/TESTCASES/ConvergenceMultirate.lua index 8bfa3867a091bd27caa0d922f274d57363cc0b64..bae2734f50afa74534a04c8fcabaa807d94b2d2a 100644 --- a/Solver/TESTCASES/ConvergenceMultirate.lua +++ b/Solver/TESTCASES/ConvergenceMultirate.lua @@ -17,8 +17,8 @@ function velocity( XYZ, FCT ) for i=0,XYZ:size1()-1 do X = XYZ:get(i,0) Y = XYZ:get(i,1) - FCT:set(i,0,1) - FCT:set(i,1,0) + FCT:set(i,0,0) + FCT:set(i,1,1) FCT:set(i,2,0) end end @@ -62,12 +62,13 @@ FS = functionLua(1, 'initial_condition', {'XYZ'}):getName() GC=dgGroupCollection(myModel,2,order) solTmp=dgDofContainer(GC,1) solTmp:L2Projection(FS) -dt=GC:splitGroupsForMultirate(3,law,solTmp) +dt=GC:splitGroupsForMultirate(20,1,law,solTmp) GC:buildGroupsOfInterfaces(myModel,2,order) solution=dgDofContainer(GC,1) solutionRef=dgDofContainer(GC,1) solutionRef:L2Projection(FS) solution:exportGroupIdMsh() +solution:exportMultirateGroupMsh() solutionRef:exportMsh("solution") nRefSteps=100 diff --git a/Solver/TESTCASES/MultirateAdvection.lua b/Solver/TESTCASES/MultirateAdvection.lua index 4bd85943d51fef3b74f62f40ed6ae0e37b399b79..d1b9af574c86424a57c277083c1eb65df99a9931 100644 --- a/Solver/TESTCASES/MultirateAdvection.lua +++ b/Solver/TESTCASES/MultirateAdvection.lua @@ -17,6 +17,7 @@ function velocity( XYZ, FCT ) Y = XYZ:get(i,1) FCT:set(i,0,0) FCT:set(i,1,1) + FCT:set(i,2,0) end end @@ -48,7 +49,7 @@ elseif (order == 5) then end print'*** Create a dg solver ***' -velF = functionLua(2, 'velocity', {'XYZ'}):getName() +velF = functionLua(3, 'velocity', {'XYZ'}):getName() law=dgConservationLawAdvectionDiffusion(velF,"") zero=functionConstant({0.}):getName(); @@ -59,7 +60,7 @@ FS = functionLua(1, 'initial_condition', {'XYZ'}):getName() GC=dgGroupCollection(myModel,2,order) solTmp=dgDofContainer(GC,1) solTmp:L2Projection(FS) -dt=GC:splitGroupsForMultirate(4,law,solTmp) +dt=GC:splitGroupsForMultirate(2,10,law,solTmp) GC:buildGroupsOfInterfaces(myModel,2,order) solution=dgDofContainer(GC,1) solution:L2Projection(FS) @@ -95,7 +96,7 @@ time=0 --for i=1,1000 i=0 integrator=dgFunctionIntegrator(functionLua(1, 'toIntegrate', {'XYZ'}):getName()) -while time<0.2 do +while i<1 do -- norm1 = RK:iterate43SchlegelJCAM2009(law,dt,solution) -- TEST with Explicit Euler multirate !!! norm2 = multirateRK:iterate(dt,solution2) diff --git a/Solver/dgDofContainer.cpp b/Solver/dgDofContainer.cpp index c6bce12be812f7d517c0ad84007728a272f86cd0..cbf6afa0af39791c8142f6544b84ae34ac80c3d6 100644 --- a/Solver/dgDofContainer.cpp +++ b/Solver/dgDofContainer.cpp @@ -192,6 +192,19 @@ double dgDofContainer::norm() { return localNorm; #endif } +double dgDofContainer::norm(std::vector<dgGroupOfElements *>gV){ + double norm=0; + for(int i=0;i<gV.size();i++){ + dgGroupOfElements* g=gV[i]; + fullMatrix<double>&groupData=getGroupProxy(g); + for(int r=0;r<groupData.size1();r++){ + for(int c=0;c<groupData.size1();c++){ + norm+=groupData(r,c)*groupData(r,c); + } + } + } + return norm; +} void dgDofContainer::save(const std::string name) { FILE *f = fopen (name.c_str(),"wb"); _data->binarySave(f); @@ -233,7 +246,7 @@ void dgDofContainer::exportGroupIdMsh(){ // the elementnodedata::export does not work !! std::ostringstream name_oss; - name_oss<<"groups.msh"; + name_oss<<"groupsId.msh"; if(Msg::GetCommSize()>1) name_oss<<"_"<<Msg::GetCommRank(); FILE *f = fopen (name_oss.str().c_str(),"w"); @@ -294,6 +307,76 @@ void dgDofContainer::exportGroupIdMsh(){ */ } +void dgDofContainer::exportMultirateGroupMsh(){ + // the elementnodedata::export does not work !! + + std::ostringstream name_oss; + name_oss<<"groupsMultirateType.msh"; + if(Msg::GetCommSize()>1) + name_oss<<"_"<<Msg::GetCommRank(); + FILE *f = fopen (name_oss.str().c_str(),"w"); + int COUNT = 0; + for (int i=0;i < _groups.getNbElementGroups() ;i++){ + COUNT += _groups.getElementGroup(i)->getNbElements(); + } + fprintf(f,"$MeshFormat\n2.1 0 8\n$EndMeshFormat\n"); + fprintf(f,"$ElementNodeData\n"); + fprintf(f,"1\n"); + fprintf(f,"\"%s\"\n","GroupsIds"); + fprintf(f,"1\n"); + fprintf(f,"0.0\n"); + fprintf(f,"%d\n", Msg::GetCommSize() > 1 ? 4 : 3); + fprintf(f,"0\n 1\n %d\n",COUNT); + if(Msg::GetCommSize() > 1) fprintf(f,"%d\n", Msg::GetCommRank()); + for (int i=0;i < _groups.getNbElementGroups() ;i++){ + dgGroupOfElements *group = _groups.getElementGroup(i); + int groupType=0;//-3*group->getMultirateExponent(); + if(group->getIsInnerMultirateBuffer()) + groupType+=1; + if(group->getIsOuterMultirateBuffer()) + groupType+=2; + for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) { + MElement *e = group->getElement(iElement); + int num = e->getNum(); + fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields); + fprintf(f,"%d %d",num,sol.size1()); + for (int k=0;k<sol.size1();++k) { + fprintf(f," %.16E ",groupType*1.0); + } + fprintf(f,"\n"); + } + } + fprintf(f,"$EndElementNodeData\n"); + fclose(f); + return; + // we should discuss that : we do a copy of the solution, this should + // be avoided ! + + /*std::map<int, std::vector<double> > data; + + for (int i=0;i < _groups.getNbElementGroups() ;i++){ + dgGroupOfElements *group = _groups.getElementGroup(i); + for (int iElement=0 ; iElement< group->getNbElements() ;++iElement) { + MElement *e = group->getElement(iElement); + int num = e->getNum(); + fullMatrix<double> sol(getGroupProxy(i), iElement*_nbFields,_nbFields); + std::vector<double> val; + // val.resize(sol.size2()*sol.size1()); + val.resize(sol.size1()); + int counter = 0; + // for (int iC=0;iC<sol.size2();iC++) + printf("%g %g %g\n",sol(0,0),sol(1,0),sol(2,0)); + for (int iR=0;iR<sol.size1();iR++)val[counter++] = sol(iR,0); + data[num] = val; + } + } + + PView *pv = new PView (name, "ElementNodeData", _gm, data, 0.0, 1); + pv->getData()->writeMSH(name+".msh", false); + delete pv; + */ +} + void dgDofContainer::exportMsh(const std::string name) { // the elementnodedata::export does not work !! @@ -386,7 +469,9 @@ void dgDofContainer::registerBindings(binding *b){ cm->setArgNames("filename", NULL); cm = cb->addMethod("exportGroupIdMsh",&dgDofContainer::exportGroupIdMsh); cm->setDescription("Export the group ids for gmsh visualization"); - cm = cb->addMethod("norm",&dgDofContainer::norm); + cm = cb->addMethod("exportMultirateGroupMsh",&dgDofContainer::exportMultirateGroupMsh); + cm->setDescription("Export the group Multirate properties for gmsh visualization"); + cm = cb->addMethod("norm",(double (dgDofContainer::*)())&dgDofContainer::norm); cm->setDescription("Returns the norm of the vector"); cm = cb->addMethod("scale",(void (dgDofContainer::*)(double))&dgDofContainer::scale); cm->setArgNames("factor",NULL); diff --git a/Solver/dgDofContainer.h b/Solver/dgDofContainer.h index c1ce0989748ade9f861ac5d9b6d3161f60972f71..ad926cd1ef44d70dad7215c00b556a5552b066f7 100644 --- a/Solver/dgDofContainer.h +++ b/Solver/dgDofContainer.h @@ -28,6 +28,7 @@ public: void scale(double f); void scale(std::vector<dgGroupOfElements*>groups, double f); double norm(); + double norm(std::vector<dgGroupOfElements*>groups); void axpy(dgDofContainer &x, double a=1.); void axpy(std::vector<dgGroupOfElements*>groups,dgDofContainer &x, double a=1.); inline fullMatrix<double> &getGroupProxy(int gId){ return *(_dataProxys[gId]); } @@ -44,6 +45,7 @@ public: void Mesh2Mesh_L2Projection(dgDofContainer &other); void exportMsh(const std::string name); void exportGroupIdMsh(); + void exportMultirateGroupMsh(); static void registerBindings(binding *b); inline dgGroupCollection *getGroups() { return &_groups; } diff --git a/Solver/dgGroupOfElements.cpp b/Solver/dgGroupOfElements.cpp index 158aca05e69c9e228f30280edd39cb250fe2c8d6..dfdb3fe8f066bca608b79155bb2e438acbe45cfc 100644 --- a/Solver/dgGroupOfElements.cpp +++ b/Solver/dgGroupOfElements.cpp @@ -19,6 +19,7 @@ #include <string.h> #endif + static fullMatrix<double> * dgGetIntegrationRule (MElement *e, int p){ int npts; IntPt *pts; @@ -737,7 +738,7 @@ void dgGroupCollection::buildParallelStructure() } // Split the groups of elements depending on their local time step -double dgGroupCollection::splitGroupsForMultirate(int maxLevels,dgConservationLaw *claw, dgDofContainer *solution) { +double dgGroupCollection::splitGroupsForMultirate(int maxLevels,int bufferSize,dgConservationLaw *claw, dgDofContainer *solution) { // What are the levels/layers: // bulk: elements that are time stepped using the "normal" 4 stage Runge-Kutta // innerBuffer: elements that use the small time step but talks to elements using the big time step @@ -845,32 +846,33 @@ double dgGroupCollection::splitGroupsForMultirate(int maxLevels,dgConservationLa else{ // Add the neighbors elements to the new groups // For buffer AND non buffer layers - int _lowerLevelGroupIdStart=lowerLevelGroupIdStart; - int _lowerLevelGroupIdEnd=lowerLevelGroupIdEnd; lowerLevelGroupIdStart=lowerLevelGroupIdEnd; - for(int iInterface=0;iInterface<miniInterfaceV->size();iInterface++){ - dgMiniInterface &interface=miniInterfaceV->at(iInterface); - bool toAdd=false; - // if one of the elements adjacent to the interface is mapped to the previous level - // we check all elements adjacent to this interface, and add those that does not - // already have a new group to the current new group - for(int iConn=0;iConn<interface.connections.size();iConn++){ - int gId=interface.connections[iConn].iGroup; - int eId=interface.connections[iConn].iElement; - int newGroupId=newGroupIds[gId][eId]; - if(newGroupId>=0 /*newGroupId >= _lowerLevelGroupIdStart && newGroupId<_lowerLevelGroupIdEnd*/){ - toAdd=true; - continue; - } - } - if(toAdd){ + // We add bufferSize elements (most of the time, bufferSize=1 is enough) + for(int iLoop=0;iLoop<bufferSize;iLoop++){ + for(int iInterface=0;iInterface<miniInterfaceV->size();iInterface++){ + dgMiniInterface &interface=miniInterfaceV->at(iInterface); + bool toAdd=false; + // if one of the elements adjacent to the interface is mapped to the previous level + // we check all elements adjacent to this interface, and add those that does not + // already have a new group to the current new group for(int iConn=0;iConn<interface.connections.size();iConn++){ int gId=interface.connections[iConn].iGroup; int eId=interface.connections[iConn].iElement; int newGroupId=newGroupIds[gId][eId]; - if(newGroupId==-1){ - mapNewGroups[gId].push_back(eId); - newGroupIds[gId][eId]=-2; + if(newGroupId>=0 || ( newGroupId>-2-iLoop && newGroupId<-1) ){ + toAdd=true; + continue; + } + } + if(toAdd){ + for(int iConn=0;iConn<interface.connections.size();iConn++){ + int gId=interface.connections[iConn].iGroup; + int eId=interface.connections[iConn].iElement; + int newGroupId=newGroupIds[gId][eId]; + if(newGroupId==-1){ + mapNewGroups[gId].push_back(eId); + newGroupIds[gId][eId]=-2-iLoop; + } } } } @@ -892,22 +894,41 @@ double dgGroupCollection::splitGroupsForMultirate(int maxLevels,dgConservationLa // We split those elements into bulk and innerBuffer (i.e. those who have a neighbor with a bigger time step) lowerLevelGroupIdStart=currentNewGroupId; + +#define MAXBUFFERSIZE 100000 + if(currentExponent>0){ + for(int iLoop=0;iLoop<bufferSize;iLoop++){ + for (std::map<int, std::vector<int> >::iterator it = mapNewGroups.begin(); it !=mapNewGroups.end() ; ++it){ + for(int i=0;i<it->second.size();i++){ + bool inInnerBuffer=false; + int oldGId=it->first; + int oldEId=it->second[i]; + // We only consider elements in the map and not in the inner buffer for a different iLoop + if(newGroupIds[oldGId][oldEId]>-2 || newGroupIds[oldGId][oldEId]<-(MAXBUFFERSIZE-1) ) + continue; + for(int iNeighbor=0;iNeighbor<elementToNeighbors[oldGId][oldEId].size();iNeighbor++){ + std::pair<int,int> neighIds=elementToNeighbors[oldGId][oldEId][iNeighbor]; + if(newGroupIds[neighIds.first][neighIds.second]==-1-iLoop*MAXBUFFERSIZE){ + inInnerBuffer=true; + continue; + } + } + if(inInnerBuffer){ + newGroupIds[oldGId][oldEId]=-1-(iLoop+1)*MAXBUFFERSIZE; + } + } + } + } + } + for (std::map<int, std::vector<int> >::iterator it = mapNewGroups.begin(); it !=mapNewGroups.end() ; ++it){ if(!it->second.empty()){ std::vector<int>forBulk; std::vector<int>forInnerBuffer; for(int i=0;i<it->second.size();i++){ - bool inInnerBuffer=false; int oldGId=it->first; int oldEId=it->second[i]; - for(int iNeighbor=0;iNeighbor<elementToNeighbors[oldGId][oldEId].size();iNeighbor++){ - std::pair<int,int> neighIds=elementToNeighbors[oldGId][oldEId][iNeighbor]; - if(newGroupIds[neighIds.first][neighIds.second]==-1){ - inInnerBuffer=true; - continue; - } - } - if(inInnerBuffer){ + if( newGroupIds[oldGId][oldEId]>-2 || newGroupIds[oldGId][oldEId]<-(MAXBUFFERSIZE-1) ){ forInnerBuffer.push_back(oldEId); } else{ @@ -994,7 +1015,7 @@ double dgGroupCollection::splitGroupsForMultirate(int maxLevels,dgConservationLa // Some stats int count=0; for(int i=0;i<newGroups.size();i++){ - Msg::Info("old: %d, level %d, New group # %d has %d elements",oldGroupIds[i],newGroups[i]->getMultirateExponent(),i,newGroups[i]->getNbElements()); + Msg::Info("Old group #%d, exponent %d, New group #%d has %d elements",oldGroupIds[i],newGroups[i]->getMultirateExponent(),i,newGroups[i]->getNbElements()); if(newGroups[i]->getIsInnerMultirateBuffer()) Msg::Info("InnerBuffer"); else if(newGroups[i]->getIsOuterMultirateBuffer()) @@ -1182,7 +1203,7 @@ void dgGroupCollection::registerBindings(binding *b) cm->setDescription("Build the group of interfaces, i.e. boundary interfaces and inter-element interfaces"); cm = cb->addMethod("splitGroupsForMultirate",&dgGroupCollection::splitGroupsForMultirate); cm->setDescription("Split the groups according to their own stable time step"); - cm->setArgNames("maxLevels","claw","solution",NULL); + cm->setArgNames("maxLevels","bufferSize","claw","solution",NULL); cm = cb->addMethod("splitGroupsByVerticalLayer",&dgGroupCollection::splitGroupsByVerticalLayer); cm->setDescription("Split the groups according vertical layer structure. The first is defined by the topLevelTags."); cm->setArgNames("topLevelTags",NULL); diff --git a/Solver/dgGroupOfElements.h b/Solver/dgGroupOfElements.h index 39bc4c2b9b0f8d4079fc3ae27d6d9a45845b4f6c..0190ef5ccdf3d8921a3b95a55754f27186c6d29f 100644 --- a/Solver/dgGroupOfElements.h +++ b/Solver/dgGroupOfElements.h @@ -247,7 +247,7 @@ class dgGroupCollection { void buildGroupsOfElements (GModel *model,int dimension, int order); void buildGroupsOfInterfaces (); - double splitGroupsForMultirate(int maxLevels,dgConservationLaw *claw, dgDofContainer *solution); + double splitGroupsForMultirate(int maxLevels,int bufferSize,dgConservationLaw *claw, dgDofContainer *solution); void splitGroupsByVerticalLayer(std::vector<std::string> topLevelTags); void find (MElement *elementToFind, int &iGroup, int &ithElementOfGroup); diff --git a/Solver/dgRungeKuttaMultirate.cpp b/Solver/dgRungeKuttaMultirate.cpp index 0770696a2c9b79bb8ea3877d962a41c5b7149bba..ad35b10a625d8df976041896b00771124c65a8fa 100644 --- a/Solver/dgRungeKuttaMultirate.cpp +++ b/Solver/dgRungeKuttaMultirate.cpp @@ -6,12 +6,56 @@ #include "dgGroupOfElements.h" #include <algorithm> #include <limits.h> +#include <stdio.h> +//#define MULTIRATEVERBOSE + + +static double A43[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} + }; +static double AInner43[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} + }; + + // Big step RK43 +static double AOuter43[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}, + }; + +static double b[4]={1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; +static double c[4]={0, 1.0/2.0, 1.0/2.0, 1}; +static double bInner[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}; +static double cInner[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 }; +static double bOuter[10]={1.0/6.0, 0 , 0 , 0 , 1.0/3.0,1.0/3.0, 0 , 0 , 0 , 1.0/6.0}; +static double cOuter[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 }; dgRungeKuttaMultirate::dgRungeKuttaMultirate(dgGroupCollection* gc,dgConservationLaw *law, int nStages){ _law=law; _residualVolume=new dgResidualVolume(*_law); _residualInterface=new dgResidualInterface(*_law); _residualBoundary=new dgResidualBoundary(*_law); + _gc=gc; _K=new dgDofContainer*[nStages]; for(int i=0;i<nStages;i++){ _K[i]=new dgDofContainer(gc,_law->getNbFields()); @@ -40,12 +84,6 @@ dgRungeKuttaMultirate::dgRungeKuttaMultirate(dgGroupCollection* gc,dgConservatio _bulkGroupsOfElements[ge->getMultirateExponent()].first.push_back(ge); } } -// std::vector<std::set<dgGroupOfFaces*> >bulkFacesSet; -// std::vector<std::set<dgGroupOfFaces*> >innerBufferFacesSet; -// std::vector<std::set<dgGroupOfFaces*> >outerBufferFacesSet; -// bulkFacesSet.resize(_maxExponent+1); -// innerBufferFacesSet.resize(_maxExponent+1); -// outerBufferFacesSet.resize(_maxExponent+1); for(int iGroup=0;iGroup<gc->getNbFaceGroups();iGroup++){ dgGroupOfFaces *gf=gc->getFaceGroup(iGroup); const dgGroupOfElements *ge[2]; @@ -66,7 +104,6 @@ dgRungeKuttaMultirate::dgRungeKuttaMultirate(dgGroupCollection* gc,dgConservatio dgGroupOfFaces *gf=gc->getBoundaryGroup(iGroup); const dgGroupOfElements *ge[1]; ge[0]=&gf->getGroupOfConnections(0).getGroupOfElements(); - //ge[1]=&gf->getGroupRight(); for(int i=0;i<1;i++){ if(ge[i]->getIsInnerMultirateBuffer()){ _innerBufferGroupsOfElements[ge[i]->getMultirateExponent()].second.push_back(gf); @@ -103,7 +140,11 @@ dgRungeKuttaMultirate::~dgRungeKuttaMultirate(){ } void dgRungeKuttaMultirate::computeK(int iK,int exponent,bool isBuffer){ - //Msg::Info("Compute K%d at level %d %s",iK,exponent,isBuffer?"Buffer":"Bulk"); +#ifdef MULTIRATEVERBOSE + for(int i=0;i<exponent;i++) + printf("\t"); + printf("Exponent %d, %s, compute K%d\n",exponent,isBuffer?" Buffer":"Not buffer",iK); +#endif if(isBuffer){ std::vector<dgGroupOfElements *>&vei=_innerBufferGroupsOfElements[exponent].first; std::vector<dgGroupOfElements *>&veo=_outerBufferGroupsOfElements[exponent].first; @@ -124,7 +165,6 @@ void dgRungeKuttaMultirate::computeK(int iK,int exponent,bool isBuffer){ dgGroupOfFaces *faces=*it; if(faces->getNbGroupOfConnections()==1){ _residualBoundary->computeAndMap1Group(*faces,*_currentInput,*_residual); - //Msg::Info("Buffer face group %p is boundary in multirate",faces); } else{ const dgGroupOfElements *gL = &faces->getGroupOfConnections(0).getGroupOfElements(); @@ -133,11 +173,12 @@ void dgRungeKuttaMultirate::computeK(int iK,int exponent,bool isBuffer){ fullMatrix<double> residuInterface(faces->getNbNodes(),faces->getNbElements()*2*_law->getNbFields()); faces->mapToInterface(_law->getNbFields(), _currentInput->getGroupProxy(gL), _currentInput->getGroupProxy(gR), solInterface); _residualInterface->compute1Group(*faces,solInterface,_currentInput->getGroupProxy(gL), _currentInput->getGroupProxy(gR),residuInterface); - //Msg::Info("Buffer face group %p is mapped left or right in multirate",faces); - if(gL->getMultirateExponent()==exponent && gL->getIsMultirateBuffer()) + if(gL->getMultirateExponent()==exponent && gL->getIsMultirateBuffer()){ faces->mapLeftFromInterface(_law->getNbFields(), residuInterface,_residual->getGroupProxy(gL)); - if(gR->getMultirateExponent()==exponent && gR->getIsMultirateBuffer()) + } + if(gR->getMultirateExponent()==exponent && gR->getIsMultirateBuffer()){ faces->mapRightFromInterface(_law->getNbFields(), residuInterface,_residual->getGroupProxy(gR)); + } } } fullMatrix<double> iMassEl, KEl,residuEl; @@ -236,43 +277,25 @@ void dgRungeKuttaMultirate43::computeInputForK(int iK,int exponent,bool isBuffer if(exponent>_maxExponent){ return; } - //Msg::Info("Input for K%d at level %d %s",iK,exponent,isBuffer?"Buffer":"Bulk"); +#ifdef MULTIRATEVERBOSE + for(int i=0;i<exponent;i++) + printf("\t"); + printf("Exponent %d, %s, input K%d\n",exponent,isBuffer?" Buffer":"Not buffer",iK); +#endif + double localDt=_dt/pow(2.0,(double)exponent); - 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 _AInner[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} - }; - // Big step RK43 - double _AOuter[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}, - }; -// Msg::Info("K%d, %d, %s",iK,exponent,isBuffer?"Buffer":"Bulk"); - // compute K[iK] for this exponent and buffer - if(isBuffer){ + if(!isBuffer){ + std::vector<dgGroupOfElements *> &gV=_bulkGroupsOfElements[exponent].first; + _currentInput->scale(gV,0.0); + _currentInput->axpy(gV,*_solution,1.0); + for(int i=0;i<iK;i++){ + if(A43[iK][i]!=0.0){ + _currentInput->axpy(gV,*_K[i],A43[iK][i]*localDt); + } + } + } + else{ std::vector<dgGroupOfElements *>&gVi=_innerBufferGroupsOfElements[exponent].first; std::vector<dgGroupOfElements *>&gVo=_outerBufferGroupsOfElements[exponent].first; _currentInput->scale(gVi,0.0); @@ -280,21 +303,44 @@ void dgRungeKuttaMultirate43::computeInputForK(int iK,int exponent,bool isBuffer _currentInput->axpy(gVi,*_solution,1.0); _currentInput->axpy(gVo,*_solution,1.0); for(int i=0;i<iK;i++){ - if(_AInner[iK][i]!=0.0) - _currentInput->axpy(gVi,*_K[i],_AInner[iK][i]*localDt*2); - if(_AOuter[iK][i]!=0.0) - _currentInput->axpy(gVo,*_K[i],_AOuter[iK][i]*localDt*2); + if(AInner43[iK][i]!=0.0) + _currentInput->axpy(gVi,*_K[i],AInner43[iK][i]*localDt*2); + if(AOuter43[iK][i]!=0.0) + _currentInput->axpy(gVo,*_K[i],AOuter43[iK][i]*localDt*2); } - } - else{ - std::vector<dgGroupOfElements *> &gV=_bulkGroupsOfElements[exponent].first; - _currentInput->scale(gV,0.0); - _currentInput->axpy(gV,*_solution,1.0); - for(int i=0;i<iK;i++){ - if(_A[iK][i]!=0.0){ - _currentInput->axpy(gV,*_K[i],_A[iK][i]*localDt); + /* + NOT NEEDED + // We need to update input for the neighboring elements with bigger time step. + // if there is no corresponding K to be computed + if( (iK>0 && iK<4) || (iK>5 && iK<9) ){ + std::vector<dgGroupOfElements *>&gVbigger=_bulkGroupsOfElements[exponent-1].first; + _currentInput->scale(gVbigger,0.0); + _currentInput->axpy(gVbigger,*_solution,1.0); + int idOuter2Bulk[10]={0,0,0,0,1,2,2,2,2,3}; + for(int i=0;i<iK;i++){ + if(AOuter43[iK][i]!=0.0){ + // ON DIRAIT QUE CETTE LIGNE DE CODE NE FAIT RIEN ... + _currentInput->axpy(gVbigger,*_K[idOuter2Bulk[i]],AOuter43[iK][i]*localDt*2); + } + } + std::vector<dgGroupOfElements *>&gViBigger=_innerBufferGroupsOfElements[exponent-1].first; + _currentInput->scale(gViBigger,0.0); + _currentInput->axpy(gViBigger,*_solution,1.0); + // shift + int s=0; + if(upperLeveliK>=5){ + for(int i=0;i<4;i++){ + _currentInput->axpy(gViBigger,*_K[i],b[i]*localDt*2); + } + s+=5; + } + for(int i=0;i<iK;i++){ + if(AOuter43[iK][i]!=0.0){ + _currentInput->axpy(gViBigger,*_K[idOuter2Bulk[i]+s],AOuter43[iK][i]*localDt*2); + } } } + */ } if(!isBuffer){ @@ -318,12 +364,10 @@ void dgRungeKuttaMultirate43::computeInputForK(int iK,int exponent,bool isBuffer computeInputForK(iK%5,exponent,false); } } - computeK(iK,exponent,isBuffer); -// Msg::Info("Multirate %d %0.16e",iK,_K[iK]->norm()); - if( (iK==3 && !isBuffer) || (iK==9 && isBuffer) ){ - updateSolution(exponent,isBuffer); - } - if(!isBuffer){ + if(exponent==0){ + computeK(iK,exponent,false); + if(iK==3) + updateSolution(exponent,false); switch(iK){ case 0: for(int i=1;i<4;i++){ @@ -337,17 +381,37 @@ void dgRungeKuttaMultirate43::computeInputForK(int iK,int exponent,bool isBuffer break; } } + if(isBuffer && exponent>0){ + if( (iK%5)<4) + computeK(iK%5,exponent,false); + computeK(iK,exponent,true); + if( (iK%5)==3) + updateSolution(exponent,false); + if(iK==9) + updateSolution(exponent,true); + switch(iK%5){ + case 0: + for(int i=1;i<4;i++){ + computeInputForK(i,exponent+1,true); + } + break; + case 2: + for(int i=6;i<9;i++){ + computeInputForK(i,exponent+1,true); + } + break; + } + } } void dgRungeKuttaMultirate43::updateSolution(int exponent,bool isBuffer){ - //Msg::Info("Updating solution at level %d %s",exponent,isBuffer?"Buffer":"Bulk"); + +#ifdef MULTIRATEVERBOSE + for(int i=0;i<exponent;i++) + printf("\t"); + printf("Updating solution at level %d %s\n",exponent,isBuffer?"Buffer":"Bulk"); +#endif double localDt=_dt/pow(2.0,(double)exponent); - 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 bInner[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 cInner[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 }; - double bOuter[10]={1.0/6.0, 0 , 0 , 0 , 1.0/3.0,1.0/3.0, 0 , 0 , 0 , 1.0/6.0}; - double cOuter[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 }; if(isBuffer){ std::vector<dgGroupOfElements *>&gVi=_innerBufferGroupsOfElements[exponent].first; std::vector<dgGroupOfElements *>&gVo=_outerBufferGroupsOfElements[exponent].first; @@ -364,6 +428,8 @@ void dgRungeKuttaMultirate43::updateSolution(int exponent,bool isBuffer){ if(b[i]!=0.0) _solution->axpy(gV,*_K[i],b[i]*localDt); } + _currentInput->scale(gV,0.0); + _currentInput->axpy(gV,*_solution,1.0); } } diff --git a/Solver/dgRungeKuttaMultirate.h b/Solver/dgRungeKuttaMultirate.h index ddeb70c79d7c3ee9bbd5a95d26fafc1cc0ef330f..f7a98fa322403950882548e48954835356b2f785 100644 --- a/Solver/dgRungeKuttaMultirate.h +++ b/Solver/dgRungeKuttaMultirate.h @@ -13,6 +13,7 @@ class dgRungeKuttaMultirate: public dgRungeKutta{ dgResidualVolume *_residualVolume; dgResidualInterface *_residualInterface; dgResidualBoundary *_residualBoundary; + dgGroupCollection *_gc; std::vector<std::pair<std::vector<dgGroupOfElements*>,std::vector<dgGroupOfFaces*> > >_bulkGroupsOfElements;// int is the multirateExponent std::vector<std::pair<std::vector<dgGroupOfElements*>,std::vector<dgGroupOfFaces*> > >_innerBufferGroupsOfElements;// int is the multirateExponent std::vector<std::pair<std::vector<dgGroupOfElements*>,std::vector<dgGroupOfFaces*> > >_outerBufferGroupsOfElements;// int is the multirateExponent