Skip to content
Snippets Groups Projects
Commit a7949440 authored by bamme's avatar bamme
Browse files

clean up

parent b5ac87c6
Branches master
No related tags found
No related merge requests found
......@@ -61,7 +61,7 @@ namespace Diffusion_PSE_Euler_1D
protected:
bool stop(const GlobalVariable& g)override{
return (g.endT<=g.t);
return (g.endT<g.t);
}
void neighborhood(const GlobalVariable& g)override{
this->cutoffRadius=g.rc;
......
......@@ -22,6 +22,7 @@ namespace PSE_1D
public:
double concentration;
double accumulator;
//int interactionCOunt;
//overritten helper functions for the print out
std::string getLables() const override {
......@@ -67,11 +68,15 @@ namespace PSE_1D
}
void interact(const GlobalVariable& g, Particle& p, Particle& q)override{
double d = q.position[0]-p.position[0];//calulates the euclidian distance squared
p.accumulator+= (q.concentration-p.concentration)*exp(-d*d/(4*g.epsilon*g.epsilon ));//calculate the excange of strangth (concentration) between the neighbors
//p.accumulator+= (q.concentration-p.concentration)*exp(-d*d/(4*g.epsilon*g.epsilon ));//calculate the excange of strangth (concentration) between the neighbors
p.accumulator+= (q.concentration-p.concentration)*exp(-(d/g.epsilon)*(d/(4.0*g.epsilon)));
//p.interactionCOunt++;
}
void evolve(GlobalVariable& g,Particle& p)override{
p.concentration= g.meshSpacing/(g.epsilon*g.epsilon*g.epsilon*2*sqrt(M_PI)) * p.accumulator;
p.accumulator=0;//set to 0 to have a fresh accumulator for the next time step
//p.concentration= g.meshSpacing/(g.epsilon*g.epsilon*g.epsilon*2*sqrt(M_PI)) * p.accumulator;
p.concentration= (g.meshSpacing/g.epsilon) * (p.accumulator/g.epsilon) /(g.epsilon*2.0*sqrt(M_PI));
p.accumulator=0.0;//set to 0 to have a fresh accumulator for the next time step
//cout<<p.interactionCOunt<<endl;
}
};
......
No preview for this file type
......@@ -10,7 +10,6 @@
#include "PM_Point.hpp"
#include "Perfectly_Elastic_Collision_nD_unit_test.hpp"
#include "Perfectly_Elastic_Collision_nD_correctness_check.hpp"
#include "functions_unit_tests.hpp"
#include "Diffusion_PSE_Euler_unit_test.hpp"
#include "Diffusion_PSE_Euler_correctness_check.hpp"
......@@ -24,27 +23,49 @@ int main(int argc, const char * argv[]) {
auto start = std::chrono::high_resolution_clock::now();//time mesurment start time
//test cases, they should be used one by one
// test_PM_Point();
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_unit_test();
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_big_unit_test();
// test_PM_Point();
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_unit_test();
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_big_unit_test();
// SPH::sph_unit_test();
//Diffusion_PSE_Euler_3D::diffusion_PSE_Euler_unit_test();
// functions_unit_test();
//Diffusion_PSE_Euler_3D::diffusion_PSE_Euler_correctness_check(32);
//Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_correctness_check();
// //Conovergence Study
// Diffusion_PSE_Euler_3D::diffusion_PSE_Euler_unit_test();
// functions_unit_test();
// Diffusion_PSE_Euler_3D::diffusion_PSE_Euler_correctness_check(32);
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_correctness_check();
// //Conovergence Study with sin() (paper)
// for(int i=1;i<100;i++){
// PSE_1D::pse_convergence_unit_test(power(2,i));
// }
// Time Complexity of increasing domain size with const particle density
for(int i=0;i<100;i++){
Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_big_time_test(0.5*power(2,i));
}
// //Conovergence Study with gaus-curve
// for(int i=1;i<100;i++){
// PSE_1D::pse_convergence_unit_test_gauss(power(2,i));
// }
// //Time Complexity of increasing domain size constant particle density (paper)
// for(int i=1;i<100;i++){
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_big_time_test_02(0.5*power(i,2));
// }
// //Time Complexity of increasing number of particles (paper)
// for(int i=0;i<100;i++){
// Diffusion_PSE_Euler_3D::diffusion_PSE_Euler_runtime_test(power(2,i));
// }
//random other tests
// // Time Complexity of increasing domain size with const particle density
// for(int i=0;i<100;i++){
// Perfectly_Elastic_Collision::perfectly_elastic_collision_2D_big_time_test(0.5*power(2,i));
// }
// //Time Complexity of increasing particle number constant domain size
// for(int i=0;i<100;i++){
......@@ -57,6 +78,7 @@ int main(int argc, const char * argv[]) {
// }
//time mesurment
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
......
......@@ -18,7 +18,7 @@
//Particle Method Instances for Diffusion
namespace Diffusion_PSE_Euler_3D {
double exactSolution(PM_Point<double,3> pos, double t, double diffConst){
double exactSolution(PM_Point<double,3> pos, double t, double diffConst){
double c=4*t*diffConst;
return exp(-pos.abs2()/c)/sqrt(power(M_PI*c,3));
}
......@@ -51,9 +51,117 @@ namespace Diffusion_PSE_Euler_3D {
}
Particle_Method diff(g, mesh);
diff.run(1000);
diff.run(10);
}
void diffusion_PSE_Euler_runtime_test(double scaling=64){
//Domain width is 1.0 and the center is 0.0 in all dimentions
GlobalVariable g;
g.diffusionConst=0.01;
g.meshSpacing=1.0/scaling;
g.epsilon=g.meshSpacing;
g.endT=0.5;
g.t=0.0;
g.dt=0.002;
g.rc=g.meshSpacing*3;
int halfsize=scaling/2.0;
g.meshDim = PM_Point<int,3> (2*halfsize+1);
g.domain_min= -halfsize*g.meshSpacing*PM_Point<double,3>(1);
g.domain_max= halfsize*g.meshSpacing*PM_Point<double,3>(1);
vector<Particle> mesh;
int length=g.meshDim[0]*g.meshDim[1]*g.meshDim[2];
mesh.resize(length);
mesh[(length-1)/2].concentration=1.0/power(g.meshSpacing,3);//initial peak at the center
//just for storing the data
for (int i=0; i<mesh.size(); i++){
mesh[i].position=(PM_Point<double, 3>)toVectorialIndex(i, g.meshDim)*g.meshSpacing+g.domain_min;
}
Particle_Method diff(g, mesh);
auto start = std::chrono::high_resolution_clock::now();//time mesurment start time
diff.run(-1);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
//init native C++
double t=0;
double dt=0.002; //std=0.002
double tend=0.5;
double meshSpacing=1.0/scaling;
double rc=meshSpacing*3;//cutof radius std=3
double epsilon=meshSpacing;//kernal width std=meshSpacing
double diffusionConst=0.01;
int halfNo=scaling/2.0;;
int no1D=halfNo*2+1;
int noParticles=no1D*no1D*no1D;
double x[noParticles];
double y[noParticles];
double z[noParticles];
double concentration[noParticles];
double accumulator[noParticles];
for(int i=0;i<no1D;i++){
for(int j=0;j<no1D;j++){
for(int k=0;k<no1D;k++){
x[k+j*no1D+i*no1D*no1D]=k*meshSpacing-halfNo*meshSpacing;
y[k+j*no1D+i*no1D*no1D]=j*meshSpacing-halfNo*meshSpacing;
z[k+j*no1D+i*no1D*no1D]=i*meshSpacing-halfNo*meshSpacing;
concentration[k+j*no1D+i*no1D*no1D]=0;
accumulator[k+j*no1D+i*no1D*no1D]=0;
}
}
}
concentration[(noParticles-1)/2]=1.0/meshSpacing/meshSpacing/meshSpacing;//initial peak at the center
cout << noParticles<<"," << elapsed.count() <<",";
start = std::chrono::high_resolution_clock::now();//time mesurment start time
//caclulation
while(t<tend){
for(int i=0;i<noParticles;i++){
for(int j=0;j<noParticles;j++){
double d2= (x[i]-x[j])*(x[i]-x[j])
+(y[i]-y[j])*(y[i]-y[j])
+(z[i]-z[j])*(z[i]-z[j]);
if(d2<=rc*rc){
double factor=d2/epsilon/epsilon;
double factor5=factor*factor*factor*factor*factor;
accumulator[i]+= (concentration[j]-concentration[i]) / (factor5+1.0);
}
}
}
for(int i=0;i<noParticles;i++){
double fa=meshSpacing/epsilon;
double fa3=fa*fa*fa;
double fb=epsilon*M_PI*epsilon*M_PI;
concentration[i]+= dt* diffusionConst * 15.0 * fa3/fb * accumulator[i];//Euler time step
accumulator[i]=0;//set to 0 to have a fresh accumulator for the next time step
}
t+=dt;
}
finish = std::chrono::high_resolution_clock::now();
elapsed = finish - start;
cout << elapsed.count() << ",";
//for correctness studies
double difference=0;
for (int i=0; i < noParticles; i++){
difference+=abs(mesh[i].concentration-concentration[i]);
}
cout << difference << endl;
}
}
#endif /* Diffusion_PSE_Euler_unit_test_h */
\ No newline at end of file
......@@ -16,13 +16,17 @@ namespace PSE_1D {
void pse_convergence_unit_test(int scaling=100){
GlobalVariable g;
//Settings for the convergence study in the aper
double domainSize=4.0;
int no_neigbors=12;
g.meshSpacing=domainSize/scaling;
g.epsilon=g.meshSpacing;
g.rc=g.meshSpacing*no_neigbors;
int length=scaling+2*no_neigbors+1;
g.meshDim = PM_Point<int,1> (length);
......@@ -65,6 +69,88 @@ namespace PSE_1D {
// cout << s.str() << endl;
save_to_file <Particle, 1>(errorMesh,s.str());
}
double gauss(double x){
double sigma=0.05;
return exp(-(x*x)/(sigma*sigma))/(sqrt(M_PI)*sigma);
}
double gaussdx(double x){
double sigma=0.05;
return -2.0*x*exp(-x*x/sigma/sigma)/sqrt(M_PI)/power(sigma,3);
}
double gaussdx2(double x){
double sigma=0.05;
//return 2.0/sqrt(M_PI)/power(sigma,3)*(2*x*x/sigma/sigma-1)*exp(-x*x/sigma/sigma);
return exp(-(x*x)/(sigma*sigma))*(4.0*x*x-2.0*sigma*sigma)/(sqrt(M_PI)*power(sigma,5));
}
void pse_convergence_unit_test_gauss(int scaling=100){
GlobalVariable g;
//Settings for the convergence study in the aper
double domainSize=1.0;
double no_neigbors=9;
g.meshSpacing=domainSize/scaling;
double c=1.0;
g.epsilon=g.meshSpacing/c;
g.rc=g.epsilon*no_neigbors;
int length=scaling+2*no_neigbors+1;
g.meshDim = PM_Point<int,1> (length);
g.domain_min= PM_Point<double,1>(-domainSize/2.0-g.rc);
g.domain_max= PM_Point<double,1>(domainSize/2.0+g.rc);
vector<Particle> mesh;
mesh.resize(length);
//init
for (int i=0; i<length; i++){
mesh[i].position[0]=i*g.meshSpacing+g.domain_min[0];
mesh[i].concentration= gauss(mesh[i].position[0]);
//mesh[i].interactionCOunt=0;
//cout <<mesh[i].position[0]<<","<< mesh[i].concentration <<","<< gauss(mesh[i].position[0]) <<endl;
}
//cout <<endl <<endl;
Particle_Method diff(g, mesh);
auto start = std::chrono::high_resolution_clock::now();//time mesurment start time
diff.run(1000);
auto finish = std::chrono::high_resolution_clock::now();
auto runtime = finish - start;
//for convergence studies
double maxError=0.0;
double l2error=0.0;
double maxValue=0.0;
vector<Particle> errorMesh;
errorMesh.resize(length);
for (int i=no_neigbors; i < length-no_neigbors; i++){
errorMesh[i].position=mesh[i].position;
double error=mesh[i].concentration-gaussdx2(mesh[i].position[0]);
errorMesh[i].concentration=abs(error);
l2error+=error*error;
maxValue=max(maxValue,abs(gaussdx2(mesh[i].position[0])));
maxError=max(maxError,errorMesh[i].concentration);
//cout <<mesh[i].position[0]<<","<< mesh[i].concentration <<","<< gaussdx2(mesh[i].position[0]) <<endl;
}
//l2error=sqrt(l2error)/maxValue/(scaling+1);//sqrt(l2error)/maxValue/(scaling+1);
l2error=l2error/maxValue/maxValue/(scaling+1);
maxError=maxError/maxValue;
cout << g.meshSpacing<<","<< maxError <<","<< runtime.count() << endl;
std::stringstream s;
s.str("");
s << "PSE_error_"<< ".csv";
// cout << s.str() << endl;
save_to_file <Particle, 1>(errorMesh,s.str());
}
}
#endif /* Diffusion_PSE_Euler_unit_test_h */
\ No newline at end of file
//
// Perfectly_Elastic_Collision_nD_correctness_check.hpp
// prototype_interface
//
// Created by Johannes Pahlke on 15.06.2022.
//
#ifndef Perfectly_Elastic_Collision_nD_correctness_check_h
#define Perfectly_Elastic_Collision_nD_correctness_check_h
#include "Perfectly_Elastic_Collision_nD.hpp"
#include <type_traits>
#include <random>
//Particle Method Instances for perfectly elastic collision
namespace Perfectly_Elastic_Collision{
void perfectly_elastic_collision_2D_correctness_check(){
std::random_device rd;
std::mt19937 e2(0);
std::uniform_real_distribution<> rand(-0.5, 0.5);
//invalid initial values (the particle are too close)
// int size=10000;
// vector<Particle<double,2>> balls;
// balls.resize(size);
// for (int i=0; i<size; i++){
// balls[i].position[0]=rand(e2);
// balls[i].position[1]=rand(e2);
// balls[i].velocity[0]=rand(e2)/10;
// balls[i].velocity[1]=rand(e2)/10;
// }
// GlobalVariable<double> g;
// g.dt=0.1;
// g.endT=10;
// g.t=0.0;
// g.rc=0.01;
int size=3;
vector<Particle<double,2>> balls;
balls.resize(3);
balls[0].position[0]=0.0;
balls[0].position[1]=0.0;
balls[1].position[0]=1.0;
balls[1].position[1]=0.2;
balls[2].position[0]=-0.1;
balls[2].position[1]=0.8;
balls[0].velocity[0]=0.25;
balls[0].velocity[1]=0;
balls[1].velocity[0]=-0.50;
balls[1].velocity[1]=0;
balls[2].velocity[0]=0.20;
balls[2].velocity[1]=-0.70;
GlobalVariable<double> g;
g.dt=0.1;
g.endT=10;
g.t=0.0;
g.rc=0.5;
Particle_Method<double, 2> pec(g,balls);
// Init native C++ variante
double t=0;
double dt=0.1;
double tend=10;
double rc=0.01;
double x[size];
double y[size];
double vx[size];
double vy[size];
for(int i=0;i<size;i++){
x[i]=balls[i].position[0];
y[i]=balls[i].position[1];
vx[i]=balls[i].velocity[0];
vy[i]=balls[i].velocity[1];
}
// run framework variant
pec.run();
//run native C++ variante
while(t<tend){
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
// double d2= (x[i]-x[j])*(x[i]-x[j])
// +(y[i]-y[j])*(y[i]-y[j]);
double diffx=x[j]-x[i];
double diffy=y[j]-y[i];
double d2=diffx*diffx+diffy*diffy;
if(d2<=rc*rc && (diffx>0.0 || (diffx==0.0 && diffy>0.0)) ){
double diffx=x[j]-x[i];
double diffy=y[j]-y[i];
double diffvx=vx[j]-vx[i];
double diffvy=vy[j]-vy[i];
double temp=diffx*diffvx+diffy*diffvy;
vx[i]+=diffx/d2*temp;
vy[i]+=diffy/d2*temp;
vx[j]-=diffx/d2*temp;
vy[j]-=diffy/d2*temp;
}
}
}
for(int i=0;i<size;i++){
x[i]+=dt*vx[i];
y[i]+=dt*vy[i];
}
t+=dt;
}
//calculate the difference of the two versions
double difference=0;
for (int i=0; i < size; i++){
difference+=abs(balls[i].position[0]-x[i])+abs(balls[i].position[1]-y[i]);
}
cout << "difference: " << difference << endl;
}
}
#endif /* Perfectly_Elastic_Collision_nD_correctness_check_h */
\ No newline at end of file
......@@ -177,7 +177,204 @@ namespace Perfectly_Elastic_Collision{
int cellNo=power(domainSize/g.rc,dimension);
cout << cellNo << "," << particleNo << "," << elapsed.count() << endl;
}
//Instance with not valid initial values (the particle are too close)
void perfectly_elastic_collision_2D_big_time_test_02(double domainSize){
const int dimension=2;
int paNoPerDimAndCell=3;
GlobalVariable<double> g;
g.dt=0.1;
g.endT=10;
g.t=0.0;
g.rc=0.5;
double particleSPacing=g.rc/paNoPerDimAndCell;
//particleNo=10*power(domainSize,dimension);//this keeps the particle density on average the same low density
int particleNoPerDim=paNoPerDimAndCell*domainSize/g.rc;
int particleNo=power(particleNoPerDim,dimension);
std::random_device rd;
std::mt19937 e2(0);
std::uniform_real_distribution<> rand(-0.5, 0.5);
vector<Particle<double,dimension>> balls;
balls.resize(particleNo);
for (int i=0; i<particleNo; i++){
balls[i].position=(PM_Point<double, dimension>)toVectorialIndex(i, PM_Point<int,dimension> (particleNoPerDim))*particleSPacing;
for(int j=0; j<dimension; j++){
// balls[i].position[j]=rand(e2)/;
// balls[i].position[j]=
balls[i].velocity[j]=rand(e2)/10.0;
}
}
// Init native C++ variante
double t=g.t;
double dt=g.dt;
double tend=g.endT;
double rc=g.rc;
double x[particleNo];
double y[particleNo];
double vx[particleNo];
double vy[particleNo];
for(int i=0;i<particleNo;i++){
x[i]=balls[i].position[0];
y[i]=balls[i].position[1];
vx[i]=balls[i].velocity[0];
vy[i]=balls[i].velocity[1];
}
// Time mesurment // run framework variant
Particle_Method<double, dimension> pec(g,balls);
auto start = std::chrono::high_resolution_clock::now();//time mesurment start time
pec.run();
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
int cellNo=power(domainSize/g.rc,dimension);
cout << cellNo << "," << particleNo << "," << elapsed.count() << ",";
start = std::chrono::high_resolution_clock::now();//time mesurment start time
//run native C++ variante
while(t<tend){
for(int i=0;i<particleNo;i++){
for(int j=0;j<particleNo;j++){
// double d2= (x[i]-x[j])*(x[i]-x[j])
// +(y[i]-y[j])*(y[i]-y[j]);
double diffx=x[j]-x[i];
double diffy=y[j]-y[i];
double d2=diffx*diffx+diffy*diffy;
if(d2<=rc*rc && (diffx>0.0 || (diffx==0.0 && diffy>0.0)) ){
double diffx=x[j]-x[i];
double diffy=y[j]-y[i];
double diffvx=vx[j]-vx[i];
double diffvy=vy[j]-vy[i];
double temp=diffx*diffvx+diffy*diffvy;
vx[i]+=diffx/d2*temp;
vy[i]+=diffy/d2*temp;
vx[j]-=diffx/d2*temp;
vy[j]-=diffy/d2*temp;
}
}
}
for(int i=0;i<particleNo;i++){
x[i]+=dt*vx[i];
y[i]+=dt*vy[i];
}
t+=dt;
}
finish = std::chrono::high_resolution_clock::now();
elapsed = finish - start;
cout << elapsed.count() << endl;
}
void perfectly_elastic_collision_2D_correctness_check(){
std::random_device rd;
std::mt19937 e2(0);
std::uniform_real_distribution<> rand(-0.5, 0.5);
int size=3;
vector<Particle<double,2>> balls;
balls.resize(3);
balls[0].position[0]=0.0;
balls[0].position[1]=0.0;
balls[1].position[0]=1.0;
balls[1].position[1]=0.2;
balls[2].position[0]=-0.1;
balls[2].position[1]=0.8;
balls[0].velocity[0]=0.25;
balls[0].velocity[1]=0;
balls[1].velocity[0]=-0.50;
balls[1].velocity[1]=0;
balls[2].velocity[0]=0.20;
balls[2].velocity[1]=-0.70;
GlobalVariable<double> g;
g.dt=0.1;
g.endT=10;
g.t=0.0;
g.rc=0.5;
Particle_Method<double, 2> pec(g,balls);
// Init native C++ variante
double t=g.t;
double dt=g.dt;
double tend=g.endT;
double rc=g.rc;
double x[size];
double y[size];
double vx[size];
double vy[size];
for(int i=0;i<size;i++){
x[i]=balls[i].position[0];
y[i]=balls[i].position[1];
vx[i]=balls[i].velocity[0];
vy[i]=balls[i].velocity[1];
}
// run framework variant
pec.run();
//run native C++ variante
while(t<tend){
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
double diffx=x[j]-x[i];
double diffy=y[j]-y[i];
double d2=diffx*diffx+diffy*diffy;
if(d2<=rc*rc && (diffx>0.0 || (diffx==0.0 && diffy>0.0)) ){
double diffvx=vx[j]-vx[i];
double diffvy=vy[j]-vy[i];
double temp=diffx*diffvx+diffy*diffvy;
vx[i]+=diffx/d2*temp;
vy[i]+=diffy/d2*temp;
vx[j]-=diffx/d2*temp;
vy[j]-=diffy/d2*temp;
}
}
}
for(int i=0;i<size;i++){
x[i]+=dt*vx[i];
y[i]+=dt*vy[i];
}
t+=dt;
}
//calculate the difference of the two versions
double difference=0;
for (int i=0; i < size; i++){
difference+=abs(balls[i].position[0]-x[i])+abs(balls[i].position[1]-y[i]);
}
cout << "difference: " << difference << endl;
}
}
#endif /* Perfectly_Elastic_Collision_nD_unit_test_h */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment