#include "system.h" #include #include #include #include #include "voro++.hh" #include "string.h" #include #include using namespace voro; //----------------------------------------------------- // Constructor, Destructor and Access functions //----------------------------------------------------- System::System(){ nop = 0; ghost_nop = 0; real_nop = 0; triclinic = 0; usecells = 0; filter = 0; maxclusterid = -1; alpha = 1; voronoiused = 0; solidq = 6; criteria = 0; comparecriteria = 0; neighbordistance = 0; //set box with zeros for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ box[i][j] = 0.0; } } } System::~System(){ } //----------------------------------------------------- // Simulation box related methods //----------------------------------------------------- void System::assign_triclinic_params(vector> drot, vector> drotinv){ for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ rot[i][j] = drot[i][j]; rotinv[i][j] = drotinv[i][j]; } } triclinic = 1; } vector> System::get_triclinic_params(){ vector> drot; vector dummydrot; for(int i=0; i<3; i++){ dummydrot.clear(); for(int j=0; j<3; j++){ dummydrot.emplace_back(rot[i][j]); } drot.emplace_back(dummydrot); } return drot; } void System::sbox(vector> boxd) { //this method will be redone to get a 3x3 box //always. They will be then translated to the //corresponding other boxes double isum; for(int i=0; i<3; i++){ isum = 0; for(int j=0; j<3; j++){ box[i][j] = boxd[i][j]; isum += boxd[i][j]*boxd[i][j]; } boxdims[i][0] = 0; boxdims[i][1] = sqrt(isum); } boxx = boxdims[0][1] - boxdims[0][0]; boxy = boxdims[1][1] - boxdims[1][0]; boxz = boxdims[2][1] - boxdims[2][0]; } vector> System::gbox(){ vector> qres; vector qd; for(int i=0;i<3;i++){ qd.clear(); for(int j=0;j<3;j++){ qd.emplace_back(box[i][j]); } qres.emplace_back(qd); } return qres; } //----------------------------------------------------- // Atom related methods //----------------------------------------------------- //this function allows for handling custom formats of atoms and so on void System::set_atoms( vector atomitos){ atoms.clear(); nop = atomitos.size(); atoms.reserve(nop); atoms.assign(atomitos.begin(), atomitos.end()); //now assign ghost and real atoms int tg = 0; int tl = 0; for(int i=0; i System::get_atoms( ){ //here, we have to filter ghost atoms vector retatoms; for(int i=0; i atomitos){ //check for ghost atoms int tg = 0; int tl = 0; for(int i=0; i0){ //now the atoms need to be reordered vector real_atoms; vector ghost_atoms; for(int i=0; i System::get_all_atoms( ){ //here, we have to filter ghost atoms vector retatoms; for(int i=0; i boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; //now divide by box vals - scale down the size diffx = diffx/boxx; diffy = diffy/boxy; diffz = diffz/boxz; //now transform back to normal system ax = rot[0][0]*diffx + rot[0][1]*diffy + rot[0][2]*diffz; ay = rot[1][0]*diffx + rot[1][1]*diffy + rot[1][2]*diffz; az = rot[2][0]*diffx + rot[2][1]*diffy + rot[2][2]*diffz; //now assign to diffs and calculate distnace diffx = ax; diffy = ay; diffz = az; //finally distance abs = sqrt(diffx*diffx + diffy*diffy + diffz*diffz); } else{ //nearest image if (diffx> boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; abs = sqrt(diffx*diffx + diffy*diffy + diffz*diffz); } return abs; } //function for binding double System::get_abs_distance(Atom atom1 , Atom atom2 ){ double abs, ax, ay, az; double diffx = atom1.posx - atom2.posx; double diffy = atom1.posy - atom2.posy; double diffz = atom1.posz - atom2.posz; if (triclinic == 1){ //convert to the triclinic system ax = rotinv[0][0]*diffx + rotinv[0][1]*diffy + rotinv[0][2]*diffz; ay = rotinv[1][0]*diffx + rotinv[1][1]*diffy + rotinv[1][2]*diffz; az = rotinv[2][0]*diffx + rotinv[2][1]*diffy + rotinv[2][2]*diffz; //scale to match the triclinic box size diffx = ax*boxx; diffy = ay*boxy; diffz = az*boxz; //now check pbc //nearest image if (diffx> boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; //now divide by box vals - scale down the size diffx = diffx/boxx; diffy = diffy/boxy; diffz = diffz/boxz; //now transform back to normal system ax = rot[0][0]*diffx + rot[0][1]*diffy + rot[0][2]*diffz; ay = rot[1][0]*diffx + rot[1][1]*diffy + rot[1][2]*diffz; az = rot[2][0]*diffx + rot[2][1]*diffy + rot[2][2]*diffz; //now assign to diffs and calculate distnace diffx = ax; diffy = ay; diffz = az; //finally distance abs = sqrt(diffx*diffx + diffy*diffy + diffz*diffz); } else{ //nearest image if (diffx> boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; abs = sqrt(diffx*diffx + diffy*diffy + diffz*diffz); } return abs; } //function for binding vector System::get_distance_vector(Atom atom1 , Atom atom2 ){ double ax, ay, az; double diffx = atom1.posx - atom2.posx; double diffy = atom1.posy - atom2.posy; double diffz = atom1.posz - atom2.posz; if (triclinic == 1){ //convert to the triclinic system ax = rotinv[0][0]*diffx + rotinv[0][1]*diffy + rotinv[0][2]*diffz; ay = rotinv[1][0]*diffx + rotinv[1][1]*diffy + rotinv[1][2]*diffz; az = rotinv[2][0]*diffx + rotinv[2][1]*diffy + rotinv[2][2]*diffz; double dummy; //scale to match the triclinic box size diffx = ax*boxx; diffy = ay*boxy; diffz = az*boxz; //now check pbc //nearest image if (diffx> boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; //now divide by box vals - scale down the size diffx = diffx/boxx; diffy = diffy/boxy; diffz = diffz/boxz; //now transform back to normal system ax = rot[0][0]*diffx + rot[0][1]*diffy + rot[0][2]*diffz; ay = rot[1][0]*diffx + rot[1][1]*diffy + rot[1][2]*diffz; az = rot[2][0]*diffx + rot[2][1]*diffy + rot[2][2]*diffz; //now assign to diffs and calculate distnace diffx = ax; diffy = ay; diffz = az; } else{ //nearest image if (diffx> boxx/2.0) {diffx-=boxx;}; if (diffx<-boxx/2.0) {diffx+=boxx;}; if (diffy> boxy/2.0) {diffy-=boxy;}; if (diffy<-boxy/2.0) {diffy+=boxy;}; if (diffz> boxz/2.0) {diffz-=boxz;}; if (diffz<-boxz/2.0) {diffz+=boxz;}; } vector abs; abs.emplace_back(diffx); abs.emplace_back(diffy); abs.emplace_back(diffz); return abs; } void System::reset_all_neighbors(){ for (int ti = 0;ti System::get_pairdistances(){ vector res; double d; double diffx,diffy,diffz; for (int ti=0; ti cc; //find of all find the number of cells in each direction nx = boxx/neighbordistance; ny = boxy/neighbordistance; nz = boxz/neighbordistance; //now use this to find length of cell in each direction double lx = boxx/nx; double ly = boxy/ny; double lz = boxz/nz; //find the total number of cells total_cells = nx*ny*nz; //create a vector of cells cells = new cell[total_cells]; //now run over and for each cell create its neighbor cells //all neighbor cells are also added for(int i=0; i= boxx) dx-=boxx; if (dy < 0) dy+=boxy; else if (dy >= boxy) dy-=boxy; if (dz < 0) dz+=boxz; else if (dz >= boxz) dz-=boxz; //now find c vals cx = dx/lx; cy = dy/ly; cz = dz/lz; //now get cell index ind = cell_index(cx, cy, cz); //got cell index //now add the atom to the corresponding cells cells[ind].members.emplace_back(ti); } //end of loop - all cells, the member atoms and neighboring cells are added } vector System::remap_atom(vector pos){ //remap atom position into the box //now apply boxdims double dx = pos[0]; double dy = pos[1]; double dz = pos[2]; double ax, ay, az; if (triclinic == 1){ //convert to the triclinic system ax = rotinv[0][0]*dx + rotinv[0][1]*dy + rotinv[0][2]*dz; ay = rotinv[1][0]*dx + rotinv[1][1]*dy + rotinv[1][2]*dz; az = rotinv[2][0]*dx + rotinv[2][1]*dy + rotinv[2][2]*dz; //scale to match the triclinic box size dx = ax*boxx; dy = ay*boxy; dz = az*boxz; //now check pbc //nearest image if (dx> boxx/2.0) {dx-=boxx;}; if (dx<-boxx/2.0) {dx+=boxx;}; if (dy> boxy/2.0) {dy-=boxy;}; if (dy<-boxy/2.0) {dy+=boxy;}; if (dz> boxz/2.0) {dz-=boxz;}; if (dz<-boxz/2.0) {dz+=boxz;}; //now divide by box vals - scale down the size dx = dx/boxx; dy = dy/boxy; dz = dz/boxz; //now transform back to normal system ax = rot[0][0]*dx + rot[0][1]*dy + rot[0][2]*dz; ay = rot[1][0]*dx + rot[1][1]*dy + rot[1][2]*dz; az = rot[2][0]*dx + rot[2][1]*dy + rot[2][2]*dz; //now assign to diffs and calculate distnace dx = ax; dy = ay; dz = az; } else{ if (dx < 0) dx+=boxx; else if (dx >= boxx) dx-=boxx; if (dy < 0) dy+=boxy; else if (dy >= boxy) dy-=boxy; if (dz < 0) dz+=boxz; else if (dz >= boxz) dz-=boxz; } vector rpos; rpos.emplace_back(dx); rpos.emplace_back(dy); rpos.emplace_back(dz); return rpos; } vector System::cell_periodic(int i, int j, int k){ vector ci; //apply periodic conditions if (i<0) i = i + nx; else if (i>nx-1) i = i -nx; ci.emplace_back(i); if (j<0) j = j + ny; else if (j>ny-1) j = j -ny; ci.emplace_back(j); if (k<0) k = k + nz; else if (k>nz-1) k = k -nz; ci.emplace_back(k); return ci; } //get all neighbor info but using cell lists void System::get_all_neighbors_cells(){ voronoiused = 0; double d; double diffx,diffy,diffz; double r,theta,phi; int ti, tj; //first create cells set_up_cells(); int maincell, subcell; //now loop to find distance for(int i=0; i members/compare with tj = cells[subcell].members[mj]; //compare ti and tj and add if (ti < tj){ d = get_abs_distance(ti,tj,diffx,diffy,diffz); if (d < neighbordistance){ if ((filter == 1) && (atoms[ti].type != atoms[tj].type)){ continue; } else if ((filter == 2) && (atoms[ti].type == atoms[tj].type)){ continue; } //process_neighbor(ti, tj); atoms[ti].neighbors[atoms[ti].n_neighbors] = tj; atoms[ti].neighbordist[atoms[ti].n_neighbors] = d; //weight is set to 1.0, unless manually reset atoms[ti].neighborweight[atoms[ti].n_neighbors] = 1.00; atoms[ti].n_diffx[atoms[ti].n_neighbors] = diffx; atoms[ti].n_diffy[atoms[ti].n_neighbors] = diffy; atoms[ti].n_diffz[atoms[ti].n_neighbors] = diffz; convert_to_spherical_coordinates(diffx, diffy, diffz, r, phi, theta); atoms[ti].n_r[atoms[ti].n_neighbors] = r; atoms[ti].n_phi[atoms[ti].n_neighbors] = phi; atoms[ti].n_theta[atoms[ti].n_neighbors] = theta; atoms[ti].n_neighbors += 1; atoms[ti].cutoff = neighbordistance; atoms[tj].neighbors[atoms[tj].n_neighbors] = ti; atoms[tj].neighbordist[atoms[tj].n_neighbors] = d; //weight is set to 1.0, unless manually reset atoms[tj].neighborweight[atoms[tj].n_neighbors] = 1.00; atoms[tj].n_diffx[atoms[tj].n_neighbors] = -diffx; atoms[tj].n_diffy[atoms[tj].n_neighbors] = -diffy; atoms[tj].n_diffz[atoms[tj].n_neighbors] = -diffz; convert_to_spherical_coordinates(-diffx, -diffy, -diffz, r, phi, theta); atoms[tj].n_r[atoms[tj].n_neighbors] = r; atoms[tj].n_phi[atoms[tj].n_neighbors] = phi; atoms[tj].n_theta[atoms[tj].n_neighbors] = theta; atoms[tj].n_neighbors +=1; atoms[tj].cutoff = neighbordistance; } } } } } } } void System::get_all_neighbors_normal(){ //reset voronoi flag voronoiused = 0; double d; double diffx,diffy,diffz; double r,theta,phi; for (int ti=0; ti members/compare with tj = cells[subcell].members[mj]; //compare ti and tj and add if (ti < tj){ d = get_abs_distance(ti,tj,diffx,diffy,diffz); if (d < neighbordistance){ datom x = {d, tj}; atoms[ti].temp_neighbors.emplace_back(x); datom y = {d, ti}; atoms[tj].temp_neighbors.emplace_back(y); } } } } } } } int System::get_all_neighbors_bynumber(double prefactor, int nns, int assign){ /* A new neighbor algorithm that finds a specified number of neighbors for each atom. But ONLY TEMP neighbors */ //reset voronoi flag voronoiused = 0; double d, dcut; double diffx,diffy,diffz; double r,theta,phi; int m, maxneighs, finished; finished = 1; vector nids; vector dists, sorted_dists; //double prefactor = 1.21; double summ; double boxvol; //some guesswork here //find the box volumes if (triclinic==1){ double a1, a2, a3, b1, b2, b3, c1, c2, c3; //rot is the cell vectors transposed a1 = rot[0][0]; a2 = rot[1][0]; a3 = rot[2][0]; b1 = rot[0][1]; b2 = rot[1][1]; b3 = rot[2][1]; c1 = rot[0][2]; c2 = rot[1][2]; c3 = rot[2][2]; boxvol = c1*(a2*b3-a3*b2) - c2*(a1*b3-b1*a3) + c3*(a1*b2-a2*b1); } else{ boxvol = boxx*boxy*boxz; } //now find the volume per particle double guessvol = boxvol/float(nop); //guess the side of a cube that is occupied by an atom - this is a guess distance double guessdist = cbrt(guessvol); //now add some safe padding - this is the prefactor which we will read in guessdist = prefactor*guessdist; neighbordistance = guessdist; if (usecells){ get_temp_neighbors_cells(); } else{ get_temp_neighbors_brute(); } for (int ti=0; ti 11){ double ssum = 0; for(int i=0 ; i<12; i++){ ssum += atoms[ti].temp_neighbors[i].dist; } //process sum atoms[ti].lcutsmall = 1.2071*ssum/12; //now assign neighbors based on this for(int i=0 ; i 13){ double ssum = 0; for(int i=0 ; i<8; i++){ ssum += 1.1547*atoms[ti].temp_neighbors[i].dist; } for(int i=8 ; i<14; i++){ ssum += atoms[ti].temp_neighbors[i].dist; } atoms[ti].lcutlarge = 1.2071*ssum/14; //now assign neighbors based on this for(int i=0 ; i nids; vector dists, sorted_dists; //double prefactor = 1.21; double summ; double boxvol; //some guesswork here //find the box volumes if (triclinic==1){ double a1, a2, a3, b1, b2, b3, c1, c2, c3; //rot is the cell vectors transposed a1 = rot[0][0]; a2 = rot[1][0]; a3 = rot[2][0]; b1 = rot[0][1]; b2 = rot[1][1]; b3 = rot[2][1]; c1 = rot[0][2]; c2 = rot[1][2]; c3 = rot[2][2]; boxvol = c1*(a2*b3-a3*b2) - c2*(a1*b3-b1*a3) + c3*(a1*b2-a2*b1); } else{ boxvol = boxx*boxy*boxz; } //now find the volume per particle double guessvol = boxvol/float(nop); //guess the side of a cube that is occupied by an atom - this is a guess distance double guessdist = cbrt(guessvol); //now add some safe padding - this is the prefactor which we will read in guessdist = prefactor*guessdist; neighbordistance = guessdist; if (usecells){ get_temp_neighbors_cells(); } else{ get_temp_neighbors_brute(); } for (int ti=0; ti= atoms[ti].temp_neighbors[m].dist)){ //increase m m = m+1; //here now we can add this to the list neighbors and process things int tj = atoms[ti].temp_neighbors[m].index; process_neighbor(ti, tj); //find new dcut summ = summ + atoms[ti].temp_neighbors[m].dist; dcut = summ/float(m-2); atoms[ti].cutoff = dcut; } //find if there was an error if (m==maxneighs){ finished = 0; break; } else{ finished = 1; } } return finished; } int System::get_all_neighbors_adaptive(double prefactor, int nlimit, double padding){ double d, dcut; double diffx,diffy,diffz; double r,theta,phi; int m, maxneighs, finished; double summ; double boxvol; //some guesswork here //find the box volumes if (triclinic==1){ double a1, a2, a3, b1, b2, b3, c1, c2, c3; //rot is the cell vectors transposed a1 = rot[0][0]; a2 = rot[1][0]; a3 = rot[2][0]; b1 = rot[0][1]; b2 = rot[1][1]; b3 = rot[2][1]; c1 = rot[0][2]; c2 = rot[1][2]; c3 = rot[2][2]; boxvol = c1*(a2*b3-a3*b2) - c2*(a1*b3-b1*a3) + c3*(a1*b2-a2*b1); } else{ boxvol = boxx*boxy*boxz; } //now find the volume per particle double guessvol = boxvol/float(nop); //guess the side of a cube that is occupied by an atom - this is a guess distance double guessdist = cbrt(guessvol); //now add some safe padding - this is the prefactor which we will read in guessdist = prefactor*guessdist; neighbordistance = guessdist; //introduce cell lists here - instead of looping over all neighbors //use cells if (usecells){ get_temp_neighbors_cells(); } else{ get_temp_neighbors_brute(); } //end of callstructural competition //subatoms would now be populated //now starts the main loop for (int ti=0; ti qs){ lenqs = qs.size(); reqdqs = new int[lenqs]; for(int i=0;i qs){ lenaqs = qs.size(); reqdaqs = new int[lenaqs]; for(int i=0;i l || fabs(x) > 1.0) cerr << "impossible combination of l and m" << "\n"; pmm=1.0; if (m > 0){ somx2=sqrt((1.0-x)*(1.0+x)); fact=1.0; for (i=1;i<=m;i++){ pmm *= -fact*somx2; fact += 2.0; } } if (l == m) return pmm; else{ pmmp1=x*(2*m+1)*pmm; if (l == (m+1)) return pmmp1; else{ for (ll=m+2;ll<=l;ll++){ pll=(x*(2*ll-1)*pmmp1-(ll+m-1)*pmm)/(ll-m); pmm=pmmp1; pmmp1=pll; } return pll; } } } void System::convert_to_spherical_coordinates(double x, double y, double z, double &r, double &phi, double &theta){ r = sqrt(x*x+y*y+z*z); theta = acos(z/r); phi = atan2(y,x); } void System::YLM(int l, int m, double theta, double phi, double &realYLM, double &imgYLM){ double factor; double m_PLM; m_PLM = PLM(l,m,cos(theta)); factor = ((2.0*double(l) + 1.0)/ (4.0*PI))*dfactorial(l,m); realYLM = sqrt(factor) * m_PLM * cos(double(m)*phi); imgYLM = sqrt(factor) * m_PLM * sin(double(m)*phi); } void System::QLM(int l,int m,double theta,double phi,double &realYLM, double &imgYLM ){ realYLM = 0.0; imgYLM = 0.0; if (m < 0) { YLM(l, abs(m), theta, phi, realYLM, imgYLM); realYLM = pow(-1.0,m)*realYLM; imgYLM = pow(-1.0,m)*imgYLM; } else{ YLM(l, m, theta, phi, realYLM, imgYLM); } } void System::calculate_complexQLM_6(){ //nn = number of neighbors int nn; double realti,imgti; double realYLM,imgYLM; // nop = parameter.nop; for (int ti= 0;ti qs){ //set_reqd_qs(qs); //nn = number of neighbors int nn; double realti,imgti; double realYLM,imgYLM; int q; double summ; //first make space in atoms for the number of qs needed - assign with null values /* for(int ti=0;ti qs){ //nn = number of neighbors int nn; double realti,imgti; //double realYLM,imgYLM; int q; double summ; int nns; //if (!qsfound) { calculate_q(qs); } //note that the qvals will be in -2 pos //q2 will be in q0 pos and so on // nop = parameter.nop; for (int ti= 0;ti System::gqvals(int qq){ vector qres; qres.reserve(real_nop); for(int i=0;i System::gaqvals(int qq){ vector qres; qres.reserve(real_nop); for(int i=0;i threshold) frenkelcons += 1; else if (scalar < threshold) frenkelcons += 1; atoms[ti].avq6q6 += scalar; } atoms[ti].frenkelnumber = frenkelcons; atoms[ti].avq6q6 /= atoms[ti].n_neighbors; } } void System::find_solid_atoms(){ int tfrac; if (criteria == 0){ for (int ti= 0;ti minfrenkel) && (atoms[ti].avq6q6 > avgthreshold) ); else atoms[ti].issolid = ( (atoms[ti].frenkelnumber > minfrenkel) && (atoms[ti].avq6q6 < avgthreshold) ); } } else if (criteria == 1){ for (int ti= 0;ti minfrenkel); if (comparecriteria == 0) atoms[ti].issolid = (tfrac && (atoms[ti].avq6q6 > avgthreshold)); else atoms[ti].issolid = (tfrac && (atoms[ti].avq6q6 < avgthreshold)); } } } void System::find_clusters(double clustercutoff){ //Clustering methods should only run over real atoms if (clustercutoff != 0){ for(int ti=0; timax){ max=freq[ti]; maxclusterid = ti+1; } } get_largest_cluster_atoms(); return max; } void System::get_largest_cluster_atoms(){ for(int ti=0; ti neigh,f_vert, vert_nos; vector facearea, v, faceperimeters; voronoicell_neighbor c; vector< vector > nweights; vector< vector > nneighs; vector idss; //vector nvector; double weightsum; vector pos; //pre_container pcon(boxdims[0][0],boxdims[1][1],boxdims[1][0],boxdims[1][1],boxdims[2][0],boxdims[2][1],true,true,true); pre_container pcon(0.00, boxx, 0.00, boxy, 0.0, boxz, true, true, true); for(int i=0; i dummyweights; vector dummyneighs; //only loop over neighbors weightsum = 0.0; for (int i=0; i temp; int li=0; for(int vi=si*3; vi<(si*3+3); vi++){ temp.emplace_back(v[vi]+pos[li]); li++; } atoms[ti].vertex_positions.emplace_back(temp); } //assign to the atom //atoms[ti].vorovector = nvector; //only loop over neighbors //weightsum = 0.0; //for (int i=0; i