Пример #1
0
int bound_prim_user(int boundstage, FTYPE prim[][N2M][N3M][NPR])
{
  int i, j, k, pl;
  struct of_geom geom,rgeom;
  FTYPE vcon[NDIM]; // coordinate basis vcon
#if(WHICHVEL==VEL3)
  int failreturn;
#endif
  int ri, rj, rk; // reference i,j,k
  FTYPE prescale[NPR];







  ///////////////////////////
  //
  // X1 inner OUTFLOW/FIXEDOUTFLOW
  //
  ///////////////////////////

  if (mycpupos[1] == 0) {
    if((BCtype[X1DN]==OUTFLOW)||(BCtype[X1DN]==FIXEDOUTFLOW)){
      /* inner r boundary condition: u, just copy */
      LOOPN2 LOOPN3{
#if(EXTRAP==0)
	ri=0;
	rj=j;
	rk=k;
	LOOPBOUND1IN PBOUNDLOOP(pl) prim[i][j][k][pl] = prim[ri][rj][rk][pl];
#elif(EXTRAP==1)

	ri=0;
	rj=j;
	rk=k;
	LOOPBOUND1IN{
	  for(pl=RHO;pl<=UU;pl++){
	    prim[i][j][k][pl] = prim[ri][rj][rk][pl] * gdet[ri][rj][rk][CENT]/gdet[i][j][k][CENT] ;
	  }
	  pl=U1;	    // treat U1 as special
	  prim[i][j][k][pl] = prim[ri][rj][rk][pl] * (1. - (i-ri)*dx[1]) ;
	  for(pl=U2;pl<=U3;pl++){
	    prim[i][j][k][pl] = prim[ri][rj][rk][pl] * (1. + (i-ri)*dx[1]) ;
	  }
	  pl=B1; // treat B1 special
	  prim[i][j][k][pl] = prim[ri][rj][rk][pl] * gdet[ri][rj][rk][CENT]/gdet[i][j][k][CENT] ;
	  for(pl=B2;pl<=B3;pl++){
	    prim[i][j][k][pl] = prim[ri][rj][rk][pl] * (1. + (i-ri)*dx[1]) ;
	  }
	}
#elif(EXTRAP==2)
	ri=0;
	rj=j;
	rk=k;
	get_geometry(ri, rj, rk, CENT, &rgeom);
	rescale(1,1,prim[ri][rj][rk],&rgeom,prescale);
	LOOPBOUND1IN{
	  // set guess
	  PBOUNDLOOP(pl) prim[i][j][k][pl]=prim[ri][rj][k][pl];
	  get_geometry(i, j, k, CENT, &geom);	    
	  rescale(-1,1,prim[i][j][k],&geom,prescale);
	}
#endif
	LOOPBOUND1IN{
#if(WHICHVEL==VEL4)
	  get_geometry(i, j, k, CENT, &geom);
	  inflow_check_4vel(1,prim[i][j][k],&geom, 0) ;
#elif(WHICHVEL==VEL3)
	  get_geometry(i, j, k, CENT, &geom);
	  inflow_check_3vel(1,prim[i][j][k],&geom, 0) ;
	  // projection may not preserve u^t to be real and rho>rhoscal u>uuscal
#if(JONCHECKS)
	  if(jonchecks){
	    //fixup1zone(prim[i][j][k],&geom,0);
	    failreturn=check_pr(prim[i][j][k],prim[i][j][k],&geom,-3);
	    if(failreturn){
	      dualfprintf(fail_file,"Bad boundary zone, couldn't fix: i=%d j=%d k=%d\n",startpos[1]+i,startpos[2]+j,startpos[3]+k);
	      if (fail(FAIL_BCFIX) >= 1) return (1);
	    }
	  }
#endif
#elif(WHICHVEL==VELREL4)
	  get_geometry(i,j,k,CENT,&geom) ;
	  inflow_check_rel4vel(1,prim[i][j][k],&geom,0) ;
	  if(limit_gamma(GAMMAMAX,prim[i][j][k],&geom,0)>=1)
	    FAILSTATEMENT("bounds.c:bound_prim()", "limit_gamma()", 1);
#endif	
	}
      }// end 2 3
    }// end if correct bound type

  }// end if mycpupos[1]==0
Пример #2
0
int main(int argc, char **argv)
{
    unsigned int num_customers;
    unsigned int num_selfserve = 0, num_barista = 0, num_cashier = 0; 
    int opt, ret = -1, profit;
    long avg_simple, avg_complex;

    if(argc < 2) {
        print_usage(argv[0]);
        goto out;
    }
    num_customers = atoi(argv[1]);
    check_pr(!num_customers, "Need at least one customer", out);


    while((opt = getopt(argc, argv, "s:b:c:q")) != -1)
    {
        switch(opt) {
            case 's': 
                num_selfserve = atoi(optarg);
                break;
            case 'b':
                num_barista = atoi(optarg);
                break;
            case 'c':
                num_cashier = atoi(optarg);
                break;
            case 'q':
                quiet = 1;
                break;
            default:
                print_usage(argv[0]);
                goto out;
        }
    }

    if(quiet) {
        check(!num_barista, out);
    } else {
        check_pr(!num_barista, "Need at least one barista", out);
    }

    if(num_selfserve) {
        if(quiet) {
            check(!num_cashier, out);
        } else {
            check_pr(!num_cashier, "Need at least one cashier", out);
        }
    }

    if(!quiet)
        printf( "Customers     :\t%d\n"
                "Self Services :\t%d\n"
                "Baristas      :\t%d\n"
                "Cashiers      :\t%d\n", 
                num_customers, num_selfserve, 
                num_barista, num_cashier);

    /* Allocate room for our list of times */
    simple_times = malloc(sizeof(long) * num_customers);
    check(!simple_times, free_times);
    complex_times = malloc(sizeof(long) * num_customers);
    check(!complex_times, free_times);

    profit = start_day(num_customers,
            num_selfserve, num_barista, num_cashier);
    check_pr(profit < 0, 
                "Simulation Aborted (Out of resources).",
                out);
    print_profit(profit);
    /* Compute the average turnaround time for each customer type */
    if(simple_count.val > 0)
        avg_simple = average_list(simple_times, simple_count.val);
    else
        avg_simple = 0l;
    if(complex_count.val > 0)
        avg_complex = average_list(complex_times, complex_count.val);
    else
        avg_complex = 0l;
    printf("Avg Simple :\t");
    print_time(avg_simple);
    printf("Avg Complex:\t");
    print_time(avg_complex);

    ret = 0;
free_times:
    if(complex_times)
        free(complex_times);
    if(simple_times)
        free(simple_times);
out:
    pthread_exit(&ret);
}
Пример #3
0
/* 
 * Starts a day in the new mode of operation- two queues, one that
 * feeds into self-service, and one that feeds into the coffee bar.
 *
 * One queue is also kept for the cashier.
 */
int start_day_complex(int n_customers, int n_selfserve,
        int n_barista, int n_cashier)
{
    struct server *server = NULL, *selfserve = NULL, *cashier = NULL;
    struct addict *cur;
    int i, rand, ret = 1;
    pthread_attr_t attr;
    pthread_t *threads = malloc(n_customers * sizeof(pthread_t));
    check_pr(!threads, "Out of memory", out);

    /* Instantiate the service lines */
    server    = init_server(n_barista);
    selfserve = init_server(3 * n_selfserve);
    cashier   = init_server(n_cashier);
    check_pr((!cashier || !server || !selfserve), 
            "Out of memory", free_threads);

    /* Initialize the detachable attributes */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    /* Spawn customers of random type (simple, complex). */
    srand(time(NULL));
    for(i = 0; i < n_customers; i++) {
        rand = rand_range(2); /* Two types to select */
        switch(rand) {
            case 0:
                cur = init_addict(ATIME_SIMPLE, ACOST_SIMPLE,
                        selfserve, cashier);
                break;
            default:
                cur = init_addict(ATIME_COMPLEX, ACOST_COMPLEX,
                        server, cashier);
        }
        check_pr(!cur, "Out of memory", finish);
        /* Start the timer */
        gettimeofday(&cur->start, NULL);
again:
        /* Start the corresponding thread */
        ret = pthread_create(&threads[i], &attr, (void *)*get_coffee, 
                cur);
        if(ret) {
            if(!quiet)
                printf("Failed to start thread %d, trying again\n",
                        i);
            sched_yield();
            goto again;
        }
        count_inc(running_threads, 1);
    }
    ret = 0;
finish:
    /* Wait until the work for the day is done */
    pthread_mutex_lock(&running_threads.count_mutex);
    while(running_threads.val > 0) {
        pthread_cond_wait(&running_threads.cond, 
                &running_threads.count_mutex);
    }
    pthread_mutex_unlock(&running_threads.count_mutex);
free_threads:
    /* Free all of the threads, and all of the servers */
    free(threads);
    if(server)
        free(server);
    if(selfserve)
        free(selfserve);
    if(cashier)
        free(cashier);
out:
    return ret;
}
Пример #4
0
/* auxiliary function required by mnewt */
int usrfun(FTYPE *U_target,FTYPE *pr0,int numnormterms,int whichcons, int primtoUcons, struct of_geom *ptrgeom, FTYPE *prguess, int n, FTYPE *beta, FTYPE **alpha,FTYPE*norm)
{
  static FTYPE **alpha5;
  FTYPE prstart[NPR];
  FTYPE *pr;
  static FTYPE U[NPR],U_curr[NPR];
  struct of_state q;
  int i, j, k;
  int pl,pliter;
  int failreturn=0;
  void removerow(int row, FTYPE **alpha5,FTYPE**alpha);
  static int firstc=1;

  if (firstc) {
    firstc = 0;
    alpha5 = dmatrix(1, 5, 1, 5);
  }


  pr=prguess+1;

  // Doing this constrained iteration may lead to non-convergence, but then we adjust U if that happens until we converge.

  // store old pr
  PLOOP(pliter,pl) prstart[pl]=pr[pl];

  // these checks seem to cause problems with convergence of any kind // GODMARK
  // we need to make sure densities are ok while iterating.
#if(WHICHVEL==VEL3)
  if(0&&jonchecks) fixup1zone(pr,ptrgeom,0);

  // once pr lead to imaginary u^t, state is invalid and U cannot be found.
  // Thus, need to adjust pr while iterating to keep pr in line
  // essentially we are doing a constrained damped Newton's method.
  if(0&&jonchecks) failreturn=check_pr(pr,pr0,ptrgeom,-100);
  if(0&&jonchecks) if(failreturn>=1)
                     FAILSTATEMENT("utoprim.c:usrfun()", "mnewt check:check_pr()", 2);

  // just check
  if(jonchecks) failreturn=check_pr(pr,pr0,ptrgeom,-2);
#endif



  if(!failreturn){

    // if didn't fail, we are guarenteed a good state and U.
    
    // problem here is that now pr is different and doesn't help
    // converge to Utarget, maybe kills possibility of convergence which
    // would later be just fixed at the end
    // so should probably adjust Utarget somehow to compensate for adjustment in pr.  Use dudp to fix U_target along the way
    
    /* normalize error = beta to \rho u^t */
    failreturn=get_state(pr, ptrgeom, &q);
    if(failreturn>=1)
      FAILSTATEMENT("utoprim.c:usrfun()", "get_state()", 1);

    failreturn=primtoU(primtoUcons,pr, &q, ptrgeom, U);

    // DEBUG:
    //    dualfprintf(fail_file,"nprlist: %d %d %d %d\n",nprstart,nprend,nprlist[nprstart],nprlist[nprend]);
    //    dualfprintf(fail_file,"1primtoUcons=%d ptrgeom.g=%21.15g\n",primtoUcons,ptrgeom->g);
    //    for (pl = 0; pl < INVERTNPR ; pl++)
    //      dualfprintf(fail_file,"pr[%d]=%21.15g U[%d]=%21.15g\n",pl,pr[pl],pl,U[pl]);


    if(failreturn>=1)
      FAILSTATEMENT("utoprim.c:usrfun()", "primtoU()", 1);

#if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)
    PLOOP(pliter,pl) U_curr[pl]=U[pl];
#elif(EOMTYPE==EOMFFDE)
    // convert from normal U to iterative U
    fixUtarget(WHICHFFDEINVERSION,U,U_curr);
#endif


    failreturn=dudp_calc(WHICHEOS, whichcons,GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),pr, &q, ptrgeom, alpha5);
    if(failreturn>=1)
      FAILSTATEMENT("utoprim.c:usrfun()", "dudp_calc()", 1);


    // convert from normal alpha to iterative alpha
#if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)
    for (j = 0; j < INVERTNPR ; j++){
      for (k = 0; k < INVERTNPR ; k++){
        alpha[j+1][k+1]=alpha5[j+1][k+1];
      }
    }    
#elif(EOMTYPE==EOMFFDE)

#if(WHICHFFDEINVERSION==0)
    removerow(U2,alpha5,alpha);
#elif(WHICHFFDEINVERSION==1)
    removerow(U1,alpha5,alpha);
#elif(WHICHFFDEINVERSION==2)
    removerow(UU,alpha5,alpha);
#endif

#endif

    /////////////////////
    //
    // normalize matrix
    //
    ////////////////////
#if(NORMMETHOD==-1)
    *norm=1.0;
#elif(NORMMETHOD==0)
    *norm=1.0/U_target[RHO];
#elif(NORMMETHOD==1)
    // more general normalization
    *norm=0.0;
    numnormterms=0;
    for (j = 0; j < INVERTNPR ; j++){
      for (k = 0; k < INVERTNPR ; k++){
        // GODMARK: correction:
        if(fabs(alpha[j + 1][k + 1])>NUMEPSILON){
          // old version (bug)
          //    if(alpha[j + 1][k + 1]>NUMEPSILON){
          *norm+=fabs(alpha[j + 1][k + 1]);
          numnormterms++;
        }
      }
    }
    *norm=(FTYPE)(numnormterms)/(*norm); // (i.e. inverse of average)

#endif
    
    for (j = 0; j < INVERTNPR ; j++)
      for (k = 0; k < INVERTNPR ; k++)
        alpha[j + 1][k + 1] *= (*norm);

    
    // below assumes alpha at U_curr isn't too different from at U_target
    // doesn't seem to work
    /*
      for (j = 0; j < INVERTNPR ; j++){
      for (k = 0; k < INVERTNPR ; k++){
      // should really use average alpha from initial pr and new pr, but try just new pr's dudp
      U_target[j]+=U_target[RHO]*alpha[j+1][k+1]*(pr[k]-prstart[k]);
      }
      }
    */   

    // determine normalized error
    for (k = 0; k < INVERTNPR ; k++)
      beta[k + 1] = (U_curr[k] - U_target[k]) *(*norm);


    // DEBUG:
    //    dualfprintf(fail_file,"primtoUcons=%d\n",primtoUcons);
    //    for (k = 0; k < INVERTNPR ; k++)
    //      dualfprintf(fail_file,"pr[%d]=%21.15g U_curr[%d]=%21.15g U_target[%d]=%21.15g\n",k,pr[k],k,U_curr[k],k,U_target[k]);
    

  }
  else{
    // error is huge if failed, a marker for failure
    for (k = 0; k < INVERTNPR ; k++)
      beta[k + 1] = 1.E30;
    
  }
  
  return (0);
}
Пример #5
0
/* pr *MUST* contain initial guess */
int Utoprim(int whichcons, FTYPE *U, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats)
{
  FTYPE U_target[NPR];
  FTYPE pr0[NPR];
  int numnormterms;
  int primtoUcons;
  //
  FTYPE priter[NPR];
  FTYPE prguess[NPR];
  FTYPE tolx, tolf,tolxallowed, tolfallowed, tolxreport, tolfreport;
  int ntrial, mnewtfailed,mintrial;
  int pl,pliter;
  FTYPE Ustart[NPR];
  FTYPE dU[NPR];
  struct of_state q;
  int i,j,k,loc;
  int nutoprims,countutoprims;
  FTYPE frac,SUPERFRAC;
  int faildebug1(int numnormterms, int whichcons, FTYPE *U_target, FTYPE *EOSextra, FTYPE *pr0, struct of_geom *ptrgeom);
  int faildebug2(int numnormterms, int whichcons, FTYPE *U_target, FTYPE *EOSextra, FTYPE *pr0, struct of_geom *ptrgeom);
  void fixUtarget(int which,FTYPE *Ui,FTYPE *Uf);
  extern int mnewt(FTYPE *U_target,FTYPE *pr0,int numnormterms,int whichcons, int primtoUcons, struct of_geom *ptrgeom, int whethertoreport,int ntrial, int mintrial, FTYPE x[], int n, int startp, FTYPE tolx, FTYPE tolf, FTYPE tolxallowed, FTYPE tolfallowed, FTYPE tolxreport, FTYPE tolfreport, struct of_newtonstats *newtonstats);
  int usrfun(FTYPE *U_target,FTYPE *pr0,int numnormterms,int whichcons, int primtoUcons, struct of_geom *ptrgeom, FTYPE *prguess, int n, FTYPE *beta, FTYPE **alpha,FTYPE*norm);
  int Utoprim_nonrel(FTYPE *U, struct of_geom *ptrgeom, FTYPE *pr);
  FTYPE prnonrel[NPR];
  FTYPE prrel[NPR];
  int flagifnonrel;
  int whethertoreport;
  FTYPE bsq;
  int entropyversion;


  i=ptrgeom->i;
  j=ptrgeom->j;
  k=ptrgeom->k;
  loc=ptrgeom->p;


#if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)
#define INVERTNPR (5) // always same
#define STARTPINVERT (RHO) // where to start in primitive space
#elif(EOMTYPE==EOMCOLDGRMHD)
#define INVERTNPR (4) // always same
#define STARTPINVERT (RHO) // where to start in primitive space
  // need to skip UU if using this (SUPERGODMARK -- not done yet)
#elif(EOMTYPE==EOMFFDE)
#define INVERTNPR (3) // always same
#define STARTPINVERT (U1) // where to start in primitive space
#endif



  *lpflag= UTOPRIMNOFAIL; // set as no failure at first
  // assume normally do not want special messages
  whethertoreport=0;


  /////////////
  //
  // check (disabled since should allow negative density so RK can recover)
  //
  ////////////
  if(0&&( (EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)||(EOMTYPE==EOMCOLDGRMHD) )){ // don't check for now, just fail later
    if (U[RHO] < 0.) {
      if (fail(i,j,k,loc,FAIL_UTOPRIM_NEG) >= 1)
        return (1);
    }
  }
  
  ////////////////
  //
  // evolve B before (also better than initial guess)
  /* solution is known for B, so best guess is solution (from point of view of other variables) */
  //
  ///////////////
  for (pl = B1; pl <= B3; pl++) pr[pl] = U[pl];




  //////////////////////
  //
  // rest determines rho,u,u^i for GRMHD or u^i for FFDE
  //


#if(PRECISEINVERSION)
  ntrial = 200;
  mintrial = 3;
  tolx = tolf = 1.e-11; // 1E-11 is best mnewt() can do with DODAMP=2
  tolxallowed = tolfallowed = 1.e-8 ;
  tolxreport=1.e4*tolx;
  tolfreport=1.e4*tolf;
  
#else
  // choice
  ntrial = 20;
  mintrial=2;
  tolx = 1.e-10;
  tolf = 1.e-10;
  tolxallowed=tolfallowed=1.e-4;
  tolxreport=1.e3*tolx;
  tolfreport=1.e3*tolf;
#endif



  /////////////
  //
  // Setup inversion
  //
  ////////////


  // store initial guess and U as target
  PLOOP(pliter,pl) pr0[pl]=priter[pl]=pr[pl];


  entropyversion=0;

#if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)
  PLOOP(pliter,pl) U_target[pl] = U[pl];

  //#define NORMMETHOD (-1)
#define NORMMETHOD (1)
  // -1: no normalization
  // 0=use Utarget[RHO]
  // 1=use generaleralized mean so matrix stays well conditioned

  // assume normally want special messages
  whethertoreport=1;
  entropyversion=0;

  if((whichcons==EVOLVENOENTROPY)||(whichcons==EVOLVESIMPLEENTROPY)){
    primtoUcons=UNOTHING;
    // normal total energy inversion
    // if evolvesimpleentropy, then just invert in utoprim() after mnewt succeeds
  }
  else if(whichcons==EVOLVEFULLENTROPY){
    entropyversion=1;
    primtoUcons=UENTROPY; // implicit UNOTHING with entropy cons. quant. assigned to UU cons. quant.
    // overwrite total energy EOM with entropy EOM
    U_target[UU]=U_target[ENTROPY];
    // assumes dudp_calc replaces total energy equation with entropy equation

#if(ENTROPY==-100)
    dualfprintf(fail_file,"Should not be here in utoprim() ENTROPY variable defined\n");
    myexit(2486726);
#endif

  }


#if(1)
  // No, now further assume if not getting inversion within short trials, not going to happen and reduces to other method for "inversion"
  // No, now assuming want accurate dissipation tracking and avoidance of problems in strong shocks
  // assume don't want special messages if just using entropy evolution for comparison and not primary evolution
  if(whichcons==EVOLVEFULLENTROPY){
    whethertoreport=0;
    // then simplify inversion a bit
    ntrial = 20;
    mintrial=2;
    tolx = 1.e-6;
    tolf = 1.e-6;
    tolxallowed=tolfallowed=1.e-4;
    tolxreport=1.e3*tolx;
    tolfreport=1.e3*tolf;
  }
#endif


#elif(EOMTYPE==EOMCOLDGRMHD)

  // SUPERGODMARK: Not done yet

#define NORMMETHOD (1)  // no choice
#define WHICHFFDEINVERSION 0 // choice (see below)

  primtoUcons=UNOTHING;

  fixUtarget(WHICHFFDEINVERSION,U,U_target);

  // zero internal energy density so can use standard dU/dp
  priter[UU]=0;

#elif(EOMTYPE==EOMFFDE)

#define NORMMETHOD (1)  // no choice
#define WHICHFFDEINVERSION 0 // choice (see below)

  primtoUcons=UNOTHING;

  fixUtarget(WHICHFFDEINVERSION,U,U_target);

  // zero densities so can use standard dU/dp
  priter[RHO]=priter[UU]=0;

#endif










  /////////////
  //
  // checks if initial pr gives good u^t and determines U(pr)
  //
  ////////////

  if (get_state(pr, ptrgeom, &q) >= 1){
    //    dualfprintf(fail_file,"bad guess: i=%d j=%d k=%d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
    //    PLOOP(pliter,pl) dualfprintf(fail_file,"bad guess: pr=%21.15g\n",pr[pl]);
    // then guess bad, adjust guess
    set_atmosphere(0,WHICHVEL,ptrgeom,prguess);
    for(pl=U1;pl<=U3;pl++) pr[pl]=prguess[pl]; // only reset velocities
    // try again
    if (get_state(pr, ptrgeom, &q) >= 1)
      FAILSTATEMENT("utoprim.c:utoprim()", "get_state()", 1);
    //    PLOOP(pliter,pl) dualfprintf(fail_file,"good guess: pr=%21.15g\n",pr[pl]);
  }
  if (primtoU(primtoUcons,pr, &q, ptrgeom, Ustart) >= 1)
    FAILSTATEMENT("utoprim.c:utoprim()", "primtoU()", 1);
  // now we have U(pr)



  // only try non-rel inversion if normal inversion (not entropy-based since not setup)
  ////////////////////
  //
  // if u^t=1, then can do non-relativistic inversion
  //
  ////////////////////

  flagifnonrel=0;

#define DONONRELINV 1

  if(entropyversion==0){


#if(DONONRELINV&&( (EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)||(EOMTYPE==EOMCOLDGRMHD) ) )

    // get b^2 to check if b^2/rho_0<<1
    bsq = dot(q.bcon, q.bcov);

    flagifnonrel=0;
    if(
       (fabs(q.ucon[TT]-1.0)*fabs(q.ucon[TT]-1.0)<NUMEPSILON*5.0)
       ||(fabs(bsq/(SMALL+fabs(pr[RHO])))<NUMEPSILON*5.0)
       ||(fabs(fabs(pr[UU])/(SMALL+fabs(pr[RHO])))<NUMEPSILON*5.0)
       ){
      flagifnonrel=1;

      if(Utoprim_nonrel(U_target,ptrgeom,pr)>0){
        *lpflag= UTOPRIMFAILRHONEG;
        flagifnonrel=0; //then can't trust non-rel inversion
      }
      else{
    
        // report if failure.  Only negative densities can occur with non-relativistic inversion
        if((pr[RHO]<=0.)&&(pr[UU]>=0.)) *lpflag= UTOPRIMFAILRHONEG;
        if((pr[RHO]>=0.)&&(pr[UU]<=0.)) *lpflag= UTOPRIMFAILUNEG;
        if((pr[RHO]<=0.)&&(pr[UU]<=0.)) *lpflag= UTOPRIMFAILRHOUNEG;

        if(IFUTOPRIMNOFAILORFIXED(*lpflag)){
          //    PLOOP(pliter,pl) dualfprintf(fail_file,"U[%d]=%21.15g pr0[%d]=%21.15g pr[%d]=%21.15g\n",pl,U_target[pl],pl,pr0[pl],pl,pr[pl]);
        }
        PLOOP(pliter,pl) prnonrel[pl]=pr[pl];
      
        /////////////
        //
        // checks if initial pr gives good u^t and determines U(pr)
        //
        ////////////
        if (get_state(pr, ptrgeom, &q) >= 1)
          FAILSTATEMENT("utoprim.c:utoprim()", "get_state()", 1);
        if(fabs(q.ucon[TT]-1.0)>NUMEPSILON*5.0) flagifnonrel=0;
      }
    }
    else{
      flagifnonrel=0;
      PLOOP(pliter,pl) prnonrel[pl]=-1.0;
    }
#else
    flagifnonrel=0;
    PLOOP(pliter,pl) prnonrel[pl]=-1.0;
#endif

    //  dualfprintf(fail_file,"uu0diff1=%21.15g flagifnonrel=%d\n",fabs(q.ucon[TT]-1.0),flagifnonrel);
  } // end if not doing entropy inversion
  else{
    flagifnonrel=0;
    PLOOP(pliter,pl) prnonrel[pl]=-1.0;
  }












  if(flagifnonrel==0){
    //////////////////
    //
    // setup mnewt
    //
    //////////////////
    mnewtfailed=1; // assume failed
    nutoprims=1; // >1 usually, but 1 means directly to static if failed (with one chance for SUPERFRAC)
    countutoprims=nutoprims;
    frac=1.0/((FTYPE)nutoprims); // so that by nutoprims adjustments we are back at U_target=Ustart
    SUPERFRAC=0.0001;
    PLOOP(pliter,pl) dU[pl]=U_target[pl]-Ustart[pl];


    //  PLOOP(pliter,pl) dualfprintf(fail_file,"IN: i=%d j=%d k=%d :: pr0[%d]=%21.15g U[%d]=%21.15g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pl,pr0[pl],pl,U_target[pl]);
    //////////////////
    //
    // mnewt (loop)
    //
    //////////////////
    while(mnewtfailed){
      if(mnewtfailed){
        if(countutoprims==-1){
          // forced to use static solution. Probably better ways than a
          // linear approx, but better than nothing.  Must improve flux,
          // or lower courant factor to otherwise improve this situation
          break;
        }
        if(countutoprims==0){
          // force to be nearly identical instead of exactly identical, last hope!
          PLOOP(pliter,pl) U_target[pl]=Ustart[pl]+dU[pl]*SUPERFRAC;
        }
        else{
          // Only failed because U_target is trying to send u^t to imaginary values, or densities to negative values
          // try backup up towards original solution in conservative variable space
          PLOOP(pliter,pl) U_target[pl]=Ustart[pl]+dU[pl]*(FTYPE)countutoprims*frac;
        }
      }

      // mnewt is set to only take 5 entries and deal with pl=0-4 in the inversion.
      //
      // notice that priter is used.  Assumes setup Utarget to be consistent with priter and INVERTNPR
      //
      mnewtfailed = mnewt(U_target, pr0, numnormterms, whichcons, primtoUcons, ptrgeom, whethertoreport,ntrial, mintrial, priter - 1, INVERTNPR , STARTPINVERT, tolx, tolf, tolxallowed, tolfallowed, tolxreport, tolfreport,newtonstats);



      if(mnewtfailed) countutoprims--;
      if(nutoprims==1){
        break; // if failed, static immediately if failure since apparently goes that way anyways
        // if good, then break cause we are done
      }

    }

    /////////////////////
    //
    // convert the priter->pr
    //
    /////////////////////
    PLOOP(pliter,pl) prrel[pl]=priter[pl];


  }
  else{
    mnewtfailed=0; // don't trigger debug stuff for mnewt if not using it
    PLOOP(pliter,pl) prrel[pl]=-1;
  }



  /////////////////////
  //
  // ASSIGN ANSWER from mnewt or non-rel inversion
  //
  /////////////////////

#if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD || EOMTYPE==EOMCOLDGRMHD)



#if(0)
  //  PLOOP(pliter,pl)  dualfprintf(fail_file,"%ld %d %d inversions prnonrel[%d]=%21.15g prrel[%d]=%21.15g\n",nstep,steppart,ptrgeom->i,pl,prnonrel[pl],pl,prrel[pl]);
  //  if(flagifnonrel)  PLOOP(pliter,pl)  if(fabs(prnonrel[pl]-prrel[pl])>0.0) dualfprintf(fail_file,"%ld %d %d inversions prnonrel[%d]=%21.15g prrel[%d]=%21.15g diff=%21.15g\n",nstep,steppart,ptrgeom->i,pl,prnonrel[pl],pl,prrel[pl],prnonrel[pl]-prrel[pl]);
  if(flagifnonrel)  PLOOP(pliter,pl)  if(fabs(prnonrel[pl]-prrel[pl])/fabs(fabs(prnonrel[pl])+fabs(prrel[pl])+SMALL)>0.0) dualfprintf(fail_file,"%ld %d %d inversions prnonrel[%d]=%21.15g prrel[%d]=%21.15g diff=%21.15g\n",nstep,steppart,ptrgeom->i,pl,prnonrel[pl],pl,prrel[pl],prnonrel[pl]-prrel[pl]);
#endif

  // default is to use nonrel if was good solution
  if(flagifnonrel)  PLOOP(pliter,pl) pr[pl]=prnonrel[pl];
  else PLOOP(pliter,pl) pr[pl]=prrel[pl];

#elif(EOMTYPE==EOMFFDE)
  // v^i
  // don't overwrite rest
  pr[U1]=prrel[U1];
  pr[U2]=prrel[U2];
  pr[U3]=prrel[U3];
#endif


  if(whichcons==EVOLVEFULLENTROPY){
    // in case user wants internal energy from entropy evolution in pr[ENTROPY]
    pr[ENTROPY]=pr[UU];
  }



  //////////////////
  //
  // check if mnewt failed or got negative densities
  //
  //////////////////
  if(mnewtfailed){



    //    PLOOP(pliter,pl) dualfprintf(fail_file,"U_target[%d]=%21.15g\n",pl,U_target[pl]);



    // reset to initial pr since new pr is bad
    PLOOP(pliter,pl) pr[pl]=pr0[pl];

    // report failure
    *lpflag= UTOPRIMFAILCONV;

    // then old p should be new p, do nothing since initial guess must be final solution
    if(whethertoreport && debugfail>=1) dualfprintf(fail_file,"static solution at t=%21.15g step=%ld i=%d j=%d k=%d wtf=%d\n",t,realnstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,debugfail);

    // no need to continue unless want debug info, then pflag is messed up
    return(0); 
    // remove above return if want to get debug below
  }// otherwise got good solution
  else{
    // check densities for positivity
    if( ( (EOMTYPE==EOMGRMHD||EOMTYPE==EOMENTROPYGRMHD)||(EOMTYPE==EOMCOLDGRMHD))&&((pr[RHO]<0.0)||(pr[UU]<0.0))){
      // it doesn't seem reasonable to just "fix" negative densities since they could be arbitrarily negative and the other primitive variables depend on the negativity of the density which is unphysical.  So we fail if negative.  Could fail for a lower threshold on density than the floor to avoid those numbers as well.
      if((pr[RHO]<=0.)&&(pr[UU]>=0.)) *lpflag= UTOPRIMFAILRHONEG;
      if((pr[RHO]>=0.)&&(pr[UU]<=0.)) *lpflag= UTOPRIMFAILUNEG;
      if((pr[RHO]<=0.)&&(pr[UU]<=0.)) *lpflag= UTOPRIMFAILRHOUNEG;

      // mostly we hit pr[UU]<0, or maybe never pr[RHO]<0 and pr[UU]<0 alot
      if(debugfail>=2) dualfprintf(fail_file,"utoprim found negative density: t=%21.15g step=%ld i=%d j=%d k=%d %21.15g %21.15g\n",t,realnstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[RHO],pr[UU]);
      return(0);
    }
  }



  ////////////////////
  //
  // make sure solution is valid
  //
  ////////////////////
#if(WHICHVEL==VEL3)
  // this is just a check, fixup() will soon do both in step_ch.c

  // currently need to check this since last iteration may lead to bad pr
  if(jonchecks) fixup1zone(pr,ptrgeom,0); // actually this is done in a general fixup call soon after this point in step_ch.c
  // check and see if u^t is actually a good solution now we think we have the solution? or fix it if u^t is bad
  if(jonchecks) if(check_pr(pr,pr0,ptrgeom,0)>=1)
                  FAILSTATEMENT("utoprim.c:Utoprim()", "mnewt check:check_pr()", 1);
#endif



  ////////////////////
  //
  // determine entropy inversion if not doing full entropy evolution
  //
  ///////////////////

  if(whichcons==EVOLVESIMPLEENTROPY){
    // if evolvesimpleentropy, then just invert in utoprim() after mnewt succeeds
    if (get_state(pr, ptrgeom, &q) >= 1) FAILSTATEMENT("utoprim.c:utoprim()", "get_state()", 2);
    invertentropyflux_calc(ptrgeom,U_target[ENTROPY],0,&q,pr);// doesn't use pr[UU], but uses rest of updated primitives
    
  }// otherwise no entropy evolution or direct full entropy evolution




  /////////////////////////////
  //
  // debug stuff
  // don't fail anymore even if failed-static solution
  //
  /////////////////////////////
  if ((debugfail>=2)&&(mnewtfailed >= 1)) {

    //    faildebug1(numnormterms,whichcons,U_target,GLOBALMAC(EOSextraglobal,i,j,k),pr0,ptrgeom);
    faildebug2(numnormterms,whichcons,U_target,GLOBALMAC(EOSextraglobal,i,j,k),pr0,ptrgeom);

    if (fail(i,j,k,loc,FAIL_UTOPRIM_TEST) >= 1)
      return (1);

    
    if(!jonchecks){
      if (fail(i,j,k,loc,FAIL_UTOPRIM_TEST) >= 1)
        return (1);
    }
  }



  *pressure=pressure_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),pr[RHO],pr[UU]);



  ////////////////////
  //
  // otherwise just safely fail or succeed
  //
  ////////////////////
  *lpflag = UTOPRIMNOFAIL;
  return (0);


}
Пример #6
0
int bound_prim(int boundstage, FTYPE prim[][N2M][NPR])
{
  int i, j, k;
  struct of_geom geom,rgeom;
  FTYPE vcon[NDIM]; // coordinate basis vcon
#if(WHICHVEL==VEL3)
  int failreturn;
#endif
  int ri, rj; // reference i,j
  FTYPE prescale[NPR];


  // real boundary zones
  if((boundstage==STAGE0)||(boundstage==STAGEM1)){

    if (mycpupos[1] == 0) {
      if((BCtype[X1DN]==OUTFLOW)||(BCtype[X1DN]==FIXEDOUTFLOW)){
	/* inner r boundary condition: u, just copy */
	for (j = 0; j < N2; j++) {
#if(EXTRAP==0)
	  ri=0;
	  rj=j;
	  for(i=-1;i>=-N1BND;i--)	  PBOUNDLOOP	  prim[i][j][k] = prim[ri][rj][k];
#elif(EXTRAP==1)

	  ri=0;
	  rj=j;
	  for(i=-1;i>=-N1BND;i--){
	    for(k=RHO;k<=UU;k++){
	      prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    }
	    k=U1;	    // treat U1 as special
	    prim[i][j][k] = prim[ri][rj][k] * (1. - (i-ri)*dx[1]) ;
	    for(k=U2;k<=U3;k++){
	      prim[i][j][k] = prim[ri][rj][k] * (1. + (i-ri)*dx[1]) ;
	    }
	    k=B1; // treat B1 special
	    prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    for(k=B2;k<=B3;k++){
	      prim[i][j][k] = prim[ri][rj][k] * (1. + (i-ri)*dx[1]) ;
	    }
	  }
#elif(EXTRAP==2)
	  ri=0;
	  rj=j;
	  get_geometry(ri, rj, CENT, &rgeom);
	  rescale(1,1,prim[ri][rj],&rgeom,prescale);
	  for(i=-1;i>=-N1BND;i--){
	    // set guess
	    PBOUNDLOOP prim[i][j][k]=prim[ri][rj][k];
	    get_geometry(i, j, CENT, &geom);	    
	    rescale(-1,1,prim[i][j],&geom,prescale);
	  }
#endif
	  for(i=-1;i>=-N1BND;i--){
#if(WHICHVEL==VEL4)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_4vel(1,prim[i][j],&geom, 0) ;
#elif(WHICHVEL==VEL3)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_3vel(1,prim[i][j],&geom, 0) ;
	    // projection may not preserve u^t to be real and rho>rhoscal u>uuscal
#if(JONCHECKS)
	    if(jonchecks){
	      //fixup1zone(prim[i][j],&geom,0);
	      failreturn=check_pr(prim[i][j],prim[i][j],&geom,-3);
	      if(failreturn){
		dualfprintf(fail_file,"Bad boundary zone, couldn't fix: i=%d j=%d\n",startpos[1]+i,startpos[2]+j);
		if (fail(FAIL_BCFIX) >= 1) return (1);
	      }
	    }
#endif
#elif(WHICHVEL==VELREL4)
	    get_geometry(i,j,CENT,&geom) ;
	    inflow_check_rel4vel(1,prim[i][j],&geom,0) ;
	    if(limit_gamma(GAMMAMAX,prim[i][j],&geom,0)>=1)
	      FAILSTATEMENT("bounds.c:bound_prim()", "limit_gamma()", 1);
#endif	
	  }
	}
      }
      else if((BCtype[X1DN]==NSSURFACE)){
	// same as above but don't modify magnetid field
	// fix field
	// outflow v and densities 


	/* inner r boundary condition: u, just copy */
	for (j = 0; j < N2; j++) {
#if(EXTRAP==0)
	  ri=0;
	  rj=j;
	  for(i=-1;i>=-N1BND;i--){
	    for(k=RHO;k<=UU;k++)  prim[i][j][k] = prim[ri][rj][k];
	    vcon[RR]=0; // surface that completely dissipates normal direction momentum
	    vcon[TH]=0; // "" for this component
	    vcon[PH]=Omegastar; // surface rotates with angular frequency Omegastar to observer at infinity
	    get_geometry(i, j, CENT, &geom);
	    vcon2pr(WHICHVEL, vcon,&geom,prim[i][j]); // get in terms of primitive velocity

	    // outflow field, NS field completely reconnects through surface
	    for(k=B1;k<=B3;k++)  prim[i][j][k] = prim[ri][rj][k];
	  }
#elif(EXTRAP==1)

	  ri=0;
	  rj=j;
	  for(i=-1;i>=-N1BND;i--){
	    for(k=RHO;k<=UU;k++){
	      prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    }
	    // set  	    ucon[TT,etc.]
	    vcon[RR]=0; // surface that completely dissipates normal direction momentum
	    vcon[TH]=0; // "" for this component
	    vcon[PH]=Omegastar; // surface rotates with angular frequency Omegastar to observer at infinity
	    get_geometry(i, j, CENT, &geom);
	    vcon2pr(WHICHVEL,vcon,&geom,prim[i][j]); // get in terms of primitive velocity

	    // outflow field, NS field completely reconnects through surface
	    for(k=B1;k<=B3;k++){
	      prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    }

	  }
#elif(EXTRAP==2)
	  ri=0;
	  rj=j;
	  get_geometry(ri, rj, CENT, &rgeom);
	  rescale(1,1,prim[ri][rj],&rgeom,prescale);
	  for(i=-1;i>=-N1BND;i--){
	    // set guess
	    PBOUNDLOOP prim[i][j][k]=prim[ri][rj][k];
	    get_geometry(i, j, CENT, &geom);
	    rescale(-1,1,prim[i][j],&geom,prescale);
	  }
	  // now fix velocity
	  vcon[RR]=0; // surface that completely dissipates normal direction momentum
	  vcon[TH]=0; // "" for this component
	  vcon[PH]=Omegastar; // surface rotates with angular frequency Omegastar to observer at infinity
	  for(i=-1;i>=-N1BND;i--){
	    get_geometry(i, j, CENT, &geom);
	    vcon2pr(WHICHVEL,vcon,&geom,prim[i][j]); // get in terms of primitive velocity
	  }

#endif



	  for(i=-1;i>=-N1BND;i--){
#if(WHICHVEL==VEL4)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_4vel(1,prim[i][j],&geom, 0) ;
#elif(WHICHVEL==VEL3)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_3vel(1,prim[i][j],&geom, 0) ;
	    // projection may not preserve u^t to be real and rho>rhoscal u>uuscal
#if(JONCHECKS)
	    if(jonchecks){
	      //fixup1zone(prim[i][j],&geom,0);
	      failreturn=check_pr(prim[i][j],prim[i][j],&geom,-3);
	      if(failreturn){
		dualfprintf(fail_file,"Bad boundary zone, couldn't fix: i=%d j=%d\n",startpos[1]+i,startpos[2]+j);
		if (fail(FAIL_BCFIX) >= 1) return (1);
	      }
	    }
#endif
#elif(WHICHVEL==VELREL4)
	    get_geometry(i,j,CENT,&geom) ;
	    inflow_check_rel4vel(1,prim[i][j],&geom,0) ;
	    if(limit_gamma(GAMMAMAX,prim[i][j],&geom,0)>=1)
	      FAILSTATEMENT("bounds.c:bound_prim()", "limit_gamma()", 1);
#endif	
	  }
	}
      }

    }

    // outer r BC:
    if (mycpupos[1] == ncpux1 - 1) {
      if((BCtype[X1UP]==OUTFLOW)||(BCtype[X1UP]==FIXEDOUTFLOW)){
	/* outer r BC: outflow */
      
	for (j = 0; j < N2; j++) {
#if(EXTRAP==0)
	  ri=N1-1;
	  rj=j;
	  for(i=N1;i<=N1-1+N1BND;i++)	  PBOUNDLOOP prim[i][j][k] = prim[ri][rj][k];
#elif(EXTRAP==1)
	  ri=N1-1;
	  rj=j;
	  for(i=N1;i<=N1-1+N1BND;i++){
	    for(k=RHO;k<=UU;k++){
	      prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    }
	    k=U1; // treat U1 as special
	    prim[i][j][k] = prim[ri][rj][k] * (1. - 2*(i-ri)*dx[1]) ;
	    for(k=U2;k<=U3;k++){
	      prim[i][j][k] = prim[ri][rj][k] * (1. - (i-ri)*dx[1]) ;
	    }
	    k=B1; // treat B1 special
	    prim[i][j][k] = prim[ri][rj][k] * gdet[ri][rj][CENT]/gdet[i][j][CENT] ;
	    for(k=B2;k<=B3;k++){
	      prim[i][j][k] = prim[ri][rj][k] * (1. - (i-ri)*dx[1]) ;
	    }
	  }
#elif(EXTRAP==2)
	  ri=N1-1;
	  rj=j;
	  get_geometry(ri, rj, CENT, &rgeom);
	  rescale(1,1,prim[ri][rj],&rgeom,prescale);
	  for(i=N1;i<=N1-1+N1BND;i++){
	    // set guess
	    PBOUNDLOOP prim[i][j][k]=prim[ri][rj][k];
	    get_geometry(i, j, CENT, &geom);
	    rescale(-1,1,prim[i][j],&geom,prescale);
	  }
#endif

	  for(i=N1;i<=N1-1+N1BND;i++){
#if(WHICHVEL==VEL4)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_4vel(1,prim[i][j],&geom,0) ;
#elif(WHICHVEL==VEL3)
	    get_geometry(i, j, CENT, &geom);
	    inflow_check_3vel(1,prim[i][j],&geom,0) ;
	    // projection may not preserve u^t to be real and rho>rhoscal u>uuscal
#if(JONCHECKS)
	    if(jonchecks){
	      //fixup1zone(prim[i][j],&geom,0);
	      failreturn=check_pr(prim[i][j],prim[i][j],&geom,-3);
	      if(failreturn){
		dualfprintf(fail_file,"Bad boundary zone, couldn't fix: i=%d j=%d\n",startpos[1]+i,startpos[2]+j);
		if (fail(FAIL_BCFIX) >= 1) return (1);
	      }
	    }
#endif
#elif(WHICHVEL==VELREL4)
	    get_geometry(i,j,CENT,&geom) ;
	    inflow_check_rel4vel(1,prim[i][j],&geom,0) ;
	    if(limit_gamma(GAMMAMAX,prim[i][j],&geom, 0)>=1)
	      FAILSTATEMENT("bounds.c:bound_prim()", "limit_gamma()", 2);
#endif	
	  }
	}
      }
      /* if fixed BC: do nothing */
    }

    /* inner polar BC (preserves u^t rho and u) */
    if (mycpupos[2] == 0) {
      for (i = -N1BND; i <=N1-1+N1BND; i++){
	ri=i;
	rj=0;
	for(j=-N2BND;j<=-1;j++) PBOUNDLOOP  prim[i][j][k] = prim[ri][rj+(rj-j-1)][k];
      }
    }

    /* outer polar BC  (preserves u^t rho and u) */
    if (mycpupos[2] == ncpux2 - 1) {
       for (i = -N1BND; i <=N1-1+N1BND; i++){
	ri=i;
	rj=N2-1;
	for(j=N2;j<=N2-1+N2BND;j++) PBOUNDLOOP  prim[i][j][k] = prim[ri][rj+(rj-j+1)][k];
      }
    }
    /* make sure b and u are antisymmetric at the poles   (preserves u^t rho and u) */
    /* inner pole */
    if (mycpupos[2] == 0) {
      for (i = -N1BND; i <= N1-1+N1BND; i++) {
	for (j = -N2BND; j < 0; j++) {
	  if(POSDEFMETRIC==0){
	    // u^t must be symmetric across pole, which is functions of u2 and u3 as well as their squares and othe products.  u2 in KS happens to be independent of sign, but in general is could be for some other metric.
	    // for now, assume KS-like metric where u2 is antisymmetric and u^t dep only on u2^2, not u2
	    prim[i][j][U2] *= 1.;
	    prim[i][j][U3] *= 1.;
	    prim[i][j][B2] *= 1.;
	    prim[i][j][B3] *= 1.;
	  }
	  else{
	    prim[i][j][U2] *= -1.;
	    prim[i][j][U3] *= 1.;
	    prim[i][j][B2] *= -1.;
	    prim[i][j][B3] *= 1.;
	  }
	}
      }
    }
    /* outer pole */
    if (mycpupos[2] == ncpux2 - 1) {
      for (i = -N1BND; i <= N1-1+N1BND; i++) {
	for (j = N2; j <= N2-1+N2BND; j++) {
	  if(POSDEFMETRIC==0){
	    prim[i][j][U2] *= 1.;
	    prim[i][j][U3] *= 1.;
	    prim[i][j][B2] *= 1.;
	    prim[i][j][B3] *= 1.;
	  }
	  else{
	    prim[i][j][U2] *= -1.;
	    prim[i][j][U3] *= 1.;
	    prim[i][j][B2] *= -1.;
	    prim[i][j][B3] *= 1.;
	  }
	}
      }
    }

    // to help protect the pole from death blows to the computational grid
    // a sort of crushing regularization
#define POLEDEATH 1
    // causes problems with stability at just beyond pole
    // for field line plots, can just set B^\theta=0 along pole


    /* inner pole */
    if (mycpupos[2] == 0) {
      for (i = -N1BND; i <= N1-1+N1BND; i++) {
	for (j = -N2BND; j < 0+POLEDEATH; j++) {
	  if(POSDEFMETRIC==0){
	    // u^t must be symmetric across pole, which is functions of u2 and u3 as well as their squares and othe products.  u2 in KS happens to be independent of sign, but in general is could be for some other metric.
	    // for now, assume KS-like metric where u2 is antisymmetric and u^t dep only on u2^2, not u2
	    prim[i][j][U2] *= 0;
	    prim[i][j][B2] *= 0.;
	  }
	  else{
	    prim[i][j][U2] *= 0.;
	    prim[i][j][B2] *= 0.;
	  }
	}
      }
    }
    /* outer pole */
    if (mycpupos[2] == ncpux2 - 1) {
      for (i = -N1BND; i <= N1-1+N1BND; i++) {
	for (j = N2-POLEDEATH; j <= N2-1+N2BND; j++) {
	  if(POSDEFMETRIC==0){
	    prim[i][j][U2] *= 0.;
	    prim[i][j][B2] *= 0.;
	  }
	  else{
	    prim[i][j][U2] *= 0.;
	    prim[i][j][B2] *= 0.;
	  }
	}
      }
    }





  }// end if stage0 or stagem1

  if (USEMPI) bound_mpi(boundstage, prim);


  return (0);
}