VEC *LTsolve(const MAT *L, const VEC *b, VEC *out, double diag) { unsigned int dim; int i, i_lim; MatrixReal **L_me, *b_ve, *out_ve, tmp, invdiag, tiny; if ( ! L || ! b ) error(E_NULL,"LTsolve"); dim = mat_min(L->m,L->n); if ( b->dim < dim ) error(E_SIZES,"LTsolve"); out = v_resize(out,L->n); L_me = L->me; b_ve = b->ve; out_ve = out->ve; tiny = (10.0/HUGE_VAL); for ( i=dim-1; i>=0; i-- ) if ( b_ve[i] != 0.0 ) break; i_lim = i; if ( b != out ) { __zero__(out_ve,out->dim); MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(MatrixReal)); } if ( diag == 0.0 ) { for ( ; i>=0; i-- ) { tmp = L_me[i][i]; if ( fabs(tmp) <= tiny*fabs(out_ve[i]) ) error(E_SING,"LTsolve"); out_ve[i] /= tmp; __mltadd__(out_ve,L_me[i],-out_ve[i],i); } } else { invdiag = 1.0/diag; for ( ; i>=0; i-- ) { out_ve[i] *= invdiag; __mltadd__(out_ve,L_me[i],-out_ve[i],i); } } return (out); }
VEC *UTsolve(const MAT *U, const VEC *b, VEC *out, double diag) { unsigned int dim, i, i_lim; MatrixReal **U_me, *b_ve, *out_ve, tmp, invdiag, tiny; if ( ! U || ! b ) error(E_NULL,"UTsolve"); dim = mat_min(U->m,U->n); if ( b->dim < dim ) error(E_SIZES,"UTsolve"); out = v_resize(out,U->n); U_me = U->me; b_ve = b->ve; out_ve = out->ve; tiny = (10.0/HUGE_VAL); for ( i=0; i<dim; i++ ) if ( b_ve[i] != 0.0 ) break; else out_ve[i] = 0.0; i_lim = i; if ( b != out ) { __zero__(out_ve,out->dim); MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]),(dim-i_lim)*sizeof(MatrixReal)); } if ( diag == 0.0 ) { for ( ; i<dim; i++ ) { tmp = U_me[i][i]; if ( fabs(tmp) <= tiny*fabs(out_ve[i]) ) error(E_SING,"UTsolve"); out_ve[i] /= tmp; __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1); } } else { invdiag = 1.0/diag; for ( ; i<dim; i++ ) { out_ve[i] *= invdiag; __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1); } } return (out); }
IGL_INLINE void igl::ears( const Eigen::MatrixBase<DerivedF> & F, Eigen::PlainObjectBase<Derivedear> & ear, Eigen::PlainObjectBase<Derivedear_opp> & ear_opp) { assert(F.cols() == 3 && "F should contain triangles"); Eigen::Array<bool,Eigen::Dynamic,3> B; { Eigen::Array<bool,Eigen::Dynamic,1> I; on_boundary(F,I,B); } find(B.rowwise().count() == 2,ear); Eigen::Array<bool,Eigen::Dynamic,3> Bear; slice(B,ear,1,Bear); Eigen::Array<bool,Eigen::Dynamic,1> M; mat_min(Bear,2,M,ear_opp); }
//-------------------------------------------------------------------------- // Function to create a multilayer system replicating a standard stack // structure cs::num_multilayers times // // |-----------------------| 1.0 |-----------------------| L2 M2 // | Material 2 | |-----------------------| // |-----------------------| 0.6 x2 | | L2 M2 // | | --> |-----------------------| L1 M1 // | Material 1 | |-----------------------| // | | | | L1 M2 // |-----------------------| 0.0 |-----------------------| // // The multilayers code divides the total system height into n multiples // of the defined material heights. //-------------------------------------------------------------------------- void generate_multilayers(std::vector<cs::catom_t>& catom_array){ // Load number of multilayer repeats to temporary constant const int num_layers = cs::num_multilayers; // Determine fractional system height for each layer const double fractional_system_height = cs::system_dimensions[2]/double(num_layers); // Unroll min, max and fill for performance std::vector<double> mat_min(mp::num_materials); std::vector<double> mat_max(mp::num_materials); std::vector<bool> mat_fill(mp::num_materials); for(int mat=0;mat<mp::num_materials;mat++){ mat_min[mat]=mp::material[mat].min; mat_max[mat]=mp::material[mat].max; // alloys generally are not defined by height, and so have max = 0.0 if(mat_max[mat]<0.0000001) mat_max[mat]=-0.1; mat_fill[mat]=mp::material[mat].fill; } // Assign materials to generated atoms for(unsigned int atom=0;atom<catom_array.size();atom++){ // loop over multilayers for(int multi=0; multi < num_layers; ++multi){ const double multilayer_num = double(multi); for(int mat=0;mat<mp::num_materials;mat++){ // determine mimimum and maximum heigh for this layer const double mat_min_z = (mat_min[mat] + multilayer_num)*fractional_system_height; const double mat_max_z = (mat_max[mat] + multilayer_num)*fractional_system_height; const double cz=catom_array[atom].z; // if in range then allocate to material if((cz>=mat_min_z) && (cz<mat_max_z) && (mat_fill[mat]==false)){ catom_array[atom].material=mat; catom_array[atom].include=true; // Optionally recategorize heigh magnetization by layer in multilayer if(cs::multilayer_height_category) catom_array[atom].lh_category = multi; } } } } return; }
VEC *Usolve(const MAT *matrix, const VEC *b, VEC *out, double diag) { unsigned int dim /* , j */; int i, i_lim; MatrixReal **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny; if ( matrix==MNULL || b==VNULL ) error(E_NULL,"Usolve"); dim = mat_min(matrix->m,matrix->n); if ( b->dim < dim ){ printf("b->dim = %d; dim = %d\n", b->dim, dim); error(E_SIZES,"Usolve"); } if ( out==VNULL || out->dim < dim ) out = v_resize(out,matrix->n); mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; tiny = (10.0/HUGE_VAL); for ( i=dim-1; i>=0; i-- ) if ( b_ent[i] != 0.0 ) break; else out_ent[i] = 0.0; i_lim = i; for ( ; i>=0; i-- ) { sum = b_ent[i]; mat_row = &(mat_ent[i][i+1]); out_col = &(out_ent[i+1]); sum -= __ip__(mat_row,out_col,i_lim-i); if ( diag==0.0 ) { if ( fabs(mat_ent[i][i]) <= tiny*fabs(sum) ) error(E_SING,"Usolve"); else out_ent[i] = sum/mat_ent[i][i]; } else out_ent[i] = sum/diag; } return (out); }
VEC *Lsolve(const MAT *matrix, const VEC *b, VEC *out, double diag) { unsigned int dim, i, i_lim /* , j */; MatrixReal **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny; if ( matrix==(MAT *)NULL || b==(VEC *)NULL ) error(E_NULL,"Lsolve"); dim = mat_min(matrix->m,matrix->n); if ( b->dim < dim ) error(E_SIZES,"Lsolve"); if ( out==(VEC *)NULL || out->dim < dim ) out = v_resize(out,matrix->n); mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve; for ( i=0; i<dim; i++ ) if ( b_ent[i] != 0.0 ) break; else out_ent[i] = 0.0; i_lim = i; tiny = (10.0/HUGE_VAL); for ( ; i<dim; i++ ) { sum = b_ent[i]; mat_row = &(mat_ent[i][i_lim]); out_col = &(out_ent[i_lim]); sum -= __ip__(mat_row,out_col,(int)(i-i_lim)); if ( diag==0.0 ) { if ( fabs(mat_ent[i][i]) <= tiny*fabs(sum) ) error(E_SING,"Lsolve"); else out_ent[i] = sum/mat_ent[i][i]; } else out_ent[i] = sum/diag; } return (out); }
VEC *Dsolve(const MAT *A, const VEC *b, VEC *x) { unsigned int dim, i; MatrixReal tiny; if ( ! A || ! b ) error(E_NULL,"Dsolve"); dim = mat_min(A->m,A->n); if ( b->dim < dim ) error(E_SIZES,"Dsolve"); x = v_resize(x,A->n); tiny = (10.0/HUGE_VAL); dim = b->dim; for ( i=0; i<dim; i++ ) if ( fabs(A->me[i][i]) <= tiny*fabs(b->ve[i]) ) error(E_SING,"Dsolve"); else x->ve[i] = b->ve[i]/A->me[i][i]; return (x); }
void sphere(std::vector<double>& particle_origin, std::vector<cs::catom_t> & catom_array, const int grain){ // Set particle radius double particle_radius_squared = (cs::particle_scale*0.5)*(cs::particle_scale*0.5); // Loop over all atoms and mark atoms in sphere const int num_atoms = catom_array.size(); // determine order for core-shell particles std::list<core_radius_t> material_order(0); for(int mat=0;mat<mp::num_materials;mat++){ core_radius_t tmp; tmp.mat=mat; tmp.radius=mp::material[mat].core_shell_size; material_order.push_back(tmp); } // sort by increasing radius material_order.sort(compare_radius); // Unroll min, max and fill for performance std::vector<double> mat_min(mp::num_materials); std::vector<double> mat_max(mp::num_materials); std::vector<double> mat_cssize(mp::num_materials); std::vector<int> uc_cat(mp::num_materials); // array of material -> unit cell material associations for(int mat=0;mat<mp::num_materials;mat++){ mat_min[mat]=create::internal::mp[mat].min*cs::system_dimensions[2]; mat_max[mat]=create::internal::mp[mat].max*cs::system_dimensions[2]; mat_cssize[mat] = mp::material[mat].core_shell_size; // alloys generally are not defined by height, and so have max = 0.0 if(mat_max[mat]<1.e-99) mat_max[mat]=-0.1; uc_cat[mat] = create::internal::mp[mat].unit_cell_category; // unit cell category of material } for(int atom=0;atom<num_atoms;atom++){ double range_squared = (catom_array[atom].x-particle_origin[0])*(catom_array[atom].x-particle_origin[0]) + (catom_array[atom].y-particle_origin[1])*(catom_array[atom].y-particle_origin[1]) + (catom_array[atom].z-particle_origin[2])*(catom_array[atom].z-particle_origin[2]); const double cz=catom_array[atom].z; const int atom_uc_cat = catom_array[atom].uc_category; if(mp::material[catom_array[atom].material].core_shell_size>0.0){ // Iterate over materials for(std::list<core_radius_t>::iterator it = material_order.begin(); it != material_order.end(); it++){ int mat = (it)->mat; double my_radius = mat_cssize[mat]; double max_range = my_radius*my_radius*particle_radius_squared; double maxz=mat_max[mat]; double minz=mat_min[mat]; // check for within core shell range if(range_squared<=max_range){ if((cz>=minz) && (cz<maxz) && (atom_uc_cat == uc_cat[mat]) ){ catom_array[atom].include=true; catom_array[atom].material=mat; catom_array[atom].grain=grain; } // if set to clear atoms then remove atoms within radius else if(cs::fill_core_shell==false){ catom_array[atom].include=false; } } } } else if(range_squared<=particle_radius_squared) { catom_array[atom].include=true; catom_array[atom].grain=grain; } } return; }
/* LUfactor -- gaussian elimination with scaled partial pivoting -- Note: returns LU matrix which is A */ MAT *LUfactor(MAT *A, PERM *pivot) { unsigned int i, j, m, n; unsigned int k, k_max; int i_max; char MatrixTempBuffer[ 1000 ]; MatrixReal **A_v, *A_piv, *A_row; MatrixReal max1, temp, tiny; VEC *scale = VNULL; if ( A==(MAT *)NULL || pivot==(PERM *)NULL ){ error(E_NULL,"LUfactor"); } if ( pivot->size != A->m ) error(E_SIZES,"LUfactor"); m = A->m; n = A->n; if( SET_VEC_SIZE( A->m ) <1000 ) vec_get( &scale, (void *)MatrixTempBuffer, A->m ); else scale = v_get( A->m ); //MEM_STAT_REG(scale,TYPE_VEC); A_v = A->me; tiny = (MatrixReal)(10.0/HUGE_VAL); /* initialise pivot with identity permutation */ for ( i=0; i<m; i++ ) pivot->pe[i] = i; /* set scale parameters */ for ( i=0; i<m; i++ ) { max1 = 0.0; for ( j=0; j<n; j++ ) { temp = (MatrixReal)fabs(A_v[i][j]); max1 = mat_max(max1,temp); } scale->ve[i] = max1; } /* main loop */ k_max = mat_min(m,n)-1; for ( k=0; k<k_max; k++ ) { /* find best pivot row */ max1 = 0.0; i_max = -1; for ( i=k; i<m; i++ ) if ( fabs(scale->ve[i]) >= tiny*fabs(A_v[i][k]) ) { temp = (MatrixReal)fabs(A_v[i][k])/scale->ve[i]; if ( temp > max1 ) { max1 = temp; i_max = i; } } /* if no pivot then ignore column k... */ if ( i_max == -1 ) { /* set pivot entry A[k][k] exactly to zero, rather than just "small" */ A_v[k][k] = 0.0; continue; } /* do we pivot ? */ if ( i_max != (int)k ) /* yes we do... */ { px_transp(pivot,i_max,k); for ( j=0; j<n; j++ ) { temp = A_v[i_max][j]; A_v[i_max][j] = A_v[k][j]; A_v[k][j] = temp; } } /* row operations */ for ( i=k+1; i<m; i++ ) /* for each row do... */ { /* Note: divide by zero should never happen */ temp = A_v[i][k] = A_v[i][k]/A_v[k][k]; A_piv = &(A_v[k][k+1]); A_row = &(A_v[i][k+1]); if ( k+1 < n ) __mltadd__(A_row,A_piv,-temp,(int)(n-(k+1))); } } if( scale != (VEC *)MatrixTempBuffer ) // память выделялась, надо освободить V_FREE(scale); return A; }
int create_crystal_structure(std::vector<cs::catom_t> & catom_array){ //---------------------------------------------------------- // check calling of routine if error checking is activated //---------------------------------------------------------- if(err::check==true){std::cout << "cs::create_crystal_structure has been called" << std::endl;} int min_bounds[3]; int max_bounds[3]; #ifdef MPICF if(vmpi::mpi_mode==0){ min_bounds[0] = int(vmpi::min_dimensions[0]/unit_cell.dimensions[0]); min_bounds[1] = int(vmpi::min_dimensions[1]/unit_cell.dimensions[1]); min_bounds[2] = int(vmpi::min_dimensions[2]/unit_cell.dimensions[2]); max_bounds[0] = vmath::iceil(vmpi::max_dimensions[0]/unit_cell.dimensions[0]); max_bounds[1] = vmath::iceil(vmpi::max_dimensions[1]/unit_cell.dimensions[1]); max_bounds[2] = vmath::iceil(vmpi::max_dimensions[2]/unit_cell.dimensions[2]); } else{ min_bounds[0]=0; min_bounds[1]=0; min_bounds[2]=0; max_bounds[0]=cs::total_num_unit_cells[0]; max_bounds[1]=cs::total_num_unit_cells[1]; max_bounds[2]=cs::total_num_unit_cells[2]; } #else min_bounds[0]=0; min_bounds[1]=0; min_bounds[2]=0; max_bounds[0]=cs::total_num_unit_cells[0]; max_bounds[1]=cs::total_num_unit_cells[1]; max_bounds[2]=cs::total_num_unit_cells[2]; #endif cs::local_num_unit_cells[0]=max_bounds[0]-min_bounds[0]; cs::local_num_unit_cells[1]=max_bounds[1]-min_bounds[1]; cs::local_num_unit_cells[2]=max_bounds[2]-min_bounds[2]; int num_atoms=cs::local_num_unit_cells[0]*cs::local_num_unit_cells[1]*cs::local_num_unit_cells[2]*unit_cell.atom.size(); // set catom_array size catom_array.reserve(num_atoms); // Initialise atoms number int atom=0; // find maximum height lh_category unsigned int maxlh=0; for(unsigned int uca=0;uca<unit_cell.atom.size();uca++) if(unit_cell.atom[uca].hc > maxlh) maxlh = unit_cell.atom[uca].hc; maxlh+=1; const double cff = 1.e-9; // Small numerical correction for atoms exactly on the borderline between processors // Duplicate unit cell for(int z=min_bounds[2];z<max_bounds[2];z++){ for(int y=min_bounds[1];y<max_bounds[1];y++){ for(int x=min_bounds[0];x<max_bounds[0];x++){ // need to change this to accept non-orthogonal lattices // Loop over atoms in unit cell for(unsigned int uca=0;uca<unit_cell.atom.size();uca++){ double cx = (double(x)+unit_cell.atom[uca].x)*unit_cell.dimensions[0]+cff; double cy = (double(y)+unit_cell.atom[uca].y)*unit_cell.dimensions[1]+cff; double cz = (double(z)+unit_cell.atom[uca].z)*unit_cell.dimensions[2]+cff; #ifdef MPICF if(vmpi::mpi_mode==0){ // only generate atoms within allowed dimensions if( (cx>=vmpi::min_dimensions[0] && cx<vmpi::max_dimensions[0]) && (cy>=vmpi::min_dimensions[1] && cy<vmpi::max_dimensions[1]) && (cz>=vmpi::min_dimensions[2] && cz<vmpi::max_dimensions[2])){ #endif if((cx<cs::system_dimensions[0]) && (cy<cs::system_dimensions[1]) && (cz<cs::system_dimensions[2])){ catom_array.push_back(cs::catom_t()); catom_array[atom].x=cx; catom_array[atom].y=cy; catom_array[atom].z=cz; //std::cout << atom << "\t" << cx << "\t" << cy <<"\t" << cz << std::endl; catom_array[atom].material=unit_cell.atom[uca].mat; catom_array[atom].uc_id=uca; catom_array[atom].lh_category=unit_cell.atom[uca].hc+z*maxlh; catom_array[atom].uc_category=unit_cell.atom[uca].lc; catom_array[atom].scx=x; catom_array[atom].scy=y; catom_array[atom].scz=z; atom++; } #ifdef MPICF } } else{ if((cx<cs::system_dimensions[0]) && (cy<cs::system_dimensions[1]) && (cz<cs::system_dimensions[2])){ catom_array.push_back(cs::catom_t()); catom_array[atom].x=cx; catom_array[atom].y=cy; catom_array[atom].z=cz; catom_array[atom].material=unit_cell.atom[uca].mat; catom_array[atom].uc_id=uca; catom_array[atom].lh_category=unit_cell.atom[uca].hc+z*maxlh; catom_array[atom].uc_category=unit_cell.atom[uca].lc; catom_array[atom].scx=x; catom_array[atom].scy=y; catom_array[atom].scz=z; catom_array[atom].include=false; // assume no atoms until classification complete atom++; } } #endif } } } } // Check to see if actual and expected number of atoms agree, if not trim the excess if(atom!=num_atoms){ std::vector<cs::catom_t> tmp_catom_array(num_atoms); tmp_catom_array=catom_array; catom_array.resize(atom); for(int a=0;a<atom;a++){ catom_array[a]=tmp_catom_array[a]; } tmp_catom_array.resize(0); } // If z-height material selection is enabled then do so if(cs::SelectMaterialByZHeight==true){ // Check for interfacial roughness and call custom material assignment routine if(cs::interfacial_roughness==true) cs::roughness(catom_array); // Check for multilayer system and if required generate multilayers else if(cs::multilayers) cs::generate_multilayers(catom_array); // Otherwise perform normal assignement of materials else{ // determine z-bounds for materials std::vector<double> mat_min(mp::num_materials); std::vector<double> mat_max(mp::num_materials); std::vector<bool> mat_fill(mp::num_materials); // Unroll min, max and fill for performance for(int mat=0;mat<mp::num_materials;mat++){ mat_min[mat]=mp::material[mat].min*cs::system_dimensions[2]; mat_max[mat]=mp::material[mat].max*cs::system_dimensions[2]; // alloys generally are not defined by height, and so have max = 0.0 if(mat_max[mat]<0.0000001) mat_max[mat]=-0.1; mat_fill[mat]=mp::material[mat].fill; } // Assign materials to generated atoms for(unsigned int atom=0;atom<catom_array.size();atom++){ for(int mat=0;mat<mp::num_materials;mat++){ const double cz=catom_array[atom].z; if((cz>=mat_min[mat]) && (cz<mat_max[mat]) && (mat_fill[mat]==false)){ catom_array[atom].material=mat; catom_array[atom].include=true; } } } } // Delete unneeded atoms clear_atoms(catom_array); } // Check to see if any atoms have been generated if(atom==0){ terminaltextcolor(RED); std::cout << "Error - no atoms have been generated, increase system dimensions!" << std::endl; terminaltextcolor(WHITE); zlog << zTs() << "Error: No atoms have been generated. Increase system dimensions." << std::endl; err::vexit(); } // Now unselect all atoms by default for particle shape cutting for(unsigned int atom=0;atom<catom_array.size();atom++){ catom_array[atom].include=false; } return EXIT_SUCCESS; }