Commit bdfd2987 authored by COULAUD Olivier's avatar COULAUD Olivier
Browse files

Add outputs

parent 2208d28c
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, B��renger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
......@@ -72,7 +72,7 @@ int main(int argc, char ** argv){
#ifdef ScalFMM_USE_BLAS
// begin Chebyshef kernel
// accuracy
const unsigned int ORDER = 6;
const unsigned int ORDER = 8;
// typedefs
typedef FInterpMatrixKernelR MatrixKernelClass;
typedef FChebCell<ORDER> CellClass;
......@@ -152,9 +152,14 @@ int main(int argc, char ** argv){
}
counter.tac();
double dipoleNorm = electricMoment.norm2() ;
double volume = loader.getBoxWidth()*loader.getBoxWidth()*loader.getBoxWidth() ;
double coeffCorrectionDLPOLY = 2.0*FMath::FPi/volume/3.0 ;
std::cout << std::endl;
std::cout << "Total Charge = "<< totalCharge <<std::endl;
std::cout << "Electric Moment = "<< electricMoment <<std::endl;
std::cout << "electric Moment = "<< dipoleNorm <<std::endl;
std::cout << std::endl;
std::cout << std::endl;
......@@ -220,22 +225,26 @@ int main(int argc, char ** argv){
algo.setKernel(&kernels);
algo.execute();
algo.repetitionsIntervals(&min, &max);
// std::cout << "Min indexes " << min << std::endl ;
// std::cout << "Max indexes " << max << std::endl ;
}
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
std::cout << "Done " << "(@FMM Algorithm = " << counter.elapsed() << "s)." << std::endl;
std::cout << "\n"<< "END FMM "
<< "-------------------------------------------------------------------------" << std::endl << std::endl ;
// -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
// DIRECT COMPUTATION
// -----------------------------------------------------
EwalParticle* particlesDirect = 0;
// ----------------------------------------------------------------------------------------------------------
EwalParticle* particlesDirect = nullptr;
FReal directEnergy = 0.0;
//
// direct computation
//
bool direct = false ;
if(FParameters::existParameter(argc, argv, "-direct")){
direct = true ;
printf("Compute direct:\n");
printf("Box [%d;%d][%d;%d][%d;%d]\n", min.getX(), max.getX(), min.getY(),
max.getY(), min.getZ(), max.getZ());
......@@ -243,13 +252,19 @@ int main(int argc, char ** argv){
particlesDirect = new EwalParticle[loader.getNumberOfParticles()];
FReal denergy = 0.0;
FMath::FAccurater dfx, dfy, dfz;
FMath::FAccurater dfx, dfy, dfz ;
//
//
// particles : Ewald results
// particlesDirect : Direct results
//
counter.tic();
for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){
EwalParticle part = particles[idxTarget];
particlesDirect[idxTarget] = particles[idxTarget];
EwalParticle & part = particlesDirect[idxTarget];
part.forces[0] = part.forces[1] = part.forces[2] = 0.0;
part.potential = 0.0;
//
// compute with all other except itself
//
// Compute force and potential between particles[idxTarget] and particles inside the box
......@@ -268,15 +283,15 @@ int main(int argc, char ** argv){
//
// compute with image boxes
//
// for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){
// for(int idxY = min.getY() ; idxY <= max.getY() ; ++idxY){
// for(int idxZ = min.getZ() ; idxZ <= max.getZ() ; ++idxZ){
for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){
for(int idxY = min.getY() ; idxY <= max.getY() ; ++idxY){
for(int idxZ = min.getZ() ; idxZ <= max.getZ() ; ++idxZ){
int nL = PeriodicDeep ;
{
//
for(int idxX = -nL ; idxX <= nL -1; ++idxX){
for(int idxY = -nL ; idxY <=nL-1 ; ++idxY){
for(int idxZ = -nL ; idxZ <= nL-1; ++idxZ){
// for(int idxX = -nL ; idxX <= nL -1; ++idxX){
// for(int idxY = -nL ; idxY <=nL-1 ; ++idxY){
// for(int idxZ = -nL ; idxZ <= nL-1; ++idxZ){
if(idxX == 0 && idxY == 0 && idxZ == 0) continue;
const FPoint offset(loader.getBoxWidth() * FReal(idxX),
......@@ -298,7 +313,15 @@ int main(int argc, char ** argv){
}
} // END
}
//
// remove dipole correction for DL_POLY
//
part.forces[0] -= 2.0*part.physicalValue*coeffCorrectionDLPOLY*electricMoment.getX() ;
part.forces[1] -= 2.0*part.physicalValue*coeffCorrectionDLPOLY*electricMoment.getY() ;
part.forces[2] -= 2.0*part.physicalValue*coeffCorrectionDLPOLY*electricMoment.getZ() ;
//
// Scaling
//
part.forces[0] *= scaleForce ;
part.forces[1] *= scaleForce ;
part.forces[2] *= scaleForce ;
......@@ -321,33 +344,47 @@ int main(int argc, char ** argv){
// particlesDirect[idxTarget] = part;
}
counter.tac();
denergy *= 0.5*scaleEnergy ;
denergy -= coeffCorrectionDLPOLY*dipoleNorm*scaleEnergy ;
directEnergy = denergy ;
printf("Difference between direct and Ewald (DL_POLY)\n");
printf("DirectEwald Fx diff is = \n");
printf("DirectEwald L2Norm %e\n",dfx.getRelativeL2Norm() );
printf("DirectEwald InfNorm %e\n",dfx.getRelativeInfNorm());
printf("DirectEwaldFy diff is = \n");
printf("DirectEwald L2Norm %e\n",dfx.getRelativeL2Norm());
printf("DirectEwald InfNorm %e\n",dfy.getRelativeInfNorm());
printf("DirectEwaldFz diff is = \n");
printf("DirectEwald L2Norm %e\n",dfx.getRelativeL2Norm());
printf("DirectEwald InfNorm %e\n",dfz.getRelativeInfNorm());
double L2error = (dfx.getRelativeL2Norm()*dfx.getRelativeL2Norm() + dfy.getRelativeL2Norm()*dfy.getRelativeL2Norm() + dfz.getRelativeL2Norm() *dfz.getRelativeL2Norm() );
printf("DirectEwald L2 Force Error= %e\n",FMath::Sqrt(L2error)) ;
printf("DirectEwald Energy DIRECT= %e\n",denergy);
printf("DirectEwald Energy EWALD = %e\n",loader.getEnergy());
printf("DirectEwald Energy EWALD - Energy DIRECT = %e\n", loader.getEnergy()-denergy );
printf("DirectEwald |Energy EWALD - Energy DIRECT|/directEnergy= %e\n",FMath::Abs((loader.getEnergy()-denergy)/loader.getEnergy()));
printf("Difference between direct and DL_POLY:\n");
printf("Fx diff is = \n");
printf(" L2Norm %e\n",dfx.getL2Norm());
printf(" InfNorm %e\n",dfx.getInfNorm());
printf("Fy diff is = \n");
printf(" L2Norm %e\n",dfy.getL2Norm());
printf(" InfNorm %e\n",dfy.getInfNorm());
printf("Fz diff is = \n");
printf(" L2Norm %e\n",dfz.getL2Norm());
printf(" InfNorm %e\n",dfz.getInfNorm());
printf("Energy DIRECT= %e\n",denergy);
printf("Energy EWALD = %e\n",loader.getEnergy());
printf("Energy EWALD - Energy DIRECT = %e\n",loader.getEnergy()-denergy);
//
if(FParameters::existParameter(argc, argv, "-saveError")){
errorfile << std::endl << " END DIRECT " << std::endl ;
}
std::cout << "\n"<< " END DIRECT "
std::cout << "Done " << "(@DIRECT Algorithm = " << counter.elapsed() << "s)." << std::endl;
std::cout << "\n"<< "END DIRECT "
<< "-------------------------------------------------------------------------" << std::endl << std::endl ;
}
// -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
// DIRECT -- FMM Comparisons
// Ewald -- FMM Comparisons
// ----------------------------------------------------------------------------------------------------------
{
// particles : Ewald results
// particlesDirect : Direct results
//
FReal potential = 0.0, energy = 0.0;
FMath::FAccurater fx, fy, fz;
FMath::FAccurater fx, fy, fz, fmmdfx, fmmdfy, fmmdfz;
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
......@@ -360,15 +397,32 @@ int main(int argc, char ** argv){
const FReal*const positionsZ = leaf->getTargets()->getPositions()[2];
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
const FVector<int>& indexes = leaf->getTargets()->getIndexes();
//
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const int indexPartOrig = indexes[idxPart];
//
// remove dipole correction for DL_POLY
//
forcesX[idxPart] -= 2.0*physicalValues[idxPart]*coeffCorrectionDLPOLY*electricMoment.getX() ;
forcesY[idxPart] -= 2.0*physicalValues[idxPart]*coeffCorrectionDLPOLY*electricMoment.getY() ;
forcesZ[idxPart] -= 2.0*physicalValues[idxPart]*coeffCorrectionDLPOLY*electricMoment.getZ() ;
//
forcesX[idxPart] *= scaleForce;
forcesY[idxPart] *= scaleForce;
forcesZ[idxPart] *= scaleForce;
fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]);
if(direct) {
// std::cout << "Good x " << particlesDirect[idxPart].position.getX() << " y " << particlesDirect[idxPart].position.getY() << " z " << particlesDirect[idxPart].position.getZ() << std::endl;
// std::cout << "Direct fx " <<particlesDirect[idxPart].forces[0]<< " fy " << particlesDirect[idxPart].forces[1] << " fz " << particlesDirect[idxPart].forces[2] << std::endl;
// std::cout << "FMM fx " << forcesX[idxPart] << " fy " <<forcesY[idxPart] << " fz " << forcesZ[idxPart] << std::endl;
fmmdfx.add(particlesDirect[indexPartOrig].forces[0],forcesX[idxPart]);
fmmdfy.add(particlesDirect[indexPartOrig].forces[1],forcesY[idxPart]);
fmmdfz.add(particlesDirect[indexPartOrig].forces[2],forcesZ[idxPart]);
} else {
fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); // Ewald - FMM
fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]);
fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]);
}
energy += potentials[idxPart]*physicalValues[idxPart];
//
if(FParameters::existParameter(argc, argv, "-verbose")){
......@@ -378,8 +432,8 @@ int main(int argc, char ** argv){
std::cout << "Good fx " <<particles[indexPartOrig].forces[0] << " fy " << particles[indexPartOrig].forces[1] << " fz " << particles[indexPartOrig].forces[2] << std::endl;
std::cout << "FMM fx " << forcesX[idxPart] << " fy " <<forcesY[idxPart] << " fz " << forcesZ[idxPart] << std::endl;
std::cout << "ratio fx " << particles[indexPartOrig].forces[0]/forcesX[idxPart] << " fy " <<particles[indexPartOrig].forces[1]/forcesY[idxPart] << " fz " << particles[indexPartOrig].forces[2]/forcesZ[idxPart] << std::endl;
std::cout << "GOOD physical value " << particles[indexPartOrig].physicalValue << " potential " << particles[indexPartOrig].potential << std::endl;
std::cout << "FMM physical value " << physicalValues[idxPart] << " potential " << potentials[idxPart] << " energy cumul " << energy<<std::endl;
// std::cout << "GOOD physical value " << particles[indexPartOrig].physicalValue << " potential " << particles[indexPartOrig].potential << std::endl;
// std::cout << "FMM physical value " << physicalValues[idxPart] << " potential " << potentials[idxPart] << " energy cumul " << energy<<std::endl;
std::cout << "\n";
}
......@@ -404,25 +458,47 @@ int main(int argc, char ** argv){
}
});
energy *= 0.5*scaleEnergy ;
energy -= coeffCorrectionDLPOLY*dipoleNorm*scaleEnergy ;
// printf("(Energy EWALD - Energy FMM)/dipoleNorm = %e\n",(loader.getEnergy()-energy)*volume/(dipoleNorm));
// printf("(dipoleNorm /Volume = %e\n",correctEnergy);
//
printf("Difference between FMM and DL_POLY:\n");
if(direct) {
printf("Difference between FMM and DiRECT:\n");
printf("DirectFmm Fx diff is = \n");
printf("DirectFmm L2Norm %e\n",fmmdfx.getRelativeL2Norm());
printf("DirectFmm InfNorm %e\n",fmmdfx.getRelativeInfNorm());
printf("DirectFmm Fy diff is = \n");
printf("DirectFmm L2Norm %e\n",fmmdfy.getRelativeL2Norm());
printf("DirectFmm InfNorm %e\n",fmmdfy.getRelativeInfNorm());
printf("DirectFmm Fz diff is = \n");
printf("DirectFmm L2Norm %e\n",fmmdfz.getRelativeL2Norm());
printf("DirectFmm InfNorm %e\n",fmmdfz.getRelativeInfNorm());
double L2error = (fmmdfx.getRelativeL2Norm()*fmmdfx.getRelativeL2Norm() + fmmdfy.getRelativeL2Norm()*fmmdfy.getRelativeL2Norm() + fmmdfz.getRelativeL2Norm() *fmmdfz.getRelativeL2Norm() );
printf("DirectFmm L2 Force Error= %e\n",FMath::Sqrt(L2error)) ;
printf("Fx diff is = \n");
printf(" L2Norm %e\n",fx.getL2Norm());
printf(" InfNorm %e\n",fx.getInfNorm());
printf("Fy diff is = \n");
printf(" L2Norm %e\n",fy.getL2Norm());
printf(" InfNorm %e\n",fy.getInfNorm());
printf("Fz diff is = \n");
printf(" L2Norm %e\n",fz.getL2Norm());
printf(" InfNorm %e\n",fz.getInfNorm());
std::cout << std::endl<< std::endl<< "Potential= " << std::setprecision(8) << potential*scaleEnergy << std::endl;
//
printf("Energy FMM= %e\n",energy);
printf("Energy EWALD= %e\n",loader.getEnergy());
printf("Energy EWALD - Energy FMM = %e\n",loader.getEnergy()-energy);
printf("Energy EWALD / Energy FMM = %e\n",loader.getEnergy()/energy);
printf("DirectFmm Energy FMM= %e\n",energy);
printf("DirectFmm Energy DIRECT= %e\n",directEnergy);
printf("DirectFmm |Energy DIRECT - Energy DIRECT|/directEnergy= %e\n",FMath::Abs((directEnergy-energy)/directEnergy));
}
else {
printf("FmmEwald Difference between FMM and Ewald DL_POLY:\n");
printf("FmmEwald Fx diff is = \n");
printf("FmmEwald L2Norm %e\n",fx.getRelativeL2Norm());
printf("FmmEwald InfNorm %e\n",fx.getRelativeInfNorm());
printf("FmmEwald Fy diff is = \n");
printf("FmmEwald L2Norm %e\n",fy.getRelativeL2Norm());
printf("FmmEwald InfNorm %e\n",fy.getInfNorm());
printf("FmmEwald Fz diff is = \n");
printf("FmmEwald L2Norm %e\n",fz.getRelativeL2Norm());
printf("FmmEwald InfNorm %e\n",fz.getRelativeInfNorm());
//
printf("FmmEwald Energy FMM= %e\n",energy);
printf("FmmEwald Energy EWALD= %e\n",loader.getEnergy());
printf("FmmEwald Energy EWALD - Energy FMM = %e\n",loader.getEnergy()-energy);
printf("FmmEwald |Energy EWALD -Energy FMM|/Energy EWALD= %e\n",FMath::Abs((loader.getEnergy()-energy)/loader.getEnergy()));
}
printf("vtkParticles\n");
vtkfile.writeParticules(tree, true,1,1,"vtkParticles","FMM results");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment