예제 #1
0
bool FunctionTests::testAdaptiveIntegrate()
{
  bool success = true;

  // we must create our own basisCache here because _basisCache
  // has had its ref cell points set, which basically means it's
  // opted out of having any help with integration.
  BasisCachePtr basisCache = Teuchos::rcp( new BasisCache( _elemType, _spectralConfusionMesh ) );
  vector<GlobalIndexType> cellIDs;
  cellIDs.push_back(0);
  basisCache->setPhysicalCellNodes( _spectralConfusionMesh->physicalCellNodesForCell(0), cellIDs, true );

  double eps = .1; //
  FunctionPtr boundaryLayerFunction = Teuchos::rcp( new BoundaryLayerFunction(eps) );
  int numCells = basisCache->cellIDs().size();
  FieldContainer<double> integrals(numCells);
  double quadtol = 1e-2;
  double computedIntegral = boundaryLayerFunction->integrate(_spectralConfusionMesh,quadtol);
  double trueIntegral = (eps*(exp(1/eps) - exp(-1/eps)))*2.0;
  double diff = trueIntegral-computedIntegral;
  double relativeError = abs(diff)/abs(trueIntegral); // relative error

  double tol = 1e-2;
  if (relativeError > tol)
  {
    success = false;
    cout << "failing testAdaptiveIntegrate() with computed integral " << computedIntegral << " and true integral " << trueIntegral << endl;
  }
  return success;
}
예제 #2
0
/*Function to calculate the integral histogram*/
std::vector<cv::Mat> calculateIntegralHOG(const cv::Mat& _in, const int _nbins) {
  /*Convert the input image to grayscale*/
//  cv::Mat img_gray;

//  cv::cvtColor(_in, img_gray, CV_BGR2GRAY);
//  cv::equalizeHist(img_gray, img_gray);

  /* Calculate the derivates of the grayscale image in the x and y
   directions using a sobel operator and obtain 2 gradient images
   for the x and y directions*/

  cv::Mat xsobel, ysobel;
  cv::Sobel(_in, xsobel, CV_32FC1, 1, 0);
  cv::Sobel(_in, ysobel, CV_32FC1, 0, 1);

  //Gradient magnitude
  cv::Mat gradient_magnitude;
  cv::magnitude(xsobel, ysobel, gradient_magnitude);
  //Gradient orientation
  cv::Mat gradient_orientation;
  bool angleInDegrees = true;
  cv::phase(xsobel, ysobel, gradient_orientation, angleInDegrees);

//  std::cout << "_in=" << _in.rows << "x" << _in.cols << std::endl;
//  std::cout << "gradient_magnitude=" << gradient_magnitude.rows << "x" << gradient_magnitude.cols << std::endl;
//  std::cout << "gradient_orientation=" << gradient_orientation.rows << "x" << gradient_orientation.cols << std::endl;
//
//  double min_angle, max_angle;
//  cv::minMaxLoc(gradient_orientation, &min_angle, &max_angle, NULL, NULL);
//  std::cout << "min_angle=" << min_angle << " ; max_angle=" << max_angle << std::endl;


  //TODO: useless ?
//  img_gray.release();

  /* Create an array of 9 images (9 because I assume bin size 20 degrees
   and unsigned gradient ( 180/20 = 9), one for each bin which will have
   zeroes for all pixels, except for the pixels in the original image
   for which the gradient values correspond to the particular bin.
   These will be referred to as bin images. These bin images will be then
   used to calculate the integral histogram, which will quicken
   the calculation of HOG descriptors */

  std::vector<cv::Mat> bins(_nbins);
  for (int i = 0; i < _nbins; i++) {
    bins[i] = cv::Mat::zeros(_in.size(), CV_32FC1);
  }

  /* Create an array of 9 images ( note the dimensions of the image,
   the cvIntegral() function requires the size to be that), to store
   the integral images calculated from the above bin images.
   These 9 integral images together constitute the integral histogram */

  std::vector<cv::Mat> integrals(_nbins);
  //IplImage** integrals = (IplImage**) malloc(9 * sizeof(IplImage*));
  for (int i = 0; i < _nbins; i++) {
    integrals[i] = cv::Mat(
        cv::Size(_in.size().width + 1, _in.size().height + 1), CV_64FC1);
  }

  /* Calculate the bin images. The magnitude and orientation of the gradient
   at each pixel is calculated using the xsobel and ysobel images.
   {Magnitude = sqrt(sq(xsobel) + sq(ysobel) ), gradient = itan (ysobel/xsobel) }.
   Then according to the orientation of the gradient, the value of the
   corresponding pixel in the corresponding image is set */

  int x, y;
  float temp_gradient, temp_magnitude;
  for (y = 0; y < _in.size().height; y++) {
    /* ptr1 and ptr2 point to beginning of the current row in the xsobel and ysobel images
     respectively.
     ptrs[i] point to the beginning of the current rows in the bin images */

#if 0
    float* xsobelRowPtr = (float*) (xsobel.row(y).data);
    float* ysobelRowPtr = (float*) (ysobel.row(y).data);
    float** binsRowPtrs = new float *[_nbins];

    for (int i = 0; i < _nbins; i++) {
      binsRowPtrs[i] = (float*) (bins[i].row(y).data);
    }
#else
    float* xsobelRowPtr = xsobel.ptr<float>(y);
    float* ysobelRowPtr = ysobel.ptr<float>(y);
    float** binsRowPtrs = new float *[_nbins];

    for (int i = 0; i < _nbins; i++) {
      binsRowPtrs[i] = bins[i].ptr<float>(y);
    }

    float* magnitudeRowPtr = gradient_magnitude.ptr<float>(y);
    float* orientationRowPtr = gradient_orientation.ptr<float>(y);
#endif

    /*For every pixel in a row gradient orientation and magnitude
     are calculated and corresponding values set for the bin images. */
    for (x = 0; x < _in.size().width; x++) {
#if 0
      /* if the xsobel derivative is zero for a pixel, a small value is
       added to it, to avoid division by zero. atan returns values in radians,
       which on being converted to degrees, correspond to values between -90 and 90 degrees.
       90 is added to each orientation, to shift the orientation values range from {-90-90} to {0-180}.
       This is just a matter of convention. {-90-90} values can also be used for the calculation. */
      if (xsobelRowPtr[x] == 0) {
        temp_gradient = ((atan(ysobelRowPtr[x] / (xsobelRowPtr[x] + 0.00001)))
            * (180 / M_PI)) + 90;
      } else {
        temp_gradient = ((atan(ysobelRowPtr[x] / xsobelRowPtr[x])) * (180 / M_PI))
            + 90;
      }
      temp_magnitude = sqrt(
          (xsobelRowPtr[x] * xsobelRowPtr[x])
              + (ysobelRowPtr[x] * ysobelRowPtr[x]));
#else
      temp_magnitude = magnitudeRowPtr[x];
      temp_gradient = orientationRowPtr[x] > 180 ? orientationRowPtr[x]-180 : orientationRowPtr[x];
#endif

      /*The bin image is selected according to the gradient values.
       The corresponding pixel value is made equal to the gradient
       magnitude at that pixel in the corresponding bin image */
      float binStep = 180 / _nbins;

      for (int i = 1; i <= _nbins; i++) {
        if (temp_gradient <= binStep * i) {
          binsRowPtrs[i - 1][x] = temp_magnitude;
          break;
        }
      }
    }

    //Delete binsRowPtrs
    delete[] binsRowPtrs;
  }

  //TODO: useless
//  xsobel.release();
//  ysobel.release();

  /*Integral images for each of the bin images are calculated*/
  for (int i = 0; i < _nbins; i++) {
    cv::integral(bins[i], integrals[i]);
  }

  //TODO: useless
//  for (int i = 0; i < _nbins; i++) {
//    bins[i].release();
//  }

  /*The function returns an array of 9 images which constitute the integral histogram*/
  return integrals;
}
예제 #3
0
bool LinearTermTests::testIntegrateMixedBasis()
{
  bool success = true;

  ////////////////////   DECLARE VARIABLES   ///////////////////////
  // define test variables
  VarFactoryPtr varFactory = VarFactory::varFactory();
  VarPtr v = varFactory->testVar("v", HGRAD);

  // define trial variables
  VarPtr beta_n_u_hat = varFactory->fluxVar("\\widehat{\\beta \\cdot n }");
  VarPtr u = varFactory->fieldVar("u");

  vector<double> beta;
  beta.push_back(1.0);
  beta.push_back(1.0);

  ////////////////////   DEFINE BILINEAR FORM/Mesh   ///////////////////////

  BFPtr convectionBF = Teuchos::rcp( new BF(varFactory) );

  // v terms:
  convectionBF->addTerm( -u, beta * v->grad() );
  convectionBF->addTerm( beta_n_u_hat, v);
  convectionBF->addTerm( u, v);

  // build CONSTANT SINGLE ELEMENT MESH
  int order = 0;
  int H1Order = order+1;
  int pToAdd = 1;
  int nCells = 2; // along a side

  // create a pointer to a new mesh:
  Teuchos::RCP<Mesh> mesh = MeshUtilities::buildUnitQuadMesh(nCells,convectionBF, H1Order, H1Order+pToAdd);
  ElementTypePtr elemType = mesh->getElement(0)->elementType();
  BasisCachePtr basisCache = Teuchos::rcp(new BasisCache(elemType, mesh));
  vector<GlobalIndexType> cellIDs;
  vector< ElementPtr > allElems = mesh->activeElements();
  vector< ElementPtr >::iterator elemIt;
  for (elemIt=allElems.begin(); elemIt!=allElems.end(); elemIt++)
  {
    cellIDs.push_back((*elemIt)->cellID());
  }
  bool createSideCacheToo = true;
  basisCache->setPhysicalCellNodes(mesh->physicalCellNodesGlobal(elemType), cellIDs, createSideCacheToo);

  int numTrialDofs = elemType->trialOrderPtr->totalDofs();
  int numCells = mesh->numActiveElements();
  double areaPerCell = 1.0 / numCells;
  FieldContainer<double> integrals(numCells,numTrialDofs);
  FieldContainer<double> expectedIntegrals(numCells,numTrialDofs);
  double sidelengthOfCell = 1.0 / nCells;
  DofOrderingPtr trialOrdering = elemType->trialOrderPtr;
  int dofForField = trialOrdering->getDofIndex(u->ID(), 0);
  vector<int> dofsForFlux;
  const vector<int>* sidesForFlux = &trialOrdering->getSidesForVarID(beta_n_u_hat->ID());
  for (vector<int>::const_iterator sideIt = sidesForFlux->begin(); sideIt != sidesForFlux->end(); sideIt++)
  {
    int sideIndex = *sideIt;
    dofsForFlux.push_back(trialOrdering->getDofIndex(beta_n_u_hat->ID(), 0, sideIndex));
  }
  for (int cellIndex = 0; cellIndex < numCells; cellIndex++)
  {
    expectedIntegrals(cellIndex, dofForField) = areaPerCell;
    for (vector<int>::iterator dofIt = dofsForFlux.begin(); dofIt != dofsForFlux.end(); dofIt++)
    {
      int fluxDofIndex = *dofIt;
      expectedIntegrals(cellIndex, fluxDofIndex) = sidelengthOfCell;
    }
  }

//  cout << "expectedIntegrals:\n" << expectedIntegrals;

  // setup: with constant degrees of freedom, we expect that the integral of int_dK (flux) + int_K (field) will be ones for each degree of freedom, assuming the basis functions for these constants field/flux variables are just C = 1.0.
  //
  //On a unit square, int_K (constant) = 1.0, and int_dK (u_i) = 1, for i = 0,...,3.

  LinearTermPtr lt = 1.0 * beta_n_u_hat;
  LinearTermPtr field =  1.0 * u;
  lt->addTerm(field,true);
  lt->integrate(integrals, elemType->trialOrderPtr, basisCache);

  double tol = 1e-12;
  double maxDiff;
  success = TestSuite::fcsAgree(integrals,expectedIntegrals,tol,maxDiff);
  if (success==false)
  {
    cout << "Failed testIntegrateMixedBasis with maxDiff = " << maxDiff << endl;
  }

  return success;
}
예제 #4
0
void Foam::momentOfInertia::massPropertiesSolid
(
    const pointField& pts,
    const triFaceList& triFaces,
    scalar density,
    scalar& mass,
    vector& cM,
    tensor& J
)
{
    // Reimplemented from: Wm4PolyhedralMassProperties.cpp
    // File Version: 4.10.0 (2009/11/18)

    // Geometric Tools, LC
    // Copyright (c) 1998-2010
    // Distributed under the Boost Software License, Version 1.0.
    // http://www.boost.org/LICENSE_1_0.txt
    // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt

    // Boost Software License - Version 1.0 - August 17th, 2003

    // Permission is hereby granted, free of charge, to any person or
    // organization obtaining a copy of the software and accompanying
    // documentation covered by this license (the "Software") to use,
    // reproduce, display, distribute, execute, and transmit the
    // Software, and to prepare derivative works of the Software, and
    // to permit third-parties to whom the Software is furnished to do
    // so, all subject to the following:

    // The copyright notices in the Software and this entire
    // statement, including the above license grant, this restriction
    // and the following disclaimer, must be included in all copies of
    // the Software, in whole or in part, and all derivative works of
    // the Software, unless such copies or derivative works are solely
    // in the form of machine-executable object code generated by a
    // source language processor.

    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
    // NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
    // ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
    // OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
    // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    // USE OR OTHER DEALINGS IN THE SOFTWARE.

    const scalar r6 = 1.0/6.0;
    const scalar r24 = 1.0/24.0;
    const scalar r60 = 1.0/60.0;
    const scalar r120 = 1.0/120.0;

    // order:  1, x, y, z, x^2, y^2, z^2, xy, yz, zx
    scalarField integrals(10, 0.0);

    forAll(triFaces, i)
    {
        const triFace& tri(triFaces[i]);

        // vertices of triangle i
        vector v0 = pts[tri[0]];
        vector v1 = pts[tri[1]];
        vector v2 = pts[tri[2]];

        // cross product of edges
        vector eA = v1 - v0;
        vector eB = v2 - v0;
        vector n = eA ^ eB;

        // compute integral terms
        scalar tmp0, tmp1, tmp2;

        scalar f1x, f2x, f3x, g0x, g1x, g2x;

        tmp0 = v0.x() + v1.x();
        f1x = tmp0 + v2.x();
        tmp1 = v0.x()*v0.x();
        tmp2 = tmp1 + v1.x()*tmp0;
        f2x = tmp2 + v2.x()*f1x;
        f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
        g0x = f2x + v0.x()*(f1x + v0.x());
        g1x = f2x + v1.x()*(f1x + v1.x());
        g2x = f2x + v2.x()*(f1x + v2.x());

        scalar f1y, f2y, f3y, g0y, g1y, g2y;

        tmp0 = v0.y() + v1.y();
        f1y = tmp0 + v2.y();
        tmp1 = v0.y()*v0.y();
        tmp2 = tmp1 + v1.y()*tmp0;
        f2y = tmp2 + v2.y()*f1y;
        f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
        g0y = f2y + v0.y()*(f1y + v0.y());
        g1y = f2y + v1.y()*(f1y + v1.y());
        g2y = f2y + v2.y()*(f1y + v2.y());

        scalar f1z, f2z, f3z, g0z, g1z, g2z;

        tmp0 = v0.z() + v1.z();
        f1z = tmp0 + v2.z();
        tmp1 = v0.z()*v0.z();
        tmp2 = tmp1 + v1.z()*tmp0;
        f2z = tmp2 + v2.z()*f1z;
        f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
        g0z = f2z + v0.z()*(f1z + v0.z());
        g1z = f2z + v1.z()*(f1z + v1.z());
        g2z = f2z + v2.z()*(f1z + v2.z());

        // update integrals
        integrals[0] += n.x()*f1x;
        integrals[1] += n.x()*f2x;
        integrals[2] += n.y()*f2y;
        integrals[3] += n.z()*f2z;
        integrals[4] += n.x()*f3x;
        integrals[5] += n.y()*f3y;
        integrals[6] += n.z()*f3z;
        integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
        integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
        integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
    }

    integrals[0] *= r6;
    integrals[1] *= r24;
    integrals[2] *= r24;
    integrals[3] *= r24;
    integrals[4] *= r60;
    integrals[5] *= r60;
    integrals[6] *= r60;
    integrals[7] *= r120;
    integrals[8] *= r120;
    integrals[9] *= r120;

    // mass
    mass = integrals[0];

    // center of mass
    cM = vector(integrals[1], integrals[2], integrals[3])/mass;

    // inertia relative to origin
    J.xx() = integrals[5] + integrals[6];
    J.xy() = -integrals[7];
    J.xz() = -integrals[9];
    J.yx() = J.xy();
    J.yy() = integrals[4] + integrals[6];
    J.yz() = -integrals[8];
    J.zx() = J.xz();
    J.zy() = J.yz();
    J.zz() = integrals[4] + integrals[5];

    // inertia relative to center of mass
    J -= mass*((cM & cM)*I - cM*cM);

    // Apply density
    mass *= density;
    J *= density;
}
예제 #5
0
int main() {

//  CGAL::Timer time;
//
//  time.start();
  
  cout << "Creating point cloud" << endl;

  simu.read();

  create();
  
  if(simu.create_points()) {

    //    set_alpha_circle( Tp , 2);
    //    set_alpha_under_cos(  Tp ) ;

    cout << "Creating alpha field " << endl;
    
    set_alpha_random(  Tp ) ;

    cout << "Numbering particles " << endl;

    number(Tp);
  }
  
  // areas(Tp);
  // quad_coeffs(Tp , simu.FEMp() ); volumes(Tp, simu.FEMp() );

  // volumes(Tp, simu.FEMp() );
  // Delta(Tp);

  // linear algebra(Tp);

  // if(simu.create_points()) {
  //   nabla(Tp);
  //   Delta(Tp);
  // }
  
  move_info( Tp );

  // /// Prev test begin
  //cout << "Calculating Lapl U" << endl;
  //algebra.laplacian_v(kind::UOLD,kind::LAPLU);

  //FT dt=simu.dt();

  //cout << "Calculating Ustar implicitely" << endl;
	  //algebra.ustar_inv(kind::USTAR,  dt , kind::UOLD, false);

  //cout << "Solving PPE" << endl;
  //algebra.PPE( kind::USTAR, dt, kind:: P );

  //cout << "Calculating grad p" << endl;
  //algebra.gradient(kind::P, kind::GRADP);
  //algebra.mass_s(kind::DIVU);

  
//draw();
//  return 1;

   /// Prev test end

#ifdef WRITE
  algebra.save_matrices();
#endif

      // areas(Tp);
      // quad_coeffs(Tp , simu.FEMp() ); volumes(Tp, simu.FEMp() );

      // nabla(Tp);
      // Delta(Tp);


      // linear algebra(Tp);

      // cout << "Calculating grad alpha" << endl;
      // algebra.gradient(kind::ALPHA, kind::GRADALPHA);
  
  const std::string particle_file("particles.dat");

  draw(Tp, particle_file , true);

  simu.advance_time();
  simu.next_step();

  //  bool first_iter=true;

  CGAL::Timer time;

  time.start();

  std::ofstream log_file;

  log_file.open("main.log");

  bool is_overdamped = ( simu.mu() > 1 ) ; // high or low Re

  for(;
      simu.current_step() <= simu.Nsteps();
      simu.next_step()) {

    cout
      << "Step " << simu.current_step() 
      << " . Time " <<  simu.time()
      << " ; t step " << simu.dt()
      << endl;

    FT dt=simu.dt();

    FT dt2 = dt / 2.0 ;

    int iter=0;
    FT displ=1e10;

    FT min_displ=1e10;
    int min_iter=0;

    const int max_iter=1; //10;
    const FT  max_displ=  1e-8; // < 0 : disable

//  leapfrog, special first step.-
//    if(simu.current_step() == 1) dt2 *= 0.5;

//    dt2 *= 0.5;

    move_info(Tp);

    // iter loop
    for( ; iter<max_iter ; iter++) {

      cout << "Move iteration  " << iter << " of " << max_iter << " " << endl;

      // comment for no move.-
      displ=move( Tp , dt2 );

      cout << "Iter " << iter << " , moved avg " << displ << " to half point" << endl;

      if( (displ < max_displ) && (iter !=0) ) break;

      areas(Tp);
      quad_coeffs(Tp , simu.FEMp() ); volumes(Tp, simu.FEMp() );

      nabla(Tp);
      Delta(Tp);

      linear algebra(Tp);
      
      if( displ < min_displ) {
	min_displ=displ;
	min_iter=iter;
      }

      //      set_forces_Kolmo(Tp);

//  Reynolds number discrimination



#ifdef EXPLICIT

	cout << "Calculating Ustar explicitely" << endl;

	algebra.laplacian_v(kind::UOLD,kind::LAPLU);

	u_star(Tp, dt2 , false );

#else

//	cout << "Calculating chem pot" << endl;

//	algebra.chempot(kind::ALPHA, kind::CHEMPOT);

	cout << "Calculating alpha implicitely" << endl;

	// partly explicit ( unstable ? ):
	cout << "Calculating chem pot explicitely" << endl;

        if (iter==0)
	  algebra.chempot( kind::ALPHA0, kind::CHEMPOT );
	else
	 algebra.chempot( kind::ALPHA , kind::CHEMPOT );

	// inner iter loop

	for( int alpha_it=0 ; alpha_it < 1 ; alpha_it++) { // max_iter ; alpha_it++) {

	  cout << "Alpha loop iter " << alpha_it << endl;

	  algebra.chempot( kind::ALPHA , kind::CHEMPOT );
	  algebra.alpha_inv_cp(kind::ALPHA, dt2 , kind::ALPHA0 );

	}



	//	algebra.gradient(kind::ALPHA, kind::ALPHA0); // ???
	
	// // iterative, fully implicit (does not converge):
	
	// int alpha_it=0;
	
	//     // inner iter loop
	// for( ; alpha_it < 10 ; alpha_it++) { // max_iter ; alpha_it++) {

	//   cout << "Alpha loop iter " << alpha_it << endl;
	  
	//   algebra.alpha_inv_cp2(kind::ALPHA, dt2 , kind::ALPHA0 );
    
	//   cout << "Calculating chem pot implicitely" << endl;
	//   algebra.chempot_inv(kind::ALPHA, dt2 , kind::ALPHA0 );
	// }
	// //	draw(Tp, particle_file , true);

	
	cout << "Settinf Ustar = force" << endl;

	//	algebra.ustar_is_force(kind::USTAR);

	algebra.chem_pot_force();

	// substract spurious overall movement.-
	
	zero_mean_v( Tp , kind::FORCE);

#endif

	cout << "Solving PPE" << endl;

	// comment for no move.-
	algebra.PPE( kind::FORCE , 1 , kind:: P ); // Dt set to 1

	// cout << "Calculating grad p" << endl;
	// // comment for no move.-
	// algebra.gradient(kind::P, kind::GRADP);

	algebra.u_inv_od(kind::U);
	
	cout << "Evolving U " << endl;

	// comment for no move.-
	u_new( Tp , dt2 );

	cout << "U evolved " << endl;

    } // iter loop

    // comment for no move.-
    displ=move( Tp , dt );
    
//    update_half_velocity( Tp , false ); 

    // comment for no move.-
    update_half_velocity( Tp , is_overdamped ); 

    update_half_alpha( Tp ); 

    areas(Tp);

    quad_coeffs(Tp , simu.FEMp() ); volumes(Tp, simu.FEMp() );

    if(simu.current_step()%simu.every()==0)
      draw(Tp, particle_file , true);

    log_file
      << simu.current_step() << "  "
      <<  simu.time() << "  " ;

    integrals( Tp , log_file);     log_file << "  ";
    fidelity(  Tp , log_file );    log_file << endl;

    simu.advance_time();

  } // time loop

  time.stop();

  log_file.close();
  
  cout << "Total runtime: " << time.time() << endl;
  return 0;

}