コード例 #1
0
void ElasticityResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  typedef Intrepid::FunctionSpaceTools FST;

    for (std::size_t cell=0; cell < workset.numCells; ++cell) {
      for (std::size_t node=0; node < numNodes; ++node) {
              for (std::size_t dim=0; dim<numDims; dim++)  ExResidual(cell,node,dim)=0.0;
          for (std::size_t qp=0; qp < numQPs; ++qp) {
            for (std::size_t i=0; i<numDims; i++) {
              for (std::size_t dim=0; dim<numDims; dim++) {
                ExResidual(cell,node,i) += Stress(cell, qp, i, dim) * wGradBF(cell, node, qp, dim);
    } } } } }


  if (workset.transientTerms && enableTransient)
    for (std::size_t cell=0; cell < workset.numCells; ++cell) {
      for (std::size_t node=0; node < numNodes; ++node) {
          for (std::size_t qp=0; qp < numQPs; ++qp) {
            for (std::size_t i=0; i<numDims; i++) {
                ExResidual(cell,node,i) += uDotDot(cell, qp, i) * wBF(cell, node, qp);
    } } } }


//  FST::integrate<ScalarT>(ExResidual, Stress, wGradBF, Intrepid::COMP_CPP, false); // "false" overwrites

}
コード例 #2
0
ファイル: arena.c プロジェクト: AbrahamJewowich/FreeSWITCH
PRIntn main(PRIntn argc, char *argv[])
{
    PLOptStatus os;
	PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    {
		if (PL_OPT_BAD == os) continue;
        switch (opt->option)
        {
        case 'a':  /* arena Min size */
            arenaMin = atol( opt->value );
            break;
        case 'A':  /* arena Max size  */
            arenaMax = atol( opt->value );
            break;
        case 'p':  /* pool Min size */
            poolMin = atol( opt->value );
            break;
        case 'P':  /* pool Max size */
            poolMax = atol( opt->value );
            break;
        case 'i':  /* Iterations in stress tests */
            stressIterations = atol( opt->value );
            break;
        case 's':  /* storage to get per iteration */
            maxAlloc = atol( opt->value );
            break;
        case 't':  /* Number of stress threads to create */
            stressThreads = atol( opt->value );
            break;
        case 'd':  /* debug mode */
			debug_mode = 1;
            break;
        case 'h':  /* help */
        default:
            Help();
        } /* end switch() */
    } /* end while() */
	PL_DestroyOptState(opt);

    srand( (unsigned)time( NULL ) ); /* seed random number generator */
    tLM = PR_NewLogModule("testcase");


#if 0
	ArenaAllocate();
	ArenaGrow();
#endif

    MarkAndRelease();

    Stress();

    return(EvaluateResults());
} /* end main() */
コード例 #3
0
ファイル: defect.cpp プロジェクト: adhishm/dd2d_Matryoshka
/**
 * @brief Returns the total stress at the iteration i.
 * @details The total stress at the iteration i is returned. If an invalid value of i is provided, a zero stress tensor is returned.
 * @param i Iteration number for which the total stress is to be returned.
 * @return Total stress at iteration i.
 */
Stress Defect::getTotalStressAtIteration (int i) const
{
    if (i < this->totalStresses.size())
    {
        // If the iteration number provided is valid
        return (this->totalStresses[i]);
    }
    else
    {
        // Invalid iteration number - return zeros
        return (Stress());
    }
}
コード例 #4
0
ファイル: ObjAllocMain.cpp プロジェクト: gamezatwork/personal
void __fastcall TfrmObjAllocMain::btnStressClick(TObject *Sender)
{
	if (FIsProcessing)
	{
		FIsProcessing = false;
		return;
	}

	FIsProcessing = true;
	btnStress->Caption = "Stop";
	Screen->Cursor = crAppStart;
		Stress();
	btnStress->Caption = "Stress";
	Screen->Cursor = crDefault;
	FIsProcessing = false;
}
コード例 #5
0
// ------------------------------------------------------------------
// main
// ------------------------------------------------------------------
int main(int argc, char **argv) {

  // Banner.
  puts("StressShared (v. " VERSION ") by gynvael.coldwind//vx");
  
  // Args?
  if((argc != 2 && argc != 3) || 
     strcmp(argv[1], "-h") == 0 ||
     strcmp(argv[1], "--help") == 0 ||
     strcmp(argv[1], "/?") == 0) {
    Usage();
    return 1;
  }

  if(argc == 3) {
    if(strcmp(argv[2], "--hard") == 0) {
      Option_Hard = true;
    } else {
      Usage();
      return 2;
    }
  }

  // Load module.
  HMODULE h = LoadLibrary(argv[1]);
  if(h == NULL) {
    fprintf(stderr, "error: failed to load DLL\n");
    return 2;
  }

  // Let's start the stress.
  Stress(h);

  // The execution should normally never reach this.
  FreeLibrary(h);

  // Done.
  return 0;
}
コード例 #6
0
ファイル: main.C プロジェクト: gberan/HMBI
/*
HMBI code.  Invoke as:
      hmbi <input file> [# of processors]

The number of processors is optional, and the default is 1.  To run
in code in parallel, the source code must be compiled with -DPARALLEL,
and MPI is required.

*/
main(int argc, char ** argv) {
  
  if (argc < 2) {
    printf("HMBI syntax:: hmbi <input file> [ # of processors (optional)]\n");
    exit(1);
  }
  
  int nproc = 1;
  if (argc > 2) {
    string tmp = argv[2];
    nproc = atoi(tmp.c_str());
  }

#ifdef PARALLEL
  int mynode=0,totalnodes;

  if (nproc > 1) {
    MPI_Init(&argc, &argv);
    MPI_Comm io_comm;
    
    MPI_File *fh, *fg;      
    MPI_Info info;       

    MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes
    MPI_Comm_rank(MPI_COMM_WORLD, &mynode);     // get mynode
    if (mynode==0) 
      printf("Running MPI parallel version with %d processors\n",nproc);

  }

  if (mynode == 0) {  
#endif /* PARALLEL */

    // Set the number of processors
    Params::Parameters().SetNumberOfProcessors(nproc);

    // Store the primary process ID of the job.  Used to create unique
    // scratch files
    int pid = getpid();
    Params::Parameters().SetPID(pid);

    // Start wall clock timer
    time_t start_time, stop_time;
    start_time = time(NULL);
     
    // Open input file
    const int maxlength = 50;
    char filename[maxlength];
    strcpy(filename, argv[1]);

    ifstream infile;
    infile.open(filename);
    assert(infile.is_open()); 
    
    // Initialize Cluster object
    Cluster::cluster().Initialize(infile,nproc);
    printf("Cluster initialization complete\n");

    if (! Params::Parameters().DoForces())
      Params::Parameters().SetUseDLFind(false);

    // Compute the Energy (and forces, if requested)
    if (!Params::Parameters().UseDLFind()) {
      Cluster::cluster().RunJobsAndComputeEnergy();
    }

    if ( Params::Parameters().PrintLevel() > 0)
      Cluster::cluster().ComputeDistanceMatrix();

    // For debugging: Compute finite difference stress tensor
    bool do_finite_difference_stress_tensor = false;
    if (do_finite_difference_stress_tensor) {
      double delta = 0.001; // step size, in Angstroms

      Vector a1(3), a2(3), a3(3); // original unit cell vectors
      Vector new_a1(3),new_a2(3), new_a3(3); // deformed unit cell vectors
      Matrix Strain(3,3), Stress(3,3); 
      Stress.Set();
      
      // Grab original unit cell vectors
      a1 = Cluster::cluster().GetUnitCellVector(0);
      a2 = Cluster::cluster().GetUnitCellVector(1);
      a3 = Cluster::cluster().GetUnitCellVector(2);
      printf("Original lattice vectors (Ang):\n");
      printf("a1 = (%f, %f, %f)\n",a1[0],a1[1],a1[2]);
      printf("a2 = (%f, %f, %f)\n",a2[0],a2[1],a2[2]);
      printf("a3 = (%f, %f, %f)\n",a3[0],a3[1],a3[2]);

      // Get cell volume, convert to Bohr^3
      double V = Cluster::cluster().GetCellvolume() * AngToBohr * AngToBohr * AngToBohr;

      // Get the atomic coords.  We use these when triggering the
      // reset of the dimer images, even though we don't change the atomic
      // positions at all.
      Vector Coords = Cluster::cluster().GetCurrentCoordinates();

	// Loop over elements of the strain tensor e_ij
	for (int i=0;i<3;i++) {
	  for (int j=0;j<3;j++) {

	    // Set one element of the strain tensor to +delta
	    printf("Setting Strain(%d,%d) to +%f\n",i,j,delta);
	    Strain.Set(); new_a1.Set(); new_a2.Set(); new_a3.Set();
	    Strain(i,j) = delta;
	    Strain.Print("Strain tensor");
	    
	    // Deform the lattice vectors: new_ai = ai + Strain * ai
	    new_a1 = Strain.MatrixTimesVector(a1);
	    new_a1 += a1;
	    new_a2 = Strain.MatrixTimesVector(a2);
	    new_a2 += a2;
	    new_a3 = Strain.MatrixTimesVector(a3);
	    new_a3 += a3;
	    
	    printf("Updated lattice vectors (Ang):\n");
	    printf("a1 = (%f, %f, %f)\n",new_a1[0],new_a1[1],new_a1[2]);
	    printf("a2 = (%f, %f, %f)\n",new_a2[0],new_a2[1],new_a2[2]);
	    printf("a3 = (%f, %f, %f)\n",new_a3[0],new_a3[1],new_a3[2]);

	    // Set the new lattice vectors and get the energy
	    Cluster::cluster().SetUnitCellVectors(new_a1, new_a2, new_a3);
	    Cluster::cluster().SetNewCoordinates(Coords);
	    Cluster::cluster().RunJobsAndComputeEnergy();
	    double E1 = Cluster::cluster().GetHMBIEnergy();

	    // Repeat for strain tensor element -delta
	    printf("Setting Strain(%d,%d) to -%f\n",i,j,delta);
	    Strain.Set(); new_a1.Set(); new_a2.Set(); new_a3.Set();
	    Strain(i,j) = -delta;
	    Strain.Print("Strain tensor");
	    
	    // Deform the lattice vectors: new_ai = ai + Strain * ai
	    new_a1 = Strain.MatrixTimesVector(a1);
	    new_a1 += a1;
	    new_a2 = Strain.MatrixTimesVector(a2);
	    new_a2 += a2;
	    new_a3 = Strain.MatrixTimesVector(a3);
	    new_a3 += a3;
	    
	    printf("Updated lattice vectors (Ang):\n");
	    printf("a1 = (%f, %f, %f)\n",new_a1[0],new_a1[1],new_a1[2]);
	    printf("a2 = (%f, %f, %f)\n",new_a2[0],new_a2[1],new_a2[2]);
	    printf("a3 = (%f, %f, %f)\n",new_a3[0],new_a3[1],new_a3[2]);

	    // Set the new lattice vectors and get the energy
	    Cluster::cluster().SetUnitCellVectors(new_a1, new_a2, new_a3);
	    Cluster::cluster().SetNewCoordinates(Coords);
	    Cluster::cluster().RunJobsAndComputeEnergy();
	    double E2 = Cluster::cluster().GetHMBIEnergy();

	    // Final Stress tensor element stress(i,j) = 1/V dE/dstrain(i,j)
	    Stress(i,j) = (1.0/V)*(E1 - E2)/(2*delta);
	  }
	}

	printf("Finite Difference Stress Tensor:\n");
	for (int i=0;i<3;i++) {
	  printf("%15.9f  %15.9f  %15.9f\n",Stress(i,0), Stress(i,1), Stress(i,2));
	}
    }



  
    // For debugging: Compute finite difference gradients
    bool do_finite_difference_grad = Params::Parameters().UseFiniteDifferenceGradients();
    if (do_finite_difference_grad && Params::Parameters().DoForces()) {

      Vector Grad = Cluster::cluster().GetHMBIGradient();
      Grad.Print("Analytical HMBI Gradient");
      int Natoms = Cluster::cluster().GetTotalNumberOfAtoms();
      Vector Eplus(3*Natoms), Eminus(3*Natoms);
      Vector Original_coords = Cluster::cluster().GetCurrentCoordinates();

      Vector LatticeGradient(6);
      LatticeGradient.Set();

      // Do the finite difference
      double delta = 0.001; // step size, in Angstroms
      /*
      for (int i=0;i<3*Natoms;i++) {

	printf("Shifting coord %d by -%f\n",i,delta);
	Vector Coords = Original_coords;
	Coords[i] -= delta;
	// Update the coordinates & get the energy
	Cluster::cluster().SetNewCoordinates(Coords);
	Cluster::cluster().RunJobsAndComputeEnergy();
	Eplus[i] = Cluster::cluster().GetHMBIEnergy();

	printf("Shifting coord %d by +%f\n",i,delta);
	Coords[i] += 2.0*delta;
	// Update the coordinates & get the energy
	Cluster::cluster().SetNewCoordinates(Coords);
	Cluster::cluster().RunJobsAndComputeEnergy();
	Eminus[i] = Cluster::cluster().GetHMBIEnergy();
      
      }
      */
      // Now do finite difference over the lattice parameters, if appropriate
      double deltaTheta = 0.01;
      if (Params::Parameters().IsPeriodic() ) {
	string *params;
	params = new string[6];
	params[0] = "a"; params[1] = "b"; params[2] = "c";
	params[3] = "alpha", params[4] = "beta"; params[5] = "gamma";

	Vector Coords = Original_coords; // we need these to trigger the reset of the
	// dimer images, even if we don't change the atomic positions at all.

	for (int i=0;i<6;i++) {
	  double current = Cluster::cluster().GetUnitCellParameter(params[i]);
	  double new1,new2;
	  if (i < 3) {
	    printf("Shifting coord %s by -%f\n",params[i].c_str(),delta);
	    new1 = current - delta;
	  }
	  else {
	    printf("Shifting coord %s by -%f\n",params[i].c_str(),deltaTheta);
	    new1 = current - deltaTheta;
	  }
	  Cluster::cluster().SetUnitCellParameter(params[i],new1);
	  Cluster::cluster().SetNewCoordinates(Coords);
	  Cluster::cluster().RunJobsAndComputeEnergy();
	  double E1 = Cluster::cluster().GetHMBIEnergy();

	  if (i < 3) {
	    printf("Shifting coord %s by +%f\n",params[i].c_str(),delta);
	    new2 = current + delta;
	  }
	  else {
	    printf("Shifting coord %s by +%f\n",params[i].c_str(),deltaTheta);
	    new2 = current + deltaTheta;
	  }
	  // Update the coordinates & get the energy
	  Cluster::cluster().SetUnitCellParameter(params[i],new2);
	  Cluster::cluster().SetNewCoordinates(Coords);
	  Cluster::cluster().RunJobsAndComputeEnergy();
	  double E2 = Cluster::cluster().GetHMBIEnergy();

	  if (i < 3) {
	    LatticeGradient[i] = (E2 - E1) / ((new2 - new1)*AngToBohr);
	  }
	  else{
	    LatticeGradient[i] = (E2 - E1) / ((new2 - new1)*DegreesToRadians);
	  }

	  // Reset the lattice parameter to its original value
	  Cluster::cluster().SetUnitCellParameter(params[i],current);

	}

      }

      // Form the actual gradient, G = (Eminus - Eplus)/(2*delta)
      Grad.Set();
      Grad = Eminus;
      Grad -= Eplus;
      Grad.Scale(1.0/(2*delta*AngToBohr));

      Grad.Print("Finite Difference HMBI Gradient");

      LatticeGradient.Print("Finite Difference Lattice Parameter Gradient");

      printf("*** Finished with finite difference.");
      exit(1);
    }
    // End finite difference debug code

    
    // Optimize geometry, if requested
    if ( Params::Parameters().DoForces() ) {
      if (Params::Parameters().UseDLFind()) {
	// Use DL-FIND for geometry optimization
	int Natoms = Cluster::cluster().GetTotalNumberOfAtoms();
	int nvarin = 3*Natoms;
	int nvarin2 = 5*Natoms;// nframe*nat*3 + nweight + nmass + n_po_scaling
	int nspec = 2*Natoms; // nspec= nat + nz + 5*ncons + 2*nconn
	int master = 1; // work is done on the master node
	printf("Using DL-FIND for optimization\n");
	dl_find_(&nvarin, &nvarin2, &nspec, &master);

	// Final energy printing doesn't work, because final
	//dlf_put_coords erases energies...  
	double energy =	Cluster::cluster().GetHMBIEnergy();
	printf("HMBI Final Energy = %15.9f\n",energy);

	printf("\n");
	Cluster::cluster().ComputeDistanceMatrix();

	// Save a copy of the new geometry in a new input file.
	FILE *input;
	string input_file = "new_geom.in";
	if ((input = fopen(input_file.c_str(),"w"))==NULL) {
	  printf("OptimizeGeometry() : Cannot open file '%s'\n",input_file.c_str());
	  exit(1);
	}
	
	Cluster::cluster().PrintInputFile(input);
	printf("\nNew input file written to '%s'\n",input_file.c_str());
	fclose(input);

      }
      else{
	
	string type = "SteepestDescent";
	//string type = "ConjugateGradients";
	OptimizeGeometry(type );
      }
    }



    if ( Params::Parameters().GetJobTypeStr() == "hessian" ) {
      printf("Computing finite difference Hessian\n");  fflush(stdout);
      Vector Original_coords = Cluster::cluster().GetCurrentCoordinates();
      int imon = Params::Parameters().GetFrequencyForMonomer();
      printf("Computing the vibrational frequencies for Monomer %d\n",imon);
      Matrix Hessian = GetFiniteDifferenceHessian(Original_coords,imon);

      Cluster::cluster().ComputeHarmonicFrequencies(Hessian);

	

    }
    
    infile.close();

    
    if (Params::Parameters().CheckWarnings() > 0) {
      printf("\nHMBI job completed, but with %d warning(s).\n",Params::Parameters().CheckWarnings());
    }
    else {
      printf("\nHMBI job succesful!!!\n");
    } 

#ifdef PARALLEL    
    // Tell all nodes to shut down
    if (nproc > 1) {
      MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes
      for (int rank = 1; rank < totalnodes; rank++) {
	MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD);
      }
    }
#endif /* PARALLEL */

    // Stop the timer and print out the time
    stop_time = time(NULL);
    double elapsed_time = difftime(stop_time,start_time);
    printf("Total job wall time = %.0f seconds\n",elapsed_time);

#ifdef PARALLEL
  }
  
  else {
    /* Slave node controller: just accept & run the jobs */

    int MPI_PrintLevel = 0;

    MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes
    MPI_Comm_rank(MPI_COMM_WORLD, &mynode);     // get mynode      

    while (1) {
      char job[BUFFSIZE];
      int success;
      MPI_Status status;
      while (1) {
	success = 0;
	// run the job
	MPI_Recv(&job,BUFFSIZE,MPI_CHAR,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
	
	/* Check the tag of the received message. */
	if (status.MPI_TAG == DIETAG) {
	  //printf("%d: Received DIETAG\n",mynode);
	  break;
	}
	else if (status.MPI_TAG == QCHEM_TAG) {
	  if (MPI_PrintLevel > 0 )
	    printf("%d: Q-chem job: %s\n",mynode,job);
	}
	else if (status.MPI_TAG == TINKER_TAG) {
	  if (MPI_PrintLevel > 0 )
	    printf("%d: Tinker job: %s\n",mynode,job);
	}
	else if (status.MPI_TAG == CAMCASP_TAG) {
	  if (MPI_PrintLevel > 0 )
	    printf("%d: CamCasp job: %s\n",mynode,job);
	}
	else {
	  printf("Unknown MPI tag\n");
	}

	// Go ahead and run the job 
	system(job);
	string jobstr = job;
	success = CheckIfJobSuccessful(jobstr,status.MPI_TAG);
	
	//MPI_Send(&success,1,MPI_INT,0,0,MPI_COMM_WORLD);
	MPI_Send(&success,1,MPI_INT,0,status.MPI_TAG,MPI_COMM_WORLD);
      }
      if (MPI_PrintLevel > 0 )
	printf("MPI: Node %d exiting\n",mynode);
      break;
    } 
  }
  // Finalize MPI and exit
  fflush(stdout);
  MPI_Finalize();
#endif /* PARALLEL */
}
コード例 #7
0
void Isotropic_Rankine_Yield_Function::ReturnMapping(const Vector& StrainVector, const Vector& TrialStress, Vector& StressVector)
{

    if(mcurrent_Ft>0.00)
    {
        //const double& Young   = (*mprops)[YOUNG_MODULUS];
        //const double& Poisson = (*mprops)[POISSON_RATIO];
        //const double Gmodu    = Young/(2.00 * (1.00 + Poisson) );
        //const double Bulk     = Young/(3.00 * (1.00-2.00*Poisson));

        array_1d<double,3> PrincipalStress = ZeroVector(3);
        array_1d<double,3> Sigma = ZeroVector(3);
        array_1d<array_1d < double,3 > ,3> EigenVectors;
        array_1d<unsigned int,3> Order;
        //const double d3  = 0.3333333333333333333;

        const int dim =  TrialStress.size();
        Vector Stress(dim);
        Stress = ZeroVector(dim);
        /// computing the trial kirchooff strain
        SpectralDecomposition(TrialStress, PrincipalStress, EigenVectors);
        IdentifyMaximunAndMinumumPrincipalStres_CalculateOrder(PrincipalStress, Order);
        noalias(Sigma)  = PrincipalStress;
        noalias(Stress) = TrialStress;


        const bool check = CheckPlasticAdmisibility(PrincipalStress);
        if(check==true)
        {
            Vector delta_lamda;
            // return to main plane
            bool check = One_Vector_Return_Mapping_To_Main_Plane(PrincipalStress, delta_lamda,  Sigma);


            if(check==false)
            {
                //return to corner
                UpdateMaterial();
                check =  Two_Vector_Return_Mapping_To_Corner(PrincipalStress, delta_lamda, Sigma);
                if (check==false)
                {
                    //return to apex
                    UpdateMaterial();
                    Three_Vector_Return_Mapping_To_Apex (PrincipalStress, delta_lamda, Sigma);
                }
            }

            AssembleUpdateStressAndStrainTensor(Sigma,  EigenVectors,  Order, StrainVector, Stress);

            CalculatePlasticDamage(Sigma);
            Matrix PlasticTensor;
            PlasticTensor.resize(3,3,false);
            PlasticTensor = ZeroMatrix(3,3);
            /// Updating the  elastic plastic strain tensor
            for(unsigned int i=0; i<3; i++)
                noalias(PlasticTensor) +=  mPrincipalPlasticStrain_current[i] * Matrix(outer_prod(EigenVectors[Order[i]],  EigenVectors[Order[i]]));

            /// WARNING = Plane Strain
            mplastic_strain[0] = PlasticTensor(0,0);
            mplastic_strain[1] = PlasticTensor(1,1);
            mplastic_strain[2] = 2.00 * PlasticTensor(1,0);
            mplastic_strain[3] = PlasticTensor(2,2);

            //CalculatePlasticStrain(StrainVector, StressVector, mplastic_strain, Sigma[2]);
        }

        CalculateElasticStrain(Stress, mElastic_strain);

        /// WARNING = Plane Strain
        StressVector[0] = Stress[0];
        StressVector[1] = Stress[1];
        StressVector[2] = Stress[2];
        //KRATOS_WATCH("----------------------------")
    }
}
コード例 #8
0
ファイル: test-kec.cpp プロジェクト: gabeochoa/CS440
void
run_test(int iterations) {

    /*
     * Test with Person.
     */

    {
        Person p1("Jane");
        Person p2("John");
        Person p3("Mary");
        Person p4("Dave");

        MAP_T<const Person, int> map;

        // Insert people into the map.
        auto p1_it = map.insert(std::make_pair(p1, 1));
        map.insert(std::make_pair(p2, 2));
        map.insert(std::make_pair(p3, 3));
        map.insert(std::make_pair(p4, 4));

        // Check iterator equality.
        {
            // Returns an iterator pointing to the first element.
            auto it1 = map.begin();
            // Returns an iterator pointing to one PAST the last element.  This
            // iterator is obviously conceptual only.  It cannot be
            // dereferenced.
            auto it2 = map.end();

            it1++; // Second node now.
            it1++; // Third node now.
            it2--; // Fourth node now.
            it2--; // Third node now.
            assert(it1 == it2);
            it2--; // Second node now.
            it2--; // First node now.
            assert(map.begin() == it2);
        }

        // Check insert return value.
        {
            printf("---- Test insert() return.\n");
            // Insert returns an interator.  If it's already in, it returns an
            // iterator to the already inserted element.
            auto it = map.insert(std::make_pair(p1, 1));
            assert(it == p1_it);
            // Now insert one that is new.
            it = map.insert(std::make_pair(Person("Larry"), 5));
            print(*it);
            map.erase(it);
        }

        // Print the whole thing now, to verify ordering.
        printf("---- Before erasures.\n");

        // Iterate through the whole map, and call print() on each Person.
        for (auto &e : map) {
            print(e);
        }

        // Test multiple traversals of the same map.
        printf("---- Multiple traversals\n");
        traverse(map, 4);

        // Test multiple BST at the same time.
        printf("---- Multiple BST\n");
        traverse2<MAP_T>(4);

        /*
         * Test some erasures.
         */

        // Erase first element.
        map.erase(map.begin());
        auto it = map.end();
        --it; // it now points to last element.
        it--; // it now points to penultimate element.
        map.erase(it);

        printf("---- After erasures.\n");

        // Iterate through the whole map, and call print() on each Person.
        for (auto &e : map) {
            print(e);
        }

        // Test iterator validity.
        {
            // Iterators must be valid even when other things are inserted or
            // erased.
            printf("---- Test iterator non-invalidation\n");

            // Get iterator to the first.
            auto b = map.begin();

            // Insert element which will be at the end.
            auto it = map.insert(std::make_pair(Person("Zeke"), 10));

            // Iterator to the first should still be valid.
            print(*b);

            // Delete first, saving the actual object.
            auto tmp(*b); // Save, so we can reinsert.
            map.erase(map.begin()); // Erase it.

            // Check iterator for inserted.  Iterator to end should still be valid.
            print(*it); // This should still be valid.

            // Reinsert first element.
            map.insert(tmp);

            // Erase inserted last element.
            map.erase(it);
        }
    }

    /*
     * Test Map with MyClass.
     */

    {
        MAP_T<const MyClass, std::string> map;

        // Empty container, should print nothing.
        for (auto it = map.begin(); it != map.end(); ++it) {
            abort();
        }

        MyClass m1(0), m2(3), m3(1), m4(2);
        auto m1_it = map.insert(std::make_pair(m1, "mmm1"));
        map.insert(std::make_pair(m2, "mmm2"));
        map.insert(std::make_pair(m3, "mmm3"));
        map.insert(std::make_pair(m4, "mmm4"));

        // Should print 0.0 1.0 2.0 3.0
        for (auto &e : map) {
            printf("%3.1f ", e.first.num);
        }
        printf("\n");

        // Check return value of insert.
        {
            // Already in, so must return equal to m1_it.
            auto it = map.insert(std::make_pair(m1, "mmm1"));
            assert(it == m1_it);
        }

        // Erase the first element.
        map.erase(map.begin());
        // Should print "1.0 2.0 3.0".
        for (auto &e : map) {
            printf("%3.1f ", e.first.num);
        }
        printf("\n");

        // Erase the new first element.
        map.erase(map.begin());
        // Should print "2.0 3.0".
        for (auto &e : map) {
            printf("%3.1f ", e.first.num);
        }
        printf("\n");

        map.erase(--map.end());
        // Should print "2.0".
        for (auto &e : map) {
            printf("%3.1f ", e.first.num);
        }
        printf("\n");

        // Erase the last element.
        map.erase(map.begin());
        // Should print nothing.
        for (auto &e : map) {
            printf("%3.1f ", e.first.num);
        }
        printf("\n");
    }

    /*
     * Test Map with plain int.
     */

    {
        MAP_T<const int, std::string> map;

        // Empty container, should print nothing.
        for (auto &e : map) {
            printf("%d ", e.first);
        }

        auto p1(std::make_pair(4, "444"));
        auto p2(std::make_pair(3, "333"));
        auto p3(std::make_pair(0, "000"));
        auto p4(std::make_pair(2, "222"));
        auto p5(std::make_pair(1, "111"));

        map.insert(p1);
        map.insert(p2);
        map.insert(p3);
        map.insert(p4);
        map.insert(p5);

        // Should print "0 1 2 3 4".
        for (auto it = map.begin(); it != map.end(); ++it) {
            print(*it);
        }
        printf("\n");

        // Insert dupes.
        map.insert(p4);
        map.insert(p1);
        map.insert(p3);
        map.insert(p2);
        map.insert(p5);
        // Should print "0 1 2 3 4".
        for (auto it = map.begin(); it != map.end(); ++it) {
            print(*it);
        }
        printf("\n");

        // Erase the first element.
        map.erase(map.begin());

        // Erase the new first element.
        map.erase(map.begin());

        // Erase the element in the end.
        map.erase(--map.end());
        // Should print "2 3".
        for (auto &e : map) {
            print(e);
        }
        printf("\n");

        // Erase all elements.
        map.erase(map.begin());
        map.erase(map.begin());
        // Should print nothing.
        for (auto &e : map) {
            print(e);
        }
        printf("\n");
    }

    /*
     * Stress test Map.
     */

    if (iterations > 0) {

        MAP_T<const Stress, double> map;
        using it_t = typename MAP_T<const Stress, double>::Iterator;
        using mirror_t = std::map<const Stress, double>;
        mirror_t mirror;

        using iters_t = std::set<it_t, bool(*)(const it_t &lhs, const it_t &rhs)>;
        iters_t iters(&less<MAP_T>);

        std::cout << "---- Starting stress test:" << std::endl;

        const int N = iterations;

        srand(9757);
        int n_inserted = 0, n_erased = 0, n_iters_changed = 0, n_empty = 0, n_dupes = 0;
        double avg_size = 0;

        for (int i = 0; i < N; ++i) {

            double op = drand48();

            // The probability of removal should be slightly higher than the
            // probability of insertion so that the map is often empty.
            if (op < .44) {

                // Insert an element.  Repeat until no duplicate.
                do {
                    // Limit the range of values of Stress so that we get some dupes.
                    auto v(std::make_pair(Stress(rand()%50000), drand48()));
                    auto find_it = map.find(v.first);
                    auto it = map.insert(v);
                    auto mir_res = mirror.insert(v);
                    if (mir_res.second) {
                        // If insert into mirror succeeded, insert into the map
                        // should also have succeeded.  It should not have
                        // found it before insert.
                        assert(find_it == map.end());
                        // Store the iterator.
                        iters.insert(it);
                        break;
                    }
                    // If insert into mirror did not succeed, insert into map
                    // should also not have succeeded, in which case, we
                    // generate another value to store.  Also, find should have
                    // found it, and insert should have returned same iterator.
                    assert(find_it == it);
                    n_dupes++;
                } while (true);

                ++n_inserted;
                 
            } else if (op < .90) {

                // Erase an element.
                if (iters.size() != 0) {

                    // Pick a random index.
                    int index = rand()%iters.size();
                    typename iters_t::iterator iit = iters.begin();
                    while(index--) {
                        ++iit;
                    }

                    auto it = *iit;
                    // The iterator should not be end()
                    assert(it != map.end());

                    Stress s((*it).first);
                    mirror.erase(s);
                    iters.erase(iit);
                    map.erase(it);

                    ++n_erased;
                }

            } else {

                // Does either postfix or prefix inc/dec operation.
                auto either_or = [&](it_t &it, it_t &(it_t::*f1)(), it_t (it_t::*f2)(int)) {
                    if (rand()%2 == 0) {
                        (it.*f1)();
                    } else {
                        (it.*f2)(0);
                    }
                };

                // Increment or decrement an iterator.

                // Size of containers should be same
                assert(iters.size() == mirror.size());

                // If the container is empty, skip
                if (iters.size() != 0) {

                    // Pick a random index
                    int index = rand()%iters.size();
                    typename iters_t::iterator iters_it = iters.begin();
                    while (index--) {
                        ++iters_it;
                    }

                    auto it = *iters_it;
                    // The iterator should not be end().
                    assert(it != map.end());

                    // If it is the begin(), then only increment,
                    // otherwise, pick either forward or backward.
                    if (it == map.begin()) {
                        either_or(it, &it_t::operator++, &it_t::operator++);
                        ++iters_it;
                    } else {
                        if (rand()%2 == 0) {
                            either_or(it, &it_t::operator++, &it_t::operator++);
                            ++iters_it;
                        } else {
                            either_or(it, &it_t::operator--, &it_t::operator--);
                            --iters_it;
                        }
                    }
                    // If we didn't hit the end, replace the resulting iterator
                    // in the iterator list.
                    // Note that the set is sorted.
                    if (it != map.end()) {
                        assert(it == *iters_it);
                        iters.erase(iters_it);
                        iters.insert(it);
                    }
                }

                ++n_iters_changed;
            }

            avg_size += double(iters.size())/N;

            if (iters.size() == 0) {
                ++n_empty;
            }

            check(map, mirror);
        }

        std::cout << "inserted: " << n_inserted << " times" << std::endl;
        std::cout << "erased: " << n_erased << " times" << std::endl;
        std::cout << "iterators changed: " << n_iters_changed << " times" << std::endl;
        std::cout << "empty count: " << n_empty << std::endl;
        std::cout << "avg size: " << avg_size << std::endl;
        std::cout << "n dupes: " << n_dupes << std::endl;
    }
}