@@ -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
0 commit comments