Hi Bill, Here is a first stab: I just took deform.C and tried to tack on a diffusion equation solver on top. The current code gives rather spectacularly bad results, which is a little confusing to me, as my much more complicated fluid solver, which to my understanding works more or less the same, does not fail nearly this badly...Here it is: #include "Ogen.h" #include "PlotStuff.h" #include "NurbsMapping.h" #include "HyperbolicMapping.h" #include "Ogshow.h" #include "CompositeGridOperators.h" // // Deforming Grid Example: // o // o interpolate a grid function, update the interpolant for the new grid // o save solutions in a show file // int main(int argc, char *argv[]) { Overture::start(argc,argv); // initialize Overture Mapping::debug=0; int numberOfSteps=50; // take small time-steps for the grid int plotOption=true; if( argc > 1 ) { // look at arguments for "noplot" aString line; int len=0; for( int i=1; i<argc; i++ ) { line=argv[i]; if( line=="noplot" ) plotOption=false; else if( len=line.matches("-numSteps=") ) { sScanF(line(len,line.length()-1),"%i",&numberOfSteps); printF("Setting numberOfSteps=%i\n",numberOfSteps); } } } aString nameOfOGFile="iceCircle.hdf"; // use this grid to start // cout << "Enter the name of the (old) overlapping grid file:" << endl; // cin >> nameOfOGFile; // Create two CompositeGrid objects, cg[0] and cg[1] CompositeGrid cg[2]; getFromADataBase(cg[0],nameOfOGFile); // read cg[0] from a data-base file cg[1]=cg[0]; // copy cg[0] into cg[1] // Deform component grid 2 (do this by changing the mapping) int gridToDeform=2; // The grid we deform will be a Hyperbolic Mapping, we need 2 of them: HyperbolicMapping transform[2]; NurbsMapping *startCurve = new NurbsMapping [2]; // start curve representing the ice surface const int n0=13; realArray x0(n0,2), x1(n0,2), x2(n0,2); real rad=.5, theta; // x0: points on a arc x0(0,0)=0.; x0(0,1)=1.*rad; theta=Pi* 5./180.; x0(1,0)=-rad*sin(theta); x0(1,1)=rad*cos(theta); theta=Pi*10./180.; x0(2,0)=-rad*sin(theta); x0(2,1)=rad*cos(theta); theta=Pi*15./180.; x0(3,0)=-rad*sin(theta); x0(3,1)=rad*cos(theta); theta=Pi*20./180.; x0(4,0)=-rad*sin(theta); x0(4,1)=rad*cos(theta); theta=Pi*50./180.; x0(5,0)=-rad*sin(theta); x0(5,1)=rad*cos(theta); theta=Pi*90./180.; x0(6,0)=-rad*sin(theta); x0(6,1)=rad*cos(theta); theta=Pi*130./180.;x0(7,0)=-rad*sin(theta); x0(7,1)=rad*cos(theta); x0( 8,0)=x0(4,0); x0( 8,1)=-x0(4,1); x0( 9,0)=x0(3,0); x0( 9,1)=-x0(3,1); x0(10,0)=x0(2,0); x0(10,1)=-x0(2,1); x0(11,0)=x0(1,0); x0(11,1)=-x0(1,1); x0(12,0)=x0(0,0); x0(12,1)=-x0(0,1); // a second start curve (deformed version) x1=x0; x1(5,0)=-.7; x1(5,1)= .5; x1(6,0)=-.6; x1(6,1)= 0.; x1(7,0)=-.7; x1(7,1)= -.5; startCurve[0].interpolate(x0); startCurve[1].interpolate(x0); for( int i=0; i<=1; i++ ) { const bool isSurfaceGrid=false, init=true; transform[i].setSurface(startCurve[i],isSurfaceGrid,init); transform[i].setGridDimensions(axis1,61); transform[i].setParameters(HyperbolicMapping::distanceToMarch,.25); transform[i].setParameters(HyperbolicMapping::linesInTheNormalDirection,9); transform[i].setShare(0,1,1); transform[i].generate(); } // Replace the mapping of the component grid that we want to move: for( int i=0; i<=1; i++ ) { cg[i][gridToDeform].reference(transform[i]); cg[i].update(); } // now we destroy all the data on the new grid -- it will be shared with the old grid // this is not necessary to do but it will save space cg[1].destroy(CompositeGrid::EVERYTHING); // we tell the grid generator which grids have changed LogicalArray hasMoved(cg[0].numberOfGrids()); hasMoved = LogicalFalse; hasMoved(gridToDeform) = LogicalTrue; // Only this grid will change char buff[80]; //set boundary conditions in the proper locations const int DIRICHLET = 1; cg[0][0].boundaryCondition()(0,0) = DIRICHLET; cg[0][0].boundaryCondition()(1,0) = DIRICHLET; cg[0][0].boundaryCondition()(0,1) = DIRICHLET; cg[0][0].boundaryCondition()(1,1) = DIRICHLET; cg[0][1].boundaryCondition()(0,0) = 0; cg[0][1].boundaryCondition()(1,0) = 0; cg[0][1].boundaryCondition()(0,1) = DIRICHLET; cg[0][1].boundaryCondition()(1,1) = 0; cg[0][2].boundaryCondition()(0,0) = 0; cg[0][2].boundaryCondition()(1,0) = 0; cg[0][2].boundaryCondition()(0,1) = DIRICHLET; cg[0][2].boundaryCondition()(1,1) = 0; PlotStuff ps(plotOption,"Deforming Grid Example"); // for plotting PlotStuffParameters psp; // Here is the overlapping grid generator Ogen gridGenerator(ps); // update the initial grid, since the above reference destroys the mask gridGenerator.updateOverlap(cg[0]); // Here is an interpolant Interpolant & interpolant = *new Interpolant(cg[0]); interpolant.incrementReferenceCount(); //why do we have to do this here? CompositeGridOperators operators(cg[0]); // operators for the CompositeGrid realCompositeGridFunction u(cg[0]), F(cg[0]); u = 0.; F = 1.; u.setOperators(operators); F.setOperators(operators); //diffusion term const real nu = 1; //we'll solve the diffusion equation /****************** u_t = nu*(u_{xx} + u_{yy}) + 1 u(0) = 0 ******************/ //with zero dirichlet boundary conditions on all boundaries //the first version will be forward Euler explicit time stepping // Here is a show file Ogshow show("deform.show"); show.setIsMovingGridProblem(true); //the time step size for the grid deformation real delta=1./numberOfSteps; //moves the time-step int nx = 81; //the grid dimensions for CFL //the time-step size for the forward Euler solves const int numSubSteps = std::ceil(3*nx*nx); const real dt = 1./numSubSteps; //viscous time-step restriction for the forward Euler solves std::cout << "numSubSteps: " << numSubSteps << std::endl; // ---- Deform the grid in a periodic fashion.---- for (int i=1; i<=numberOfSteps; i++) { int newCG = i % 2; // new grid int oldCG = (i+1) % 2; // old grid ps.erase(); psp.set(GI_TOP_LABEL,sPrintF(buff,"Solution at step=%i",i)); // set title //PlotIt::plot(ps,cg[oldCG],psp); // plot the current overlapping grid PlotIt::contour(ps,u,psp); if( i>10 ) psp.set(GI_PLOT_THE_OBJECT_AND_EXIT,TRUE); // set this to run in "movie" mode (after first plot) ps.redraw(TRUE); //real deltaOmega=1./20.; real deltaOmega = delta; real omega=pow(sin(Pi*i*deltaOmega),2.); // omega varies in the interval [0,1] x2 = (1.-omega)*x0 + omega*x1; startCurve[newCG].interpolate(x2); // form the new start curve (NurbsMapping) const bool isSurfaceGrid=false; const bool init=false; // this means keep existing hype parameters such as distanceToMarch, linesToMarch etc. transform[newCG].setSurface(startCurve[newCG],isSurfaceGrid,init); // supply a new start curve // ** generate the new grid with the hyperbolic grid generator ** transform[newCG].generate(); // Update the overlapping grid newCG, starting with and sharing data with oldCG. Ogen::MovingGridOption option = Ogen::useOptimalAlgorithm; int useFullAlgorithmInterval=1; // 10; if( i% useFullAlgorithmInterval == useFullAlgorithmInterval-1 ) { cout << "\n +++++++++++ use full algorithm in updateOverlap +++++++++++++++ \n"; option=Ogen::useFullAlgorithm; } gridGenerator.updateOverlap(cg[newCG], cg[oldCG], hasMoved, option ); cg[newCG][0].boundaryCondition()(0,0) = DIRICHLET; cg[newCG][0].boundaryCondition()(1,0) = DIRICHLET; cg[newCG][0].boundaryCondition()(0,1) = DIRICHLET; cg[newCG][0].boundaryCondition()(1,1) = DIRICHLET; cg[newCG][1].boundaryCondition()(0,0) = 0; cg[newCG][1].boundaryCondition()(1,0) = 0; cg[newCG][1].boundaryCondition()(0,1) = DIRICHLET; cg[newCG][1].boundaryCondition()(1,1) = 0; cg[newCG][2].boundaryCondition()(0,0) = 0; cg[newCG][2].boundaryCondition()(1,0) = 0; cg[newCG][2].boundaryCondition()(0,1) = DIRICHLET; cg[newCG][2].boundaryCondition()(1,1) = 0; cg[newCG].update(); //move the solution and operators to the new grid [!?] interpolant.updateToMatchGrid(cg[newCG]); operators.updateToMatchGrid(cg[newCG]); u.updateToMatchGrid(cg[newCG]); interpolant.interpolate(u); F.updateToMatchGrid(cg[newCG]); interpolant.interpolate(F); //clamp u to zero on the boundaries for(int grid = 0; grid <= 2; grid++) { //ok I know there are exactly 3 grids //MappedGrid& mg = cg[newCG][grid]; for(int axis = 0; axis <= 1; axis++) { for(int side = 0; side <= 1; side++) { if( cg[newCG][grid].boundaryCondition()(side,axis) == DIRICHLET) { Index I1,I2,I3; getBoundaryIndex(cg[newCG][grid].gridIndexRange(),side,axis,I1,I2,I3); u[grid](I1,I2,I3) = 0.; } } } } u.applyBoundaryCondition(0,BCTypes::dirichlet,DIRICHLET,0.); u.finishBoundaryConditions(); //take the requisite number of forward Euler time-steps to catch up to the grid for(int k = 0; k < numSubSteps; k++) { u += dt*( nu*(u.xx() + u.yy()) + F); } interpolant.interpolate(u); // save the result in a show file, every fourth step if( (i % 4) == 1 ) { show.startFrame(); show.saveComment(0,sPrintF(buff,"Solution at step = %i",i)); show.saveSolution(u); } } printF("Results saved in deform.show, use Overture/bin/plotStuff to view this file\n"); printF("deform: interpolant.getReferenceCount=%i\n",interpolant.getReferenceCount()); if( interpolant.decrementReferenceCount()==0 ) { printF("deform: delete Interpolant\n"); delete &interpolant; } Overture::finish(); return 0; } Best, Jacob On Thu, July 26, 2012 9:02 am, Bill Henshaw wrote: > Hi Jacob, > My thought was to develop a relatively simple example code > that we could add to the Overture distribution for other > people to use. If you want to make a first attempt then > I can make adjustments. > > ....Bill > > > On 07/25/2012 09:49 PM, jacob@xxxxxxxxxxxx wrote: >> Hi Bill, >> >> Hmm I agree, though I had thought move2.C was a bit complicated and >> wasn't >> sure what exactly it was doing, so I more used deform.C to make my guess >> at how to deform the grids...But yeah I can take a pass at making a test >> code which is a bit simpler...maybe I'll try advection-diffusion first >> with explicit and then with implicit stepping, since updating the solver >> should "probably" be trickier. For the deforming boundary I'll probably >> first use some kind of spline that deforms in a pre-defined way and try >> to >> build a HyperbolicMapping off of it...if that doesn't work I'll >> back-pedal >> and try something simpler... >> >> Best, >> Jacob >> >> On Wed, July 25, 2012 11:47 pm, Bill Henshaw wrote: >>> Hi Jacob, >>> Thanks for the code segments. You have made some good progress, >>> although >>> I do see some problems with what you are doing. >>> >>> Recall: >>> GOLDEN RULE 3 of programming -- "It always saves time in >>> the long run to have a simple test code". >>> >>> Corollary of Golden Rule 3: you may hate this rule but unfortunately >>> it is really true. >>> >>> Unfortunately I have not created a simple deforming grid >>> PDE solver code. I think that the first step is for us to create >>> such a code. I think the easiest way to do this is to merge >>> deform.C and move2.C so that we solve an advection diffusion >>> equation with twilight-zone on a deforming grid. Perhaps you >>> want to make a first attempt at doing this? Otherwise I can >>> try to put something together but I'm not sure when I can get >>> to it. >>> >>> >>> ...Bill >>> >>> >>> >> >> >> > >