Exemplo n.º 1
0
/*  FUNCTION:  Calculate a grid of Voigt profiles.                          */
int
calcprofiles(struct transit *tr){
  struct transithint *th = tr->ds.th; /* transithint struct                 */
  struct opacity *op=tr->ds.op;     /* Opacity struct                       */
  int i, j;                         /* for-loop indices                     */
  int nDop, nLor;                   /* Number of Doppler and Lorentz-widths */
  double Lmin, Lmax, Dmin, Dmax;    /* Minimum and maximum widths           */
  PREC_VOIGT ***profile;            /* Grid of Voigt profiles               */
  float timesalpha=tr->timesalpha;  /* Voigt wings width                    */
  struct timeval tv;  /* Time-keeping variables                             */
  double t0=0.0;

  /* Make logscale grid for the profile widths:                             */
  /* FINDME: Add check that these numbers make sense                        */
  nDop = op->nDop = th->nDop;
  nLor = op->nLor = th->nLor;
  Dmin = th->dmin;
  Dmax = th->dmax;
  Lmin = th->lmin;
  Lmax = th->lmax;
  op->aDop = logspace(Dmin, Dmax, nDop);
  op->aLor = logspace(Lmin, Lmax, nLor);

  /* Allocate array for the profile half-size:                              */
  op->profsize    = (PREC_NREC **)calloc(nDop,      sizeof(PREC_NREC *));
  op->profsize[0] = (PREC_NREC  *)calloc(nDop*nLor, sizeof(PREC_NREC));
  for (i=1; i<nDop; i++)
    op->profsize[i] = op->profsize[0] + i*nLor;

  /* Allocate grid of Voigt profiles:                                       */
  op->profile    = (PREC_VOIGT ***)calloc(nDop,      sizeof(PREC_VOIGT **));
  op->profile[0] = (PREC_VOIGT  **)calloc(nDop*nLor, sizeof(PREC_VOIGT *));
  for (i=1; i<nDop; i++){
    op->profile[i] = op->profile[0] + i*nLor;
  }
  profile = op->profile;
  tr_output(TOUT_RESULT, "Number of Voigt profiles: %d.\n", nDop*nLor);

  t0 = timestart(tv, "Begin Voigt profiles calculation.");
  /* Evaluate the profiles for the array of widths:                         */
  for   (i=0; i<nDop; i++){
    for (j=0; j<nLor; j++){
      /* Skip calculation if Doppler width << Lorentz width:                */
      /* Set size and pointer to previous profile:                          */
      if (op->aDop[i]*10.0 < op->aLor[j]  &&  i != 0){
        op->profsize[i][j] = op->profsize[i-1][j];
        profile[i][j] = profile[i-1][j];
      }
      else{ /* Calculate a new profile for given widths:                    */
        op->profsize[i][j] = getprofile(&profile[i][j],
                             tr->wns.d/tr->owns.o, op->aDop[i], op->aLor[j],
                             timesalpha, tr->owns.n);
      }
      tr_output(TOUT_DEBUG, "Profile[%2d][%2d] size = %4li  (D=%.3g, "
        "L=%.3g).\n", i, j, 2*op->profsize[i][j]+1, op->aDop[i], op->aLor[j]);
    }
  }
  t0 = timecheck(verblevel, 0, 0, "End Voigt-profile calculation.", tv, t0);
  return 0;
}
Exemplo n.º 2
0
//Scott Iwanicki
//runs when a shopper reaches a store
int Shopper::storecomplete(){
        int xpos = this->smove_->storelist_->xstore_;
        int ypos = this->smove_->storelist_->ystore_;
        int zpos = this->smove_->storelist_->zstore_;
        printf("Shopper %d arrives at store S(%d,%d) on the %d Floor at time %d\n", this->RobotNum_, xpos, ypos, (zpos + 1), TIME);
        //shopper enters round robin queue
        RRqueue* ptr = new RRqueue(this);
        //the shopper is processed at the round robin queue
        while(this->smove_->storelist_->TimeSlice_ != 0)
        {
                TIME+= (TimeSlice/10);
                ptr->RunQueue();
                timecheck();
        }
        //removes the store from the shopper's list of stores
        this->smove_->RemoveStore();
        return 0;
}
Exemplo n.º 3
0
void timestep(void) 
{
  FTYPE dtother;
  int i,j,k,l ;
  FTYPE idt2[NUMDTCHECKS+1];
  int ks[NUMDTCHECKS+1], js[NUMDTCHECKS+1], is[NUMDTCHECKS+1];
  FTYPE dt2inv_max[NUMDTCHECKS+1] ;
  int didfail,didfail_full;
  int bigger;
  FTYPE finaln;
  static int firsttime=1;
  static FTYPE ttimestep=0,ttimescale=0;
  static FTYPE dtlast;
  char tempc1[50];
  // for slow idtcreate change
  FTYPE bxa,bya,bza,dv,dvdx,delv;
  FTYPE l2_ten;
  FTYPE rho,u ;
  FTYPE odx1,odx2,odx3,ods,odl;
  FTYPE valphen,velfastm,valphen2,cs2 ;
  int reall,viscl,nonvl;
  FTYPE vel1,vel2,vel3;
  FTYPE ftemp;
  FTYPE dvx,dvy,dvz,ftemp1,ftemp2,ftemp3;
  static FTYPE dtrecv;
  int nstepmin,nstepmax;
  int gosub,gosup;
  FTYPE dt2invl[3];
  static FTYPE dtotherlowest;
  static int laststep;



  if(visc_real==1){
    nu_compute();
  }
  if(RESMEM&&(res_real==1)){
    if(rreal==2) current_compute(123);
    nu_res_compute();
  }

  for(l=2;l<=NUMDTCHECKS;l++){
    dt2inv_max[l]=0.;
    ks[l]=js[l]=is[l]=0;
  }
  dtlast = dt ;

  didfail=0;
  didfail_full=0;
  if(firsttime==1){
    ttimestep=t-1.E-12;
    ttimescale=t-1.E-12;
    laststep=0;
  }

  LOOPTIMESTEP{

#if(BOUNDTYPE==3)
    if(bzmask[k][j][i]!=0) continue;
#endif

#if(TS0CHECK)
    if(s[2][k][j][i] < 0) { // actually detects nan too
      sprintf(tempc1,"%3f",s[2][k][j][i]);
      if(tempc1[0]=='n'){
	fprintf(fail_file,"nan internal energy density error: k: %3d j: %3d i: %3d u: %15.10g \n",k,j,i,s[2][k][j][i]) ;
      }
      else if(s[2][k][j][i]<0) fprintf(fail_file,"negative internal energy density error: k: %3d j: %3d i: %3d en: %15.10g \n",k,j,i,s[2][k][j][i]) ;
      didfail=1;
    }
    if(s[1][k][j][i] < 0) {
      sprintf(tempc1,"%3f",s[1][k][j][i]);
      if(tempc1[0]=='n'){
	fprintf(fail_file,"nan mass density error: k: %3d j: %3d i: %3d rho: %15.10g \n",k,j,i,s[1][k][j][i]) ;
      }
      else if(s[1][k][j][i]<0) fprintf(fail_file,"negative mass density error: k: %3d j: %3d i: %3d rho: %15.10g \n",k,j,i,s[1][k][j][i]) ;
      didfail=1;
    }
#endif



    // not inlining this function for some reason, so slow in loop, so make .h file
    // idtcreate(idt2,k,j,i);
#include "timestep.h"

    for(l=2;l<=NUMDTCHECKS;l++){
      ftemp=idt2[l];
      if(ftemp > dt2inv_max[l]){
	dt2inv_max[l] = ftemp ;
	ks[l]=k;
	js[l]=j;
	is[l]=i;
      }
      if(CHECKDTLOW==1){
	if(ftemp>SQIDTLOWEST){
	  timecheck(-l,idt2,k,j,i,0);
	  didfail=1;
	  fflush(fail_file);
	}
      }
    }



  }// end loop over domain


  if(CHECKDTLOW==1){
    // check if any cpu has failure
    if(numprocs>1){
#if(USEMPI)
      MPI_Allreduce(&didfail, &didfail_full, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
#endif
    }
    else{
      didfail_full=didfail;
    }
    if(didfail_full){
      if(myid<=0){
	fprintf(log_file,"timestep failure\n");
      }
      if(DOGENDIAG){
	diag(2);
      }
      if(DOAVGDIAG){
	diagavg(2);
      }
#if(USEMPI)
      MPI_Barrier(MPI_COMM_WORLD); // allow to finish diags
#endif
      myexit(5);
    }
  }



  // find lowest constrainer on dt
  reall=2;
  for(l=3;l<=NUMDTCHECKS;l++){
    if(dt2inv_max[l]>dt2inv_max[reall]){
      reall=l;
    }
  }

  if(DODTDIAG){
    // do check up on dominates of timestep for each type
    if((t>ttimestep)||(dt<DTLOWEST)){ // per cpu pure dt data
      for(l=2;l<=NUMDTCHECKS;l++){
	timecheck(l,idt2,ks[l],js[l],is[l],reall);
      }
      fflush(logdt_file);
      
      ttimestep=t+DTtimestep;
    }
  }

  if(DOTSTEPDIAG){
    if(t>ttimescale){
      if(numprocs==1){
	timescale();
	// SUPERMARK -- need to fix timescale to be correct in new cpu setup
	ttimescale=t+DTtimescale;
      }
    }    
  }



  // find lowest constrainer on dt due to visc
  if(dt2inv_max[8]>dt2inv_max[9]){
    viscl=8;
  }
  else viscl=9;

  // find lowest constrainer on dt of non-viscosity type (next highest dt^2)
  nonvl=2;
  for(l=3;l<=NUMDTCHECKS;l++){
    if(l==8) l=10; // skip viscosity
    if(dt2inv_max[l]>dt2inv_max[nonvl]){
      nonvl=l;
    }
  }
  // communicate the lowest dt values to all cpus
  if(numprocs>1){
#if(USEMPI)
    MPI_Allreduce(&(dt2inv_max[reall]), &dt2invl[0], 1, MPI_FTYPE, MPI_MAX, MPI_COMM_WORLD);
    MPI_Allreduce(&(dt2inv_max[viscl]), &dt2invl[1], 1, MPI_FTYPE, MPI_MAX, MPI_COMM_WORLD);
    MPI_Allreduce(&(dt2inv_max[nonvl]), &dt2invl[2], 1, MPI_FTYPE, MPI_MAX, MPI_COMM_WORLD);
#endif
  }
  else{
    dt2invl[0]=dt2inv_max[reall];
    dt2invl[1]=dt2inv_max[viscl];
    dt2invl[2]=dt2inv_max[nonvl];
  }

  if(TRYSUBCYCLE){

    finaln=sqrt(dt2invl[1]/dt2invl[2]);  // fraction of other dt to viscosity dt
    
    if(subcyclen<=1){
      dtotherlowest=1.E+9; // used to check on subcycling below
      gosub=0; // assume by default won't be able to subcycle
      // if visc limits entire comp grid by factor of 2 in dt or more on other dts, then do subcycle
      if((!laststep)&&(finaln>=2.0) ){
	
	// check if stable enough to subcycle
	//      if(fabs( (dt2invl[1]-dtlast)/dtlast)<5.0){
	// so stable, now find next lowest dt
	
	dt=1.0/sqrt(dt2invl[1]); // dt to be used on viscosity
	// number of subcycles over viscosity allowed given current estimates of dt
	subcyclen=(int)(floor(finaln)); // floor to be conservative on fraction
	
	// check if subcycle possible
	if(subcyclen>=2){// should be true!
	  // setup subcycle
	  tscycleto=t+dt*(FTYPE)(subcyclen); // time to cycle to if stable cycle
	  tscyclefrom=t; // time starting subcycle
	  dtlastscycle=1.0/sqrt(dt2invl[2]); // need to make sure not cycling past newest other dts
	  nthsubcycle=1;  // first subcycle is now
	  gosub=1;
	}
	else{
	  fprintf(fail_file,"Unexpected failure in subcycle code: finaln: %15.10g subcyclen: %d\n",finaln,subcyclen);
	  myexit(1);
	}
	//}// end if stable to subcycle
      }// end if viscosity limit and want to try to subcycle on it
      if(gosub==0){ // if no subcycling possible
	dt=1.0/sqrt(dt2invl[0]); // normal case of no subcycling
	subcyclen=1;
	nthsubcycle=0;
      }
    }// endif not subcycling
    else{ // if currently subcycling
      gosup=0; // assume no need to supercycle yet
      nthsubcycle++;
      // check to see if done with subcycling or need to quit
      
      // check to see if visc no longer limit and so supercycle(do all but visc up to viscs time)
      if(finaln<=2.0){
	gosup=1;
      }
      else{// visc still limit
	dt=1.0/sqrt(dt2invl[0]); // trial dt assuming still going to subcycle(should be same as [1])
	dtother=1.0/sqrt(dt2invl[2]);
	if(dtother<dtotherlowest){
	  dtotherlowest=dtother;
	}
	// check if prospective timestep for viscosity still keeps other terms t0+dt further down t to avoid overstepping the other limits based on current data
	if( (t+dt)>(tscyclefrom+dtotherlowest) ){
	  gosup=1;
	}
      }
      if(gosup){ // general setup for supercycle
	dt=(t-tscyclefrom);
	subcyclen=-1;
	tscycleto=t;
	t=tscyclefrom;
      nthsubcycle=0;
      }
    }// endif was/still are subcycling
  }
  else{
    dt=1.0/sqrt(dt2invl[0]); // normal case of no subcycling
  }
  if(analoutput==6){
    // for checking visc code
    dt=pow(invcour2*alpha_real/(dx[2][1][0]*dx[2][1][0]),-1.0);
    ftemp=pow(invcour2*alpha_real/(x[2][1][0]*x[2][1][0]*dx[2][2][N2/2]*dx[2][2][N2/2]),-1.0);
    if(ftemp<dt) ftemp=dt;
  }
  

#if(USEMPI)
#if(DEBUGMPI>0)
      // first check if correct place in code(debug)
      MPI_Allreduce(&nstep, &nstepmin, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
      MPI_Allreduce(&nstep, &nstepmax, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
      if( (nstep!=nstepmin)||(nstep!=nstepmax)){
	fprintf(fail_file,"out of synch!\n");
	fprintf(fail_file,"proc: %d dt nstep: %d\n",myid,nstep);
	fflush(fail_file);
      }      
#endif

      // don't need anymore
      //  MPI_Allreduce(&dt, &dtrecv, 1, MPI_FTYPE, MPI_MIN, MPI_COMM_WORLD);
  //MPI_Barrier(MPI_COMM_WORLD);
      //dt=dtrecv;
#endif

  // because first time step is bad if e.g. viscosity on and no v at first
  if(firsttime==1){ // tweak for given problem so starts out good
    if(dt>1.E-5) dt=1.E-5;
    firsttime=0;
  }


  // don't increase timestep by too much on subcycle or normal cycle.
  // don't check if supercycle since need to force non-visc back to visc time.
  if(subcyclen>=0){
    if(dt > 1.3*dtlast) dt = 1.3*dtlast ;
  }

  /* don't step beyond end of run */
  if(t + dt >= tf){
    // last timestep
    laststep=1;
    if(subcyclen==1){
      dt = tf - t ;
      reallaststep=1;
    }
    if(subcyclen==-1){
      fprintf(fail_file,"shouldn't be here at end of run at super cycle\n");
      myexit(1);
    }
    if(subcyclen>=2){
      // just end subcycle and let next timestep() figure final dt, never subcycling again
      dt=(t-tscyclefrom);    
      subcyclen=-1;
      tscycleto=t;
      t=tscyclefrom;
      nthsubcycle=0;
      reallaststep=0;
    }
    // make sure don't get pathological case of dt=0 on last step
    if(dt<SSMALL){
      reallaststep=1;
      laststep=1;
      dt=SSMALL;
    }
  }
}
Exemplo n.º 4
0
void timestep(void)
{
  FTYPE dtother;
  int i, j, k, l;
  FTYPE idt2[NUMDTCHECKS + 1];
  int ks[NUMDTCHECKS + 1], js[NUMDTCHECKS + 1], is[NUMDTCHECKS + 1];
  FTYPE dt2inv_max[NUMDTCHECKS + 1];
  int didfail, didfail_full;
  FTYPE finaln;
  static int firsttime = 1;
  static FTYPE ttimestep = 0;
  static FTYPE dtlast;
  // for slow idtcreate change
  FTYPE bxa, bya, dv;
  FTYPE rho, u;
  FTYPE odx1, odx2, ods, odl;
  FTYPE valphen, valphen2, cs2;
  int reall, viscl, nonvl;
  FTYPE ftemp;
  FTYPE vel1, vel2;
  int gosub, gosup;
  FTYPE dt2invl[3];
  static FTYPE dtotherlowest;
  static int laststep;



  if (visc_real == 1) {
    nu_compute();
  }


  for (l = 2; l <= NUMDTCHECKS; l++) {
    dt2inv_max[l] = 0.;
    ks[l] = js[l] = is[l] = 0;
  }
  dtlast = dt;

  didfail = 0;
  didfail_full = 0;
  if (firsttime == 1) {
    ttimestep = t - 1.E-12;
    laststep = 0;
  }

  LOOP {
#if(TS0CHECK)
    if (s[2][k][j][i] < 0) {	// actually detects nan too
      sprintf(tempc1, "%3f", s[2][k][j][i]);
      if (tempc1[0] == 'n') {
	fprintf(fail_file,
		"nan internal energy density error: k: %3d j: %3d i: %3d u: %15.10g \n",
		k, j, i, s[2][k][j][i]);
      } else if (s[2][k][j][i] < 0)
	fprintf(fail_file,
		"negative internal energy density error: k: %3d j: %3d i: %3d en: %15.10g \n",
		k, j, i, s[2][k][j][i]);
      didfail = 1;
    }
    if (s[1][k][j][i] < 0) {
      sprintf(tempc1, "%3f", s[1][k][j][i]);
      if (tempc1[0] == 'n') {
	fprintf(fail_file,
		"nan mass density error: k: %3d j: %3d i: %3d rho: %15.10g \n",
		k, j, i, s[1][k][j][i]);
      } else if (s[1][k][j][i] < 0)
	fprintf(fail_file,
		"negative mass density error: k: %3d j: %3d i: %3d rho: %15.10g \n",
		k, j, i, s[1][k][j][i]);
      didfail = 1;
    }
#endif



    // not inlining this function for some reason, so slow in loop, 
#include "timestep1.h"

    for (l = 2; l <= NUMDTCHECKS; l++) {
      ftemp = idt2[l];
      if (ftemp > dt2inv_max[l]) {
	dt2inv_max[l] = ftemp;
	ks[l] = k;
	js[l] = j;
	is[l] = i;
      }
#if(CHECKDTLOW==1)
      if (ftemp > SQIDTLOWEST) {
	timecheck(-l, idt2, k, j, i, 0);
	didfail = 1;
	fflush(fail_file);
      }
#endif
    }



  }				// end loop over domain


#if(CHECKDTLOW==1)
  // check if any cpu has failure
  if (numprocs > 1) {
  } else {
    didfail_full = didfail;
  }
  if (didfail_full) {
    if (myid <= 0) {
      fprintf(log_file, "timestep failure\n");
    }
    if (DOGENDIAG) {
      diag(2);
    }
    myexit(5);
  }
#endif



  // find lowest constrainer on dt
  reall = 2;
  for (l = 3; l <= NUMDTCHECKS; l++) {
    if (dt2inv_max[l] > dt2inv_max[reall]) {
      reall = l;
    }
  }

#if(DODTDIAG)
  // do check up on dominates of timestep for each type
  if (t > ttimestep) {		// per cpu pure dt data
    for (l = 2; l <= NUMDTCHECKS; l++) {
      timecheck(l, idt2, ks[l], js[l], is[l], reall);
    }
    fflush(logdt_file);
  }
#endif

#if(DOTSTEPDIAG)
  if (t > ttimestep) {
    // output timescales (create own DTtimescale later)
    timescale();
  }
#endif

#if((DODTDIAG)||(DOTSTEPDIAG))
  ttimestep = t + DTtimestep;
#endif


  // find lowest constrainer on dt due to visc
  if (dt2inv_max[8] > dt2inv_max[9]) {
    viscl = 8;
  } else
    viscl = 9;

  // find lowest constrainer on dt of non-viscosity type (next
  // highest
  // dt^2)
  nonvl = 2;
  for (l = 3; l <= NUMDTCHECKS; l++) {
    if (l == 8)
      l = 10;			// skip viscosity
    if (dt2inv_max[l] > dt2inv_max[nonvl]) {
      nonvl = l;
    }
  }
  // communicate the lowest dt values to all cpus
  if (numprocs > 1) {
  } else {
    dt2invl[0] = dt2inv_max[reall];
    dt2invl[1] = dt2inv_max[viscl];
    dt2invl[2] = dt2inv_max[nonvl];
  }
  
  dt = 1.0 / sqrt(dt2invl[0]);	// normal case of no subcycling

  if (analoutput == 6) {
    // for checking visc code
    dt = pow(invcour2 * alpha_real / (dx[2][1][0] * dx[2][1][0]), -1.0);
    ftemp =
	pow(invcour2 * alpha_real /
	    (x[2][1][0] * x[2][1][0] * dx[2][2][N2 / 2] *
	     dx[2][2][N2 / 2]), -1.0);
    if (ftemp < dt)
      ftemp = dt;
  }
  // because first time step is bad if e.g. viscosity on and no v at
  // first
  if (firsttime == 1) {		// tweak for given problem so starts
    // out
    // good
    if (dt > 1.E-5)
      dt = 1.E-5;
    firsttime = 0;
  }
  // don't increase timestep by too much on subcycle or normal cycle.
  // don't check if supercycle since need to force non-visc back to
  // visc 
  // time.
  if (subcyclen >= 0) {
    if (dt > 1.3 * dtlast)
      dt = 1.3 * dtlast;
  }

  /* don't step beyond end of run */
  if (t + dt >= tf) {
    // last timestep
    laststep = 1;
    if (subcyclen == 1) {
      dt = tf - t;
      reallaststep = 1;
    }
    if (subcyclen == -1) {
      fprintf(fail_file,
	      "shouldn't be here at end of run at super cycle\n");
      myexit(1);
    }
    if (subcyclen >= 2) {
      // just end subcycle and let next timestep() figure final
      // dt,
      // never subcycling again
      dt = (t - tscyclefrom);
      subcyclen = -1;
      tscycleto = t;
      t = tscyclefrom;
      nthsubcycle = 0;
      reallaststep = 0;
    }
    // make sure don't get pathological case of dt=0 on last step
    if (dt < SSMALL) {
      reallaststep = 1;
      laststep = 1;
      dt = SSMALL;
    }
  }
}
Exemplo n.º 5
0
nkconf_t *get_nkconfig(char *key, int flags, char **resultkey)
{
	static RbtHandle handle;
	static char *realkey = NULL;
	void *k1, *k2;
	nkconf_t *result = NULL;
	int isclone;

	if (resultkey) *resultkey = NULL;

	switch (flags) {
	  case NKCONF_TIMEFILTER:
		handle = findrec(key);
		/* We may have hit a cloned record, so use the real key for further searches */
		if (handle != rbtEnd(rbconf)) {
			rbtKeyValue(rbconf, handle, &k1, &k2);
			realkey = k1;
		}

		while (handle != rbtEnd(rbconf)) {
			rbtKeyValue(rbconf, handle, &k1, &k2);
			result = (nkconf_t *)k2;
			if (timecheck(result->starttime, result->endtime, result->nktime)) return result;

			/* Go to the next */
			handle = rbtNext(rbconf, handle);
			if (handle != rbtEnd(rbconf)) {
				rbtKeyValue(rbconf, handle, &k1, &k2);
				if (strncmp(realkey, ((nkconf_t *)k2)->key, strlen(realkey)) != 0) handle=rbtEnd(rbconf);
			}
		}
		realkey = NULL;
		break;

	  case NKCONF_FIRSTMATCH:
		handle = findrec(key);
		realkey = NULL;
		if (handle != rbtEnd(rbconf)) {
			rbtKeyValue(rbconf, handle, &k1, &k2);
			realkey = (char *)k1;
		}
		break;

	  case NKCONF_FIRST:
		realkey = NULL;
		handle = rbtBegin(rbconf);
		if (handle == rbtEnd(rbconf)) return NULL;
		do {
			rbtKeyValue(rbconf, handle, &k1, &k2);
			realkey = (char *)k1;
			isclone = (*(realkey + strlen(realkey) - 1) == '=');
			if (isclone) handle = rbtNext(rbconf, handle);
		} while (isclone && (handle != rbtEnd(rbconf)));
		break;


	  case NKCONF_NEXT:
		if (!realkey || (handle == rbtEnd(rbconf))) return NULL;
		isclone = 1;
		while (isclone && (handle != rbtEnd(rbconf))) {
			handle = rbtNext(rbconf, handle);
			if (handle) {
				rbtKeyValue(rbconf, handle, &k1, &k2);
				realkey = (char *)k1;
				isclone = (*(realkey + strlen(realkey) - 1) == '=');
			}
		}
		break;

	  case NKCONF_RAW_FIRST:
		handle = rbtBegin(rbconf);
		realkey = NULL;
		break;

	  case NKCONF_RAW_NEXT:
		handle = rbtNext(rbconf, handle);
		realkey = NULL;
		break;

	  case NKCONF_FIRSTHOSTMATCH:
		do {
			int found = 0;
			char *delim;

			realkey = NULL;
			handle = rbtBegin(rbconf);
			while (!found && (handle != rbtEnd(rbconf))) {
				rbtKeyValue(rbconf, handle, &k1, &k2);
				realkey = (char *)k1;
				delim = realkey + strlen(key); /* OK even if past end of realkey */
				found = ((strncmp(realkey, key, strlen(key)) == 0) &&
					((*delim == '|') || (*delim == '=')));
				if (!found) { handle = rbtNext(rbconf, handle); realkey = NULL; }
			}

			if ((handle != rbtEnd(rbconf)) && (*(realkey + strlen(realkey) - 1) == '=')) {
				key = (char *)k2;
				isclone = 1;
			}
			else isclone = 0;

		} while (isclone && (handle != rbtEnd(rbconf)));
		break;
	}

	if (handle == rbtEnd(rbconf)) { realkey = NULL; return NULL; }

	rbtKeyValue(rbconf, handle, &k1, &k2);
	if (resultkey) *resultkey = (char *)k1;
	result = (nkconf_t *)k2;

	return result;
}