[overture] Re: deforming grid PDE solver

  • From: Bill Henshaw <henshaw@xxxxxxxx>
  • To: "overture@xxxxxxxxxxxxx" <overture@xxxxxxxxxxxxx>
  • Date: Thu, 26 Jul 2012 19:54:08 -0700

Thanks,
  I will take a look.

...Bill

On 07/26/2012 10:11 AM, jacob@xxxxxxxxxxxx wrote:
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







.



Other related posts: