HE_Mesh::HE_Mesh(FVMesh& mesh) : Mesh(nullptr) { for (int vIdx = 0 ; vIdx < mesh.vertices.size() ; vIdx++) { vertices.push_back(HE_Vertex(mesh.vertices[vIdx].p, -1)); } for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; HE_Face heFace; HE_Edge edge0(fvFace.vertex_index[0], fIdx); // vertices in face are ordered counter-clockwise HE_Edge edge1(fvFace.vertex_index[1], fIdx); HE_Edge edge2(fvFace.vertex_index[2], fIdx); int newEdgeIndex = edges.size(); vertices[ fvFace.vertex_index[0] ].someEdge_idx = newEdgeIndex+0; // overwrites existing data, if present vertices[ fvFace.vertex_index[1] ].someEdge_idx = newEdgeIndex+1; vertices[ fvFace.vertex_index[2] ].someEdge_idx = newEdgeIndex+2; edge0.next_edge_idx = newEdgeIndex+1; edge1.next_edge_idx = newEdgeIndex+2; edge2.next_edge_idx = newEdgeIndex+0; edges.push_back(edge0); edges.push_back(edge1); edges.push_back(edge2); heFace.edge_idx[0] = newEdgeIndex+0; heFace.edge_idx[1] = newEdgeIndex+1; heFace.edge_idx[2] = newEdgeIndex+2; faces.push_back(heFace); } // connect half-edges: bool faceEdgeIsConnected[mesh.faces.size()][3] = {}; // initialize all as false // for each edge of each face : if it doesn't have a converse then find the converse in the edges of the opposite face for (int fIdx = 0 ; fIdx < mesh.faces.size() ; fIdx++) { FVMeshFace& fvFace = mesh.faces[fIdx]; //FVMeshFaceHandle fh(mesh, fIdx); HE_FaceHandle fnew(*this, fIdx); // face index on FVMesh corresponds to index in HE_Mesh // HE_EdgeHandle edge = fnew.edge0(); // HE_EdgeHandle edgeStart = edge; // do // for (int eIdx = 0; eIdx < 3; eIdx++) { if (faceEdgeIsConnected[fIdx][eIdx]) { // edge.next(); continue; } int edge_idx = faces[fIdx].edge_idx[eIdx]; HE_Edge& edge = edges[ edge_idx ]; int face2 = fvFace.connected_face_index[eIdx]; // connected_face X is connected via vertex X and vertex X+1 if (face2 < 0) { atlas::logError("Incorrect model: disconnected faces. Support generation aborted.\n"); exit(1); // TODO: not exit, but continue without support! } for (int e2 = 0; e2 < 3; e2++) { if (mesh.faces[face2].vertex_index[e2] == edges[edge.next_edge_idx].from_vert_idx) { edges[ faces[face2].edge_idx[e2] ].converse_edge_idx = edge_idx; edge.converse_edge_idx = faces[face2].edge_idx[e2]; faceEdgeIsConnected[face2][e2] = true; // the other way around doesn't have to be set; we will not pass the same edge twice break; } if (e2 == 2) std::cerr << "Couldn't find converse of edge " << std::to_string(edge_idx) <<"!!!!!" << std::endl; } //edge = edge.next(); } //while (edge != edgeStart) } HE_MESH_DEBUG_DO( mesh.debugOutputWholeMesh(); ) }
void bee_colony::evolve(population &pop) const { // Let's store some useful variables. const problem::base &prob = pop.problem(); const problem::base::size_type prob_i_dimension = prob.get_i_dimension(), D = prob.get_dimension(), Dc = D - prob_i_dimension, prob_c_dimension = prob.get_c_dimension(); const decision_vector &lb = prob.get_lb(), &ub = prob.get_ub(); const population::size_type NP = (int) pop.size(); //We perform some checks to determine wether the problem/population are suitable for ABC if ( Dc == 0 ) { pagmo_throw(value_error,"There is no continuous part in the problem decision vector for ABC to optimise"); } if ( prob.get_f_dimension() != 1 ) { pagmo_throw(value_error,"The problem is not single objective and ABC is not suitable to solve it"); } if ( prob_c_dimension != 0 ) { pagmo_throw(value_error,"The problem is not box constrained and ABC is not suitable to solve it"); } if (NP < 2) { pagmo_throw(value_error,"for ABC at least 2 individuals in the population are needed"); } // Get out if there is nothing to do. if (m_iter == 0) { return; } // Some vectors used during evolution are allocated here. fitness_vector fnew(prob.get_f_dimension()); decision_vector dummy(D,0); //used for initialisation purposes std::vector<decision_vector > X(NP,dummy); //set of food sources std::vector<fitness_vector> fit(NP); //food sources fitness decision_vector temp_solution(D,0); std::vector<int> trial(NP,0); std::vector<double> probability(NP); population::size_type neighbour = 0; decision_vector::size_type param2change = 0; std::vector<double> selectionfitness(NP), cumsum(NP), cumsumTemp(NP); std::vector <population::size_type> selection(NP); double r = 0; // Copy the food sources position and their fitness for ( population::size_type i = 0; i<NP; i++ ) { X[i] = pop.get_individual(i).cur_x; fit[i] = pop.get_individual(i).cur_f; } // Main ABC loop for (int j = 0; j < m_iter; ++j) { //1- Send employed bees for (population::size_type ii = 0; ii< NP; ++ii) { //selects a random component (only of the continuous part) of the decision vector param2change = boost::uniform_int<decision_vector::size_type>(0,Dc-1)(m_urng); //randomly chose a solution to be used to produce a mutant solution of solution ii //randomly selected solution must be different from ii do{ neighbour = boost::uniform_int<population::size_type>(0,NP-1)(m_urng); } while(neighbour == ii); //copy local solution into temp_solution (the whole decision_vector, also the integer part) for(population::size_type i=0; i<D; ++i) { temp_solution[i] = X[ii][i]; } //mutate temp_solution temp_solution[param2change] = X[ii][param2change] + boost::uniform_real<double>(-1,1)(m_drng) * (X[ii][param2change] - X[neighbour][param2change]); //if generated parameter value is out of boundaries, it is shifted onto the boundaries*/ if (temp_solution[param2change]<lb[param2change]) { temp_solution[param2change] = lb[param2change]; } if (temp_solution[param2change]>ub[param2change]) { temp_solution[param2change] = ub[param2change]; } //Calling void prob.objfun(fitness_vector,decision_vector) is more efficient as no memory allocation occur //A call to fitness_vector prob.objfun(decision_vector) allocates memory for the return value. prob.objfun(fnew,temp_solution); //If the new solution is better than the old one replace it with the mutant one and reset its trial counter if(prob.compare_fitness(fnew, fit[ii])) { X[ii][param2change] = temp_solution[param2change]; pop.set_x(ii,X[ii]); prob.objfun(fit[ii], X[ii]); //update the fitness vector trial[ii] = 0; } else { trial[ii]++; //if the solution can't be improved incrase its trial counter } } //End of loop on the population members //2 - Send onlooker bees //We scale all fitness values from 0 (worst) to absolute value of the best fitness fitness_vector worstfit=fit[0]; for (pagmo::population::size_type i = 1; i < NP;i++) { if (prob.compare_fitness(worstfit,fit[i])) worstfit=fit[i]; } for (pagmo::population::size_type i = 0; i < NP; i++) { selectionfitness[i] = fabs(worstfit[0] - fit[i][0]) + 1.; } // We build and normalise the cumulative sum cumsumTemp[0] = selectionfitness[0]; for (pagmo::population::size_type i = 1; i< NP; i++) { cumsumTemp[i] = cumsumTemp[i - 1] + selectionfitness[i]; } for (pagmo::population::size_type i = 0; i < NP; i++) { cumsum[i] = cumsumTemp[i]/cumsumTemp[NP-1]; } for (pagmo::population::size_type i = 0; i < NP; i++) { r = m_drng(); for (pagmo::population::size_type j = 0; j < NP; j++) { if (cumsum[j] > r) { selection[i]=j; break; } } } for(pagmo::population::size_type t = 0; t < NP; ++t) { r = m_drng(); pagmo::population::size_type ii = selection[t]; //selects a random component (only of the continuous part) of the decision vector param2change = boost::uniform_int<decision_vector::size_type>(0,Dc-1)(m_urng); //randomly chose a solution to be used to produce a mutant solution of solution ii //randomly selected solution must be different from ii do{ neighbour = boost::uniform_int<population::size_type>(0,NP-1)(m_urng); } while(neighbour == ii); //copy local solution into temp_solution (also integer part) for(population::size_type i=0; i<D; ++i) { temp_solution[i] = X[ii][i]; } //mutate temp_solution temp_solution[param2change] = X[ii][param2change] + boost::uniform_real<double>(-1,1)(m_drng) * (X[ii][param2change] - X[neighbour][param2change]); /*if generated parameter value is out of boundaries, it is shifted onto the boundaries*/ if (temp_solution[param2change]<lb[param2change]) { temp_solution[param2change] = lb[param2change]; } if (temp_solution[param2change]>ub[param2change]) { temp_solution[param2change] = ub[param2change]; } //Calling void prob.objfun(fitness_vector,decision_vector) is more efficient as no memory allocation occur //A call to fitness_vector prob.objfun(decision_vector) allocates memory for the return value. prob.objfun(fnew,temp_solution); //If the new solution is better than the old one replace it with the mutant one and reset its trial counter if(prob.compare_fitness(fnew, fit[ii])) { X[ii][param2change] = temp_solution[param2change]; pop.set_x(ii,X[ii]); prob.objfun(fit[ii], X[ii]); //update the fitness vector trial[ii] = 0; } else { trial[ii]++; //if the solution can't be improved incrase its trial counter } } //3 - Send scout bees int maxtrialindex = 0; for (population::size_type ii=1; ii<NP; ++ii) { if (trial[ii] > trial[maxtrialindex]) { maxtrialindex = ii; } } if(trial[maxtrialindex] >= m_limit) { //select a new random solution for(problem::base::size_type jj = 0; jj < Dc; ++jj) { X[maxtrialindex][jj] = boost::uniform_real<double>(lb[jj],ub[jj])(m_drng); } trial[maxtrialindex] = 0; pop.set_x(maxtrialindex,X[maxtrialindex]); } } // end of main ABC loop }
//--------------------------------------------------------- int main(int argc, char **argv) { TPS<double> rbf; Polinomio<double> pol; Matrix<double> A,B; Vector<double> x,y,f; Vector<double> lambda,b; Vector<double> xnew,ynew,fnew; double c=0.01; int n,ni,m; //make the data in the square [0,1] x [0,1] make_data(0,1,0,1, 21, 21, x, y, ni, n); //stablish the exponent in: r^beta log(r) rbf.set_beta(4); //configure the associate polynomial // pol.make( data_dimension, degree_pol) pol.make(2 , rbf.get_degree_pol()); //show the rbf and pol info cout<<rbf; cout<<pol; //show the number of nodes cout<<endl; cout<<"total nodes N = "<<n<<endl; cout<<"interior nodes ni = "<<ni<<endl; cout<<"boundary nodes nf = "<<n-ni<<endl; cout<<endl; //get the number of elements in the polynomial base m = pol.get_M(); //resize the matrices to store the partial derivatives A.Resize(n+m,n+m); A = 0.0; B.Resize(n+m,n+m); B = 0.0; //Recall that this problem has the general form // (Uxx+Uyy) (Pxx+Pyy) = f interior nodes 0..ni // U P_b = g boundary nodes ni..n // P^transpose 0 = 0 momentun conditions in P // // P is the polynomial wit size n x m // P_b is the polynomial working in the boundary nodes, size nf x m // Pxx+Pyy has size ni x m //make the matriz derivatives fill_matrix( "dxx" , rbf , pol , c , x , y, 0 , ni , A); fill_matrix( "dyy" , rbf , pol , c , x , y, 0 , ni , B); A = A + B; // A <- Uxx + Uyy //Add the submatriz for the boundary nodes: U , P_b boundary nodes ni..n fill_matrix( "normal" , rbf , pol , c , x , y, ni, n , A); //Add the submatriz P^transpose at the end: P^transpose fill_matrix( "pol_trans" , rbf , pol , c , x , y, n , n+m, A); //resize the vector to store the right_size of the PDE b.Resize(n+m); b = 0.0; //fill with f for(int i=0;i<ni;i++) b(i) = right_side(x(i), y(i)); //fill with the boundary condition for(int i=ni;i<n;i++) b(i) = boundary_condition(x(i),y(i)); //solve the linear system of equations lambda = gauss(A,b); //make the new data grid int ni2,n2; make_data(0,1,0,1, 41, 41, xnew, ynew, ni2, n2); //interpolate on this new data grid (xnew,ynew) fnew = interpolate(rbf,pol,c,lambda,x,y,xnew,ynew); //determine the maximum error double e=0.0; for(int i=0;i<ni2;i++) { e = max(e, fabs(fnew(i) - sin(2*M_PI*xnew(i))*cos(2*M_PI*ynew(i))) ); } //show the error cout<<endl; cout<<"The maximum error: e_max = "<<e<<endl<<endl; //store the interpolated data save_gnu_data("data",xnew,ynew,fnew); return 0; }