Skip to content

Commit 92ab428

Browse files
Some improvements
Change the output result: output the aggregate files of all levels at once. Change the output result: the user can specify the number of aggregates produced by a single execution (using different random seeds). Improve reliability: Internal tests algorithm for non-overlapping and attached conditions are improved.
1 parent de13678 commit 92ab428

File tree

7 files changed

+126
-98
lines changed

7 files changed

+126
-98
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required (VERSION 3.10.0)
22
set(CMAKE_CXX_COMPILER "g++")
33
set(CMAKE_CXX_FLAGS "-O3 -fopenmp -DNDEBUG -DEIGEN_NO_DEBUG")
4-
include_directories(/mnt/c/Users/moteki/WSL_Share_Ubuntu1804/C++/eigen_3_3_5)
4+
include_directories(~/C++/eigen_3_3_5)
55

66
project(aggregate_gen)
77

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
---
33

44
### History:
5+
#### Oct 23, 2019:
6+
* Change the output result: output the aggregate files of all levels at once.
7+
* Change the output result: the user can specify the number of aggreagtes produced by a single execution (using different random seeds).
8+
* Improve reliability: Internal tests algorithm for non-overlapping and attached conditions are improved.
9+
510
#### Aug 14, 2018:
611
* Bugfix: An algorithm error causing the partial overlapping between some spherules has been fixed.
712
* Improve reliability: Internal tests of non-overlapping and attached conditions are added.
@@ -43,12 +48,13 @@
4348
levels : Number of hierarchical levels in cluster-cluster aggregation (10).
4449
kf : Fractal prefactor (1.0).
4550
Df : Fractal dimension (2.5).
51+
num_agg : Number of aggregates generated using different random seeds.
4652
4753
If you skip the [parameter_list], the code uses the default values in the parenthesis. Total number of spherules is *N* = num_sph_SA*2<sup>levels</sup>.
4854
```
4955

5056
### Output data
51-
The result is written in a text file "agg_N???_kf???_Df???.out", where the three strings ??? indicate the total number of spherules *N*, the fractal prefactor *kf*, and the fractal dimension *Df*.
57+
The result is written in a text file "agg???_N???_kf???_Df???.out", where the three strings ??? indicate the aggregate id number (0 ~ num_agg), total number of spherules *N*, the fractal prefactor *kf*, and the fractal dimension *Df*, respectively.
5258

5359
In this file, each row shows the cartesian coordinate "x y z" of each spherules relative to the centroid of cluster, where the
5460
length is scaled such that spherule radius is 1.0.

aggregate_gen_CCA.cpp

Lines changed: 72 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,39 @@ using namespace std;
1212

1313

1414
//return pos_sph matrix
15-
MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& levels, const float& kf, const float& Df, const float& tol){
15+
vector<MatrixXd> aggregate_gen_CCA(const double& a, const int& num_sph_SA, const int& levels, const double& kf, const double& Df, const double& tol){
16+
17+
vector<MatrixXd> pos_sph_agg_output; // vector of aggregate geometry from level 0 to "levels".
1618
int iter1max {1000};
1719
int iter2max {10000};
1820

1921
int num_SA_agg= pow(2,levels);
20-
int totnum_sph= num_SA_agg*num_sph_SA;
21-
cout << "totnum_sph= " << totnum_sph << endl;
22+
int final_totnum_sph= num_SA_agg*num_sph_SA;
23+
cout << "final totnum_sph= " << final_totnum_sph << endl;
2224

23-
vector<MatrixXf> pos_sph_SAagg;
25+
vector<MatrixXd> pos_sph_SAagg;
2426
for(int i= 0; i<num_SA_agg; ++i ) pos_sph_SAagg.push_back(aggregate_gen_SA(a,num_sph_SA,kf,Df,tol));
2527

26-
vector<MatrixXf> pos_sph_agg_old;
28+
pos_sph_agg_output.push_back(pos_sph_SAagg[0]); // level 0 aggregate
29+
30+
31+
vector<MatrixXd> pos_sph_agg_old;
2732

2833
// start time
2934
chrono::time_point<chrono::steady_clock> CCA_start_time= chrono::steady_clock::now();
3035

3136
for(int k= 1; k <= levels; ++k){
3237
cout << "Generating aggregates in " << k << "th level ... please wait ..." << endl;
33-
vector<MatrixXf> pos_sph_agg;
38+
vector<MatrixXd> pos_sph_agg;
3439

3540
for(int L= 1; L <= pow(2,levels-k); ++L){
3641
//cout << "generating " << L << " th " << "aggregate in level" << k << endl;
3742
int N1= num_sph_SA*pow(2,k-1);
3843
int N2= N1;
3944

4045
// aggregation process in k-th level
41-
MatrixXf pos_sph_agg1(3,N1);
42-
MatrixXf pos_sph_agg2(3,N2);
46+
MatrixXd pos_sph_agg1(3,N1);
47+
MatrixXd pos_sph_agg2(3,N2);
4348

4449
if(k==1){
4550
pos_sph_agg1= pos_sph_SAagg[2*L-2];
@@ -50,27 +55,27 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
5055
}
5156

5257
// random rotation of aggregate 1 around the centroid (origin)
53-
float theta,phi; // polar angles
58+
double theta,phi; // polar angles
5459
theta= acos(2.0f*urf(re)-1.0f);
5560
phi= 2*M_PI*urf(re);
5661

57-
Vector3f nvec; // unit vector of rotation axis
62+
Vector3d nvec; // unit vector of rotation axis
5863
nvec << sin(theta)*cos(phi),sin(theta)*sin(phi),cos(theta); //axis of rotation randomly choosen over unit sphere
5964

60-
float psi; // angle of rotation
65+
double psi; // angle of rotation
6166
psi= 2*M_PI*urf(re); // randomly choosen rotation angle
6267

63-
Matrix3f rot_mat; // 3D rotation matrix
64-
rot_mat= AngleAxisf(psi,nvec);
68+
Matrix3d rot_mat; // 3D rotation matrix
69+
rot_mat= AngleAxisd(psi,nvec);
6570

6671
for(int i= 0; i < pos_sph_agg1.cols(); ++i) pos_sph_agg1.col(i)=rot_mat*pos_sph_agg1.col(i); // random rotation of agg1
6772

68-
float R1_2; // square of gyration radius of agg1
69-
float R2_2; // square of gyration radius of agg2
73+
double R1_2; // square of gyration radius of agg1
74+
double R2_2; // square of gyration radius of agg2
7075
R1_2= a*a + pos_sph_agg1.colwise().squaredNorm().mean();
7176
R2_2= a*a + pos_sph_agg2.colwise().squaredNorm().mean();
7277

73-
float rN;
78+
double rN;
7479
rN= a*a*(N1+N2)*(N1+N2)/(N1*N2)*pow((N1+N2)/kf,2/Df)-(N1+N2)/N2*R1_2-(N1+N2)/N1*R2_2;
7580
rN= sqrt(rN);
7681

@@ -81,26 +86,22 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
8186

8287
pos_sph_agg1.colwise() -= pos_sph_agg1.rowwise().mean(); // translate the centroid of agg1 to origin
8388

84-
float phi;
89+
double phi;
8590
phi= 2*M_PI*urf(re);
86-
float u; // uniform random number [-1.0,1.0)
87-
u= 2*urf(re)-1.0f;
91+
double u; // uniform random number [-1.0,1.0)
92+
u= 2*urf(re)-1.0;
8893

89-
Vector3f cen_pos_agg1; // centroid of agg1
90-
cen_pos_agg1 << sqrt(1.0f-u*u)*cos(phi), sqrt(1.0f-u*u)*sin(phi), u;
94+
Vector3d cen_pos_agg1; // centroid of agg1
95+
cen_pos_agg1 << sqrt(1.0-u*u)*cos(phi), sqrt(1.0-u*u)*sin(phi), u;
9196
cen_pos_agg1 *= rN; // cen_pos_agg1 is set to a uniform random cartesian position (x,y,z) over the spherical surface of radius rN
9297
pos_sph_agg1.colwise() += cen_pos_agg1;
9398

94-
95-
float theta;
96-
theta= acos(2.0f*urf(re)-1.0f);
99+
double theta;
100+
theta= acos(2.0*urf(re)-1.0);
97101
phi= 2*M_PI*urf(re);
98-
Vector3f nvec; // unit vector of rotation axis
102+
Vector3d nvec; // unit vector of rotation axis
99103
nvec << sin(theta)*cos(phi),sin(theta)*sin(phi),cos(theta); //axis of rotation randomly choosen over unit sphere
100104

101-
102-
103-
104105
// random rotation of aggregate 2 around the centroid (origin)
105106
#pragma omp parallel for
106107
for(int iter2= 0; iter2 < iter2max; ++iter2){
@@ -109,31 +110,31 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
109110
found_local= found;
110111
if(found) continue;
111112

112-
MatrixXf pos_sph_agg1_thread(3,N1); // thread local copy of pos_sph_agg1
113-
MatrixXf pos_sph_agg2_thread(3,N2); // thread local copy of pos_sph_agg2
113+
MatrixXd pos_sph_agg1_thread(3,N1); // thread local copy of pos_sph_agg1
114+
MatrixXd pos_sph_agg2_thread(3,N2); // thread local copy of pos_sph_agg2
114115
pos_sph_agg1_thread= pos_sph_agg1;
115116
pos_sph_agg2_thread= pos_sph_agg2;
116117

117-
float psi; // angle of rotation
118+
double psi; // angle of rotation
118119

119120
#pragma omp critical
120121
{
121122
psi= 2*M_PI*urf(re);
122123
}
123124

124-
Matrix3f rot_mat; // 3D rotation matrix
125-
rot_mat= AngleAxisf(psi,nvec);
125+
Matrix3d rot_mat; // 3D rotation matrix
126+
rot_mat= AngleAxisd(psi,nvec);
126127
for(int i= 0; i < N2; ++i) pos_sph_agg2_thread.col(i)=rot_mat*pos_sph_agg2_thread.col(i); // random rotation of agg2
127128
// cout << "iter2 pos_sph_agg2 " << endl << pos_sph_agg2 << endl;
128129

129130
bool attached {false};
130131
for(int i= 0; i < N2; ++i){
131-
RowVectorXf dist_pair(N1);
132+
RowVectorXd dist_pair(N1);
132133
dist_pair=(pos_sph_agg1_thread.colwise()-pos_sph_agg2_thread.col(i)).colwise().norm();
133134
// cout << "dist_pair" << endl << dist_pair << endl;
134-
float mindist= dist_pair.minCoeff();
135+
double mindist= dist_pair.minCoeff();
135136
//cout << "2*a, mindist " << 2*a << ' ' << mindist << endl;
136-
bool overrapped {mindist <= (2*a-tol)};
137+
bool overrapped {mindist <= 2*a};
137138
if(overrapped) {
138139
//exit; // 20180813 removed
139140
attached= false; // 20180813 added
@@ -146,7 +147,7 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
146147
// construction of new aggregate if attached condition is satisfied
147148
if(attached){
148149
//cout << "attached " << attached << endl;
149-
MatrixXf pos_sph_agg_tmp(3,N1+N2);
150+
MatrixXd pos_sph_agg_tmp(3,N1+N2);
150151
pos_sph_agg_tmp.block(0,0,3,N1)= pos_sph_agg1_thread;
151152
pos_sph_agg_tmp.block(0,N1,3,N2)= pos_sph_agg2_thread;
152153
pos_sph_agg_tmp.colwise() -= pos_sph_agg_tmp.rowwise().mean(); // translate the centroid of new agg to origin
@@ -171,6 +172,7 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
171172
}// L loop
172173

173174
pos_sph_agg_old= move(pos_sph_agg);
175+
pos_sph_agg_output.push_back(pos_sph_agg_old[0]);
174176

175177
}// k loop
176178

@@ -179,37 +181,43 @@ MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& lev
179181
cout << "CCA computation time: "
180182
<< chrono::duration_cast<chrono::milliseconds>(CCA_end_time - CCA_start_time).count() << " milliseconds" << endl;
181183

182-
MatrixXf pos_sph_agg_final;
183-
pos_sph_agg_final = pos_sph_agg_old[0];
184-
185-
assert(totnum_sph == pos_sph_agg_final.cols());
186-
187-
// final check of the attached condition
188-
double buf_factor= 5.0; //buffer factor of torelance
189-
bool non_overlapped;
190-
ArrayXf min_diff_from2a(totnum_sph);
191-
for(int i= 0; i< totnum_sph; ++i){
192-
ArrayXf distance_from_this_sph(totnum_sph);
193-
distance_from_this_sph= (pos_sph_agg_final.colwise()-pos_sph_agg_final.col(i)).colwise().norm().array();
194-
non_overlapped= {(distance_from_this_sph-(2*a-buf_factor*tol) > 0)(i) == false};
195-
for(int j= 0; j< totnum_sph; ++j){
196-
if(j != i) {
197-
non_overlapped= non_overlapped && ((distance_from_this_sph-(2*a-buf_factor*tol) > 0)(j) == true);
184+
// geometry check for output
185+
bool non_overlapped_all {true};
186+
bool attached_at_least_1pair_all {true};
187+
188+
for(int k= 0; k <= levels; ++k){
189+
MatrixXd pos_sph_agg_k_out {pos_sph_agg_output[k]};
190+
int num_sph = num_sph_SA*pow(2,k);
191+
assert(num_sph == pos_sph_agg_k_out.cols());
192+
// final check of the attached condition
193+
bool non_overlapped;
194+
ArrayXd min_diff_from2a(num_sph);
195+
for(int i= 0; i< num_sph; ++i){
196+
ArrayXd distance_from_this_sph(num_sph);
197+
distance_from_this_sph= (pos_sph_agg_k_out.colwise()-pos_sph_agg_k_out.col(i)).colwise().norm().array();
198+
non_overlapped= {(distance_from_this_sph-2*a >= 0)(i) == false};
199+
for(int j= 0; j< num_sph; ++j){
200+
if(j != i) {
201+
non_overlapped= non_overlapped && ((distance_from_this_sph-2*a > 0)(j) == true);
202+
}
198203
}
204+
//cout << i << ", " << (distance_from_this_sph-(2*a-buf_factor*tol) >= 0).transpose() << endl ;
205+
min_diff_from2a(i)=((pos_sph_agg_k_out.colwise()-pos_sph_agg_k_out.col(i)).colwise().norm().array()-2*a).array().abs().minCoeff();
199206
}
200-
//cout << i << ", " << (distance_from_this_sph-(2*a-buf_factor*tol) >= 0).transpose() << endl ;
201-
min_diff_from2a(i)=((pos_sph_agg_final.colwise()-pos_sph_agg_final.col(i)).colwise().norm().array()-2*a).array().abs().minCoeff();
207+
bool attached_at_least_1pair {min_diff_from2a.maxCoeff() < tol};
208+
string non_overlapped_test= {non_overlapped ? "Success" : "Failed"};
209+
string attached_at_least_1pair_test= {attached_at_least_1pair ? "Success" : "Failed"};
210+
cout << k << "th level, non_overlapped_check : " << non_overlapped_test << endl;
211+
cout << k << "th level, attached_at_least_1pair_check: " << attached_at_least_1pair_test << endl;
212+
213+
non_overlapped_all = non_overlapped_all && non_overlapped;
214+
attached_at_least_1pair_all = attached_at_least_1pair_all && attached_at_least_1pair;
202215
}
203-
bool attached_at_least_1pair {min_diff_from2a.maxCoeff() < buf_factor*tol};
204-
205-
string non_overlapped_test= {non_overlapped ? "Success" : "Failed"};
206-
string attached_at_least_1pair_test= {attached_at_least_1pair ? "Success" : "Failed"};
207-
cout << "non_overlapped_check: " << non_overlapped_test << endl;
208-
cout << "attached_at_least_1pair_check: " << attached_at_least_1pair_test << endl;
209-
if(non_overlapped && attached_at_least_1pair){
210-
return pos_sph_agg_final;
216+
217+
if(non_overlapped_all && attached_at_least_1pair_all){
218+
return pos_sph_agg_output;
211219
}else{
212-
cout << "Geometry check failed! Please try other (kf, Df) pair." << endl;
220+
cout << "Geometry check failed! Please change tol." << endl;
213221
exit(1);
214222
}
215223

aggregate_gen_CCA.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

22
extern std::default_random_engine re;
3-
extern std::uniform_real_distribution<float> urf;
3+
extern std::uniform_real_distribution<double> urf;
44

5-
Eigen::MatrixXf aggregate_gen_CCA(const float& a, const int& num_sph_SA, const int& levels, const float& kf, const float& Df, const float& tol);
5+
std::vector<Eigen::MatrixXd> aggregate_gen_CCA(const double& a, const int& num_sph_SA, const int& levels, const double& kf, const double& Df, const double& tol);

aggregate_gen_SA.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ using namespace Eigen;
66
using namespace std;
77

88
//return pos_sph matrix
9-
MatrixXf aggregate_gen_SA(const float& a, const int& num_sph, const float& kf, const float& Df, const float& tol){
10-
MatrixXf pos_sph= MatrixXf::Zero(3,num_sph);
9+
MatrixXd aggregate_gen_SA(const double& a, const int& num_sph, const double& kf, const double& Df, const double& tol){
10+
MatrixXd pos_sph= MatrixXd::Zero(3,num_sph);
1111
pos_sph.col(0) << -a,0,0;
1212
pos_sph.col(1) << a,0,0;
1313

14-
Vector3f pos_cand(3);
15-
float rN;
16-
float phi;
17-
float u;
18-
ArrayXf dist_sph;
14+
Vector3d pos_cand(3);
15+
double rN;
16+
double phi;
17+
double u;
18+
ArrayXd dist_sph;
1919

2020
for(int N=3; N <= num_sph; ++N){
2121
rN= N*N*a*a/(N-1)*pow(N/kf,2/Df)-N*a*a/(N-1)-N*a*a*pow((N-1)/kf,2/Df);
@@ -32,7 +32,7 @@ MatrixXf aggregate_gen_SA(const float& a, const int& num_sph, const float& kf, c
3232
dist_sph(i)=(pos_sph.col(i)-pos_cand).norm();
3333
}
3434

35-
if(dist_sph.minCoeff() < 2*a+tol && dist_sph.minCoeff() > 2*a-tol){
35+
if(dist_sph.minCoeff() < 2*a+tol && dist_sph.minCoeff() > 2*a){
3636
pos_sph.col(N-1)= pos_cand;
3737
pos_sph.colwise() -= pos_sph.rowwise().mean(); // translate the centroid to origin
3838
break;
@@ -41,7 +41,7 @@ MatrixXf aggregate_gen_SA(const float& a, const int& num_sph, const float& kf, c
4141
}
4242

4343
// final check of the attached condition
44-
ArrayXf mindist_c(num_sph);
44+
ArrayXd mindist_c(num_sph);
4545
for(int i= 0; i< num_sph; ++i){
4646
mindist_c(i)=((pos_sph.colwise()-pos_sph.col(i)).colwise().norm().array()-2*a).array().abs().minCoeff();
4747
}

aggregate_gen_SA.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

22
extern std::default_random_engine re;
3-
extern std::uniform_real_distribution<float> urf;
3+
extern std::uniform_real_distribution<double> urf;
44

5-
Eigen::MatrixXf aggregate_gen_SA(const float& a, const int& num_sph, const float& kf, const float& Df, const float& tol);
5+
Eigen::MatrixXd aggregate_gen_SA(const double& a, const int& num_sph, const double& kf, const double& Df, const double& tol);

0 commit comments

Comments
 (0)