void PolycrystalReducedIC::initialSetup() { //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); MooseRandom::seed(_rand_seed); //Randomly generate the centers of the individual grains represented by the Voronoi tesselation _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); //Assign actual center point positions for (unsigned int grain = 0; grain < _grain_num; grain++) { for (unsigned int i = 0; i < LIBMESH_DIM; i++) _centerpoints[grain](i) = _bottom_left(i) + _range(i) * MooseRandom::rand(); if (_columnar_3D) _centerpoints[grain](2) = _bottom_left(2) + _range(2) * 0.5; } //Assign grains to specific order parameters in a way that maximizes the distance _assigned_op = PolycrystalICTools::assignPointsToVariables(_centerpoints, _op_num, _mesh, _var); }
Real RndBoundingBoxIC::value(const Point & p) { //Random number between 0 and 1 Real rand_num = MooseRandom::rand(); for (unsigned int i = 0; i < LIBMESH_DIM; ++i) if (p(i) < _bottom_left(i) || p(i) > _top_right(i)) return rand_num * _range_outvalue + _mn_outvalue; return rand_num * _range_invalue + _mn_invalue; }
void BimodalSuperellipsoidsIC::initialSetup() { // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; ++i) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_size_variation_type == 2 && _size_variation > 0.0) mooseError("If size_variation > 0.0, you must pass in a size_variation_type in " "BimodalSuperellipsoidsIC"); SmoothSuperellipsoidBaseIC::initialSetup(); }
void LatticeSmoothCircleIC::initialSetup() { // pad circles per side vector to size 3 (with 0) _circles_per_side.resize(3); //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; //Error checks if (_range(0) != 0.0 && _range(1) != 0.0 && _circles_per_side[1] == 0) mooseError("If domain is > 1D, circles_per_side must have more than one value"); if (_range(2) != 0.0 && _circles_per_side[2] == 0) mooseError("If domain is 3D, circles_per_side must have three values"); if (_range(1) == 0.0 && _range(2) == 0.0) { _circles_per_side[1] = 0; _circles_per_side[2] = 0; } //Set _numbub if (_range(2) == 0.0) { _circles_per_side[2] = 0; _numbub = _circles_per_side[0] * _circles_per_side[1]; } else _numbub = _circles_per_side[0] * _circles_per_side[1] * _circles_per_side[2]; switch (_radius_variation_type) { case 2: //No variation if (_radius_variation > 0.0) mooseError("If radius_variation > 0.0, you must pass in a radius_variation_type in LatticeSmoothCircleIC"); break; } SmoothCircleBaseIC::initialSetup(); }
void MultiSmoothCircleIC::initialSetup() { // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; ++i) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; // a variation is provided, but the type is set to 'none' if (_radius_variation > 0.0 && _radius_variation_type == 2) mooseError("If radius_variation > 0.0, you must pass in a radius_variation_type in " "MultiSmoothCircleIC"); SmoothCircleBaseIC::initialSetup(); }
Tricrystal2CircleGrainsIC::Tricrystal2CircleGrainsIC(const std::string & name, InputParameters parameters) : InitialCondition(name, parameters), _mesh(_fe_problem.mesh()), _nl(_fe_problem.getNonlinearSystem()), _op_num(getParam<unsigned int>("op_num")), _op_index(getParam<unsigned int>("op_index")) { if (_op_num != 3) mooseError("Tricrystal ICs must have op_num = 3"); //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; }
Real PFCFreezingIC::value(const Point & p) { // If out of bounds, set random value for (unsigned int i = 0; i < LIBMESH_DIM; i++) if (p(i) < _bottom_left(i) || p(i) > _top_right(i)) return _min + _val_range * MooseRandom::rand(); // If in bounds, set sinusoid IC to make atoms Real val = 0.0; if (_crystal_structure == "FCC") { // Note: this effectively (and now explicitly) returns 0.0 for FCC. return 0.0; for (unsigned int i = 0; i < _icdim; i++) val += std::cos((2.0 / _lc * p(i)) * libMesh::pi); } else { if (_icdim > 2) { for (unsigned int i = 0; i < _icdim; i++) // one mode approximation for initial condition val += (std::cos((2.0 / _lc * p(i % 3)) * libMesh::pi) * std::cos((2.0 / _lc * p((i + 1) % 3)) * libMesh::pi)) / 4.0; // Doesn't work in 2D } else { for (unsigned int i = 0; i < _icdim; i++) val *= std::cos((2.0 / _lc * p(i)) * libMesh::pi); // 2D IC for 111 plane val = val / 2.0 + 0.5; } } Real amp = _inside - _outside; val = amp * val + _outside; return val; }
void MultiSmoothCircleIC::initialSetup() { //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; switch (_radius_variation_type) { case 2: //No variation if (_radius_variation > 0.0) mooseError("If radius_variation > 0.0, you must pass in a radius_variation_type in MultiSmoothCircleIC"); break; } SmoothCircleBaseIC::initialSetup(); }
void MultiSmoothSuperellipsoidIC::initialSetup() { unsigned int nv = _numbub.size(); if (nv != _bubspac.size() || nv != _exponent.size() || nv != _semiaxis_a.size() || nv != _semiaxis_b.size() || nv != _semiaxis_c.size()) mooseError("Vectors for numbub, bubspac, exponent, semiaxis_a, semiaxis_b, and semiaxis_c must " "be the same size."); if (_semiaxis_variation_type != 2 && (nv != _semiaxis_a_variation.size() || nv != _semiaxis_b_variation.size() || nv != _semiaxis_c_variation.size())) mooseError("Vectors for numbub, semiaxis_a_variation, semiaxis_b_variation, and " "semiaxis_c_variation must be the same size."); if (_semiaxis_variation_type == 2 && (_semiaxis_a_variation.size() > 0 || _semiaxis_b_variation.size() > 0 || _semiaxis_c_variation.size() > 0)) mooseWarning( "Values were provided for semiaxis_a/b/c_variation but semiaxis_variation_type is set " "to 'none' in 'MultiSmoothSuperellipsoidIC'."); for (_gk = 0; _gk < nv; ++_gk) { // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; SmoothSuperellipsoidBaseIC::initialSetup(); } }
Real PolycrystalReducedIC::value(const Point & p) { // Assumption: We are going to assume that all variables are periodic together // _mesh.initPeriodicDistanceForVariable(_nl, _var.number()); Real min_distance = _top_right(0)*1e5; Real val = 0.0; unsigned int min_index = _grain_num + 100; //Loops through all of the grain centers and finds the center that is closest to the point p for (unsigned int grain = 0; grain < _grain_num; grain++) { Real distance = _mesh.minPeriodicDistance(_var.number(), _centerpoints[grain], p); if (min_distance > distance) { min_distance = distance; min_index = grain; } } if (min_index > _grain_num) mooseError("ERROR in PolycrystalReducedIC: didn't find minimum values"); //If the current order parameter index (_op_index) is equal to the min_index, set the value to 1.0 if (_assigned_op[min_index] == _op_index) //Make sure that the _op_index goes from 0 to _op_num-1 val = 1.0; if (val > 1.0) val = 1.0; if (val < 0.0) val = 0.0; return val; }
void PolycrystalReducedIC::initialSetup() { //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); MooseRandom::seed(_rand_seed); //Randomly generate the centers of the individual grains represented by the Voronoi tesselation _centerpoints.resize(_grain_num); std::vector<Real> distances(_grain_num); for (unsigned int grain = 0; grain < _grain_num; grain++) { for (unsigned int i = 0; i < LIBMESH_DIM; i++) _centerpoints[grain](i) = _bottom_left(i) + _range(i) * MooseRandom::rand(); if (_columnar_3D) _centerpoints[grain](2) = _bottom_left(2) + _range(2) * 0.5; } if (!_advanced_op_assignment) //Assign grains to specific order parameters in a way that maximizes the distance _assigned_op = PolycrystalICTools::assignPointsToVariables(_centerpoints, _op_num, _mesh, _var); else { std::map<dof_id_type, unsigned int> entity_to_grain; // TODO: Add a nodal option if (false) { /** * We first need to build a node to grain map (i.e. every node in the mesh needs to say * which grain it belongs to). For Voronoi, this is straightforward and we have a utility * already setup to handle this case. */ const MeshBase::node_iterator end = _mesh.getMesh().active_nodes_end(); for (MeshBase::node_iterator nl = _mesh.getMesh().active_nodes_begin(); nl != end; ++nl) { unsigned int grain_index = PolycrystalICTools::assignPointToGrain(**nl, _centerpoints, _mesh, _var, _range.norm()); entity_to_grain.insert(std::pair<dof_id_type, unsigned int>((*nl)->id(), grain_index)); } } else { const MeshBase::element_iterator end = _mesh.getMesh().active_elements_end(); for (MeshBase::element_iterator el = _mesh.getMesh().active_elements_begin(); el != end; ++el) { Point centroid = (*el)->centroid(); unsigned int grain_index = PolycrystalICTools::assignPointToGrain(centroid, _centerpoints, _mesh, _var, _range.norm()); entity_to_grain.insert(std::pair<dof_id_type, unsigned int>((*el)->id(), grain_index)); } } /** * Now we need to construct a neighbor graph using our node to grain map information. * We have a utility for this too. This one makes no assumptions about how the * grain structure was built. It uses the entity_to_grain map. */ AdjacencyGraph grain_neighbor_graph = PolycrystalICTools::buildGrainAdjacencyGraph(entity_to_grain, _mesh, _grain_num, true); /** * Now we need to assign ops in some optimal fashion. */ _assigned_op = PolycrystalICTools::assignOpsToGrains(grain_neighbor_graph, _grain_num, _op_num); } }
void PolycrystalReducedIC::initialSetup() { //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); if (_cody_test) if (_op_num != 5 || _grain_num != 10) mooseError("ERROR in PolycrystalReducedIC: Numbers aren't correct for Cody's test."); MooseRandom::seed(_rand_seed); //Randomly generate the centers of the individual grains represented by the Voronoi tesselation _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); std::vector<Point> holder; if (_cody_test) { holder.resize(_grain_num); holder[0] = Point(0.2, 0.85, 0.0); holder[1] = Point(0.5, 0.85, 0.0); holder[2] = Point(0.8, 0.85, 0.0); holder[3] = Point(0.2, 0.5, 0.0); holder[4] = Point(0.5, 0.5, 0.0); holder[5] = Point(0.8, 0.5, 0.0); holder[6] = Point(0.1, 0.1, 0.0); holder[7] = Point(0.5, 0.05, 0.0); holder[8] = Point(0.9, 0.1, 0.0); holder[9] = Point(0.5, 0.1, 0.0); } //Assign actual center point positions for (unsigned int grain = 0; grain < _grain_num; grain++) { for (unsigned int i = 0; i < LIBMESH_DIM; i++) { if (_cody_test) _centerpoints[grain](i) = _bottom_left(i) + _range(i)*holder[grain](i); else _centerpoints[grain](i) = _bottom_left(i) + _range(i)*MooseRandom::rand(); } if (_columnar_3D) _centerpoints[grain](2) = _bottom_left(2) + _range(2)*0.5; } //Assign grains to each order parameter if (_cody_test) { _assigned_op[0] = 0.0; _assigned_op[1] = 0.0; _assigned_op[2] = 0.0; _assigned_op[3] = 1.0; _assigned_op[4] = 1.0; _assigned_op[5] = 1.0; _assigned_op[6] = 2.0; _assigned_op[7] = 3.0; _assigned_op[8] = 2.0; _assigned_op[9] = 4.0; } else { for (unsigned int grain = 0; grain < _grain_num; grain++) //Assign grains to specific order parameters in a way that maximized the distance { std::vector<int> min_op_ind; std::vector<Real> min_op_dist; min_op_ind.resize(_op_num); min_op_dist.resize(_op_num); //Determine the distance to the closest center assigned to each order parameter if (grain >= _op_num) { std::fill(min_op_dist.begin() , min_op_dist.end(), _range.size()); for (unsigned int i = 0; i < grain; i++) { Real dist = _mesh.minPeriodicDistance(_var.number(), _centerpoints[grain], _centerpoints[i]); if (min_op_dist[_assigned_op[i]] > dist) { min_op_dist[_assigned_op[i]] = dist; min_op_ind[_assigned_op[i]] = i; } } } //Assign the current center point to the order parameter that is furthest away. Real mx; if (grain < _op_num) _assigned_op[grain] = grain; else { mx = 0.0; unsigned int mx_ind = 1e6; for (unsigned int i = 0; i < _op_num; i++) //Find index of max if (mx < min_op_dist[i]) { mx = min_op_dist[i]; mx_ind = i; } _assigned_op[grain] = mx_ind; } //Moose::out << "For grain " << grain << ", center point = " << _centerpoints[grain](0) << " " << _centerpoints[grain](1) << "\n"; //Moose::out << "Max index is " << _assigned_op[grain] << ", with a max distance of " << mx << "\n"; } } }
void PolycrystalReducedIC::initialSetup() { //Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); if (_cody_test) if (_op_num != 5 || _grain_num != 10) mooseError("ERROR in PolycrystalReducedIC: Numbers aren't correct for Cody's test."); MooseRandom::seed(_rand_seed); //Randomly generate the centers of the individual grains represented by the Voronoi tesselation _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); std::vector<Point> holder; if (_cody_test) { holder.resize(_grain_num); holder[0] = Point(0.2, 0.99, 0.0); holder[1] = Point(0.5, 0.99, 0.0); holder[2] = Point(0.8, 0.99, 0.0); holder[3] = Point(0.2, 0.5, 0.0); holder[4] = Point(0.5, 0.5, 0.0); holder[5] = Point(0.8, 0.5, 0.0); holder[6] = Point(0.1, 0.1, 0.0); holder[7] = Point(0.5, 0.05, 0.0); holder[8] = Point(0.9, 0.1, 0.0); holder[9] = Point(0.5, 0.1, 0.0); } //Assign actual center point positions for (unsigned int grain = 0; grain < _grain_num; grain++) { for (unsigned int i = 0; i < LIBMESH_DIM; i++) { if (_cody_test) _centerpoints[grain](i) = _bottom_left(i) + _range(i)*holder[grain](i); else _centerpoints[grain](i) = _bottom_left(i) + _range(i)*MooseRandom::rand(); } if (_columnar_3D) _centerpoints[grain](2) = _bottom_left(2) + _range(2)*0.5; } //Assign grains to each order parameter if (_cody_test) { _assigned_op[0] = 0.0; _assigned_op[1] = 0.0; _assigned_op[2] = 0.0; _assigned_op[3] = 1.0; _assigned_op[4] = 1.0; _assigned_op[5] = 1.0; _assigned_op[6] = 2.0; _assigned_op[7] = 0.0; _assigned_op[8] = 2.0; _assigned_op[9] = 4.0; } else //Assign grains to specific order parameters in a way that maximizes the distance _assigned_op = PolycrystalICTools::assignPointsToVariables(_centerpoints,_op_num, _mesh, _var); }
void HexPolycrystalIC::initialSetup() { MooseRandom::seed(_rand_seed); unsigned int root = std::floor(std::pow(_grain_num, 1.0/_mesh.dimension())); if (_grain_num != std::pow((float)root, (float)_mesh.dimension())) { root++; // Try "ceiling due to round off error if (_grain_num != std::pow((float)root, (float)_mesh.dimension())) mooseError("HexPolycrystalIC requires a square or cubic number depending on the mesh dimension"); } unsigned int third_dimension_iterations = _mesh.dimension() == 3 ? root : 1; Real ndist = 1.0/root; // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); std::vector<Point> holder(_grain_num); unsigned int count = 0; // Assign the relative center points positions, defining the grains according to a hexagonal pattern for (unsigned int k = 0; k < third_dimension_iterations; ++k) for (unsigned int j = 0; j < root; ++j) for (unsigned int i = 0; i < root; ++i) { // set x-coordinate holder[count](0) = i*ndist + (0.5*ndist*(j%2)) + _x_offset*ndist; // set y-coordinate holder[count](1) = j*ndist + (0.5*ndist*(k%2)); // set z-coordinate holder[count](2) = k*ndist; //increment counter count++; } // Assign center point values for (unsigned int grain=0; grain < _grain_num; grain++) for (unsigned int i = 0; i < LIBMESH_DIM; i++) { if (_range(i) == 0) continue; Real perturbation_dist = (_range(i)/root * (MooseRandom::rand()*2 - 1.0)) * _perturbation_percent; // Perturb -100 to 100% _centerpoints[grain](i) = _bottom_left(i) + _range(i)*holder[grain](i) + perturbation_dist; if (_centerpoints[grain](i) > _top_right(i)) _centerpoints[grain](i) = _top_right(i); if (_centerpoints[grain](i) < _bottom_left(i)) _centerpoints[grain](i) = _bottom_left(i); } //Assign grains to specific order parameters in a way that maximizes the distance _assigned_op = PolycrystalICTools::assignPointsToVariables(_centerpoints,_op_num, _mesh, _var); }
void Proc3DSCropper::sort_rotate() { float min_x = FLT_MAX, min_y = FLT_MAX, max_x = 0, max_y = 0; for(const cv::Point2f& p: this->poses) { if(p.x < min_x) min_x = p.x; if(p.x > max_x) max_x = p.x; if(p.y < min_y) min_y = p.y; if(p.y > max_y) max_y = p.y; } cv::Point2f _bot_left(min_x, max_y), _bot_right(max_x, max_y), _top_left(min_x, min_y), _top_right(max_x, min_y); cv::Point2f bot_left, bot_right, top_left, top_right; double norm_bot_left = DBL_MAX, norm_bot_right = DBL_MAX, norm_top_left = DBL_MAX, norm_top_right = DBL_MAX; for(const cv::Point2f& p: this->poses) { if(cv::norm(_bot_left - p) < norm_bot_left) { norm_bot_left = cv::norm(_bot_left - p); bot_left = p; } if(cv::norm(_bot_right - p) < norm_bot_right) { norm_bot_right = cv::norm(_bot_right - p); bot_right = p; } if(cv::norm(_top_left - p) < norm_top_left) { norm_top_left = cv::norm(_top_left - p); top_left = p; } if(cv::norm(_top_right - p) < norm_top_right) { norm_top_right = cv::norm(_top_right - p); top_right = p; } } this->corners.clear(); this->corners.push_back(bot_right); this->corners.push_back(top_right); this->corners.push_back(top_left); this->corners.push_back(bot_left); std::cout << bot_right << ", " << top_right << ", " << ", " << top_left << ", " << bot_left << std::endl; };
void HexPolycrystalIC::initialSetup() { MooseRandom::seed(_rand_seed); unsigned int root = std::floor(std::pow(_grain_num, 1.0/_mesh.dimension())); if (_grain_num != std::pow((float)root, (float)_mesh.dimension())) { root++; // Try "ceiling due to round off error if (_grain_num != std::pow((float)root, (float)_mesh.dimension())) mooseError("HexPolycrystalIC requires a square or cubic number depending on the mesh dimension"); } unsigned int third_dimension_iterations = _mesh.dimension() == 3 ? root : 1; Real ndist = 1.0/root; // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; i++) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger than the number of grains (grain_num)"); _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); std::vector<Point> holder(_grain_num); unsigned int count = 0; // Assign the relative center points positions, defining the grains according to a hexagonal pattern for (unsigned int k = 0; k < third_dimension_iterations; ++k) for (unsigned int j = 0; j < root; ++j) for (unsigned int i = 0; i < root; ++i) { // set x-coordinate holder[count](0) = i*ndist + (0.5*ndist*(j%2)) + _x_offset*ndist; // set y-coordinate holder[count](1) = j*ndist + (0.5*ndist*(k%2)); // set z-coordinate holder[count](2) = k*ndist; //increment counter count++; } // Assign center point values for (unsigned int grain=0; grain < _grain_num; grain++) for (unsigned int i = 0; i < LIBMESH_DIM; i++) { if (_range(i) == 0) continue; Real perturbation_dist = (_range(i)/root * (MooseRandom::rand()*2 - 1.0)) * _perturbation_percent; // Perturb -100 to 100% _centerpoints[grain](i) = _bottom_left(i) + _range(i)*holder[grain](i) + perturbation_dist; if (_centerpoints[grain](i) > _top_right(i)) _centerpoints[grain](i) = _top_right(i); if (_centerpoints[grain](i) < _bottom_left(i)) _centerpoints[grain](i) = _bottom_left(i); } for (unsigned int grain = 0; grain < _grain_num; grain++) //Assign grains to specific order parameters in a way that maximized the distance { std::vector<int> min_op_ind; std::vector<Real> min_op_dist; min_op_ind.resize(_op_num); min_op_dist.resize(_op_num); //Determine the distance to the closest center assigned to each order parameter if (grain >= _op_num) { std::fill(min_op_dist.begin() , min_op_dist.end(), _range.size()); for (unsigned int i = 0; i < grain; i++) { Real dist = _mesh.minPeriodicDistance(_var.number(), _centerpoints[grain], _centerpoints[i]); if (min_op_dist[_assigned_op[i]] > dist) { min_op_dist[_assigned_op[i]] = dist; min_op_ind[_assigned_op[i]] = i; } } } // Assign the current center point to the order parameter that is furthest away. Real mx; if (grain < _op_num) _assigned_op[grain] = grain; else { mx = 0.0; unsigned int mx_ind = 1e6; for (unsigned int i = 0; i < _op_num; i++) //Find index of max if (mx < min_op_dist[i]) { mx = min_op_dist[i]; mx_ind = i; } _assigned_op[grain] = mx_ind; } //Moose::out << "For grain " << grain << ", center point = " << _centerpoints[grain](0) << " " << _centerpoints[grain](1) << "\n"; //Moose::out << "Max index is " << _assigned_op[grain] << ", with a max distance of " << mx << "\n"; } }
void PolycrystalVoronoiVoidIC::computeCircleCenters() { _centers.resize(_numbub); // This Code will place void center points on grain boundaries for (unsigned int vp = 0; vp < _numbub; ++vp) { bool try_again; unsigned int num_tries = 0; do { try_again = false; num_tries++; if (num_tries > _max_num_tries) mooseError("Too many tries of assigning void centers in " "PolycrystalVoronoiVoidIC"); Point rand_point; for (unsigned int i = 0; i < LIBMESH_DIM; ++i) rand_point(i) = _bottom_left(i) + _range(i) * _random.rand(_tid); // Allow the vectors to be sorted based on their distance from the // rand_point std::vector<PolycrystalVoronoiVoidIC::DistancePoint> diff(_grain_num); for (unsigned int gr = 0; gr < _grain_num; ++gr) { diff[gr].d = _mesh.minPeriodicDistance(_var.number(), rand_point, _centerpoints[gr]); diff[gr].gr = gr; } std::sort(diff.begin(), diff.end(), _customLess); Point closest_point = _centerpoints[diff[0].gr]; Point next_closest_point = _centerpoints[diff[1].gr]; // Find Slope of Line in the plane orthogonal to the diff_centerpoint // vector Point diff_centerpoints = _mesh.minPeriodicVector(_var.number(), closest_point, next_closest_point); Point diff_rand_center = _mesh.minPeriodicVector(_var.number(), closest_point, rand_point); Point normal_vector = diff_centerpoints.cross(diff_rand_center); Point slope = normal_vector.cross(diff_centerpoints); // Midpoint position vector between two center points Point midpoint = closest_point + (0.5 * diff_centerpoints); // Solve for the scalar multiplier solution on the line Real lambda = 0; Point mid_rand_vector = _mesh.minPeriodicVector(_var.number(), midpoint, rand_point); Real slope_dot = slope * slope; mooseAssert(slope_dot > 0, "The dot product of slope with itself is zero"); for (unsigned int i = 0; i < LIBMESH_DIM; ++i) lambda += (mid_rand_vector(i) * slope(i)) / slope_dot; // Assigning points to vector _centers[vp] = slope * lambda + midpoint; // Checking to see if points are in the domain ONLY WORKS FOR PERIODIC for (unsigned int i = 0; i < LIBMESH_DIM; i++) if ((_centers[vp](i) > _top_right(i)) || (_centers[vp](i) < _bottom_left(i))) try_again = true; for (unsigned int i = 0; i < vp; ++i) { Real dist = _mesh.minPeriodicDistance(_var.number(), _centers[vp], _centers[i]); if (dist < _bubspac) try_again = true; } // Two algorithms are available for screening bubbles falling in grain // interior. They produce // nearly identical results. // Here only one is listed. The other one is available upon request. // Use circle center for checking whether voids are at GBs if (try_again == false) { Real min_rij_1, min_rij_2, rij, rij_diff_tol; min_rij_1 = _range.norm(); min_rij_2 = _range.norm(); rij_diff_tol = 0.1 * _radius; for (unsigned int gr = 0; gr < _grain_num; ++gr) { rij = _mesh.minPeriodicDistance(_var.number(), _centers[vp], _centerpoints[gr]); if (rij < min_rij_1) { min_rij_2 = min_rij_1; min_rij_1 = rij; } else if (rij < min_rij_2) min_rij_2 = rij; } if (std::abs(min_rij_1 - min_rij_2) > rij_diff_tol) try_again = true; } } while (try_again == true); } }
void HexPolycrystalIC::initialSetup() { const unsigned int root = MathUtils::round(std::pow(_grain_num, 1.0 / _dim)); // integer power the rounded root and check if we recover the grain number unsigned int grain_pow = root; for (unsigned int i = 1; i < _dim; ++i) grain_pow *= root; if (_grain_num != grain_pow) mooseError( "HexPolycrystalIC requires a square or cubic number depending on the mesh dimension"); // Set up domain bounds with mesh tools for (unsigned int i = 0; i < LIBMESH_DIM; ++i) { _bottom_left(i) = _mesh.getMinInDimension(i); _top_right(i) = _mesh.getMaxInDimension(i); } _range = _top_right - _bottom_left; if (_op_num > _grain_num) mooseError("ERROR in PolycrystalReducedIC: Number of order parameters (op_num) can't be larger " "than the number of grains (grain_num)"); _centerpoints.resize(_grain_num); _assigned_op.resize(_grain_num); std::vector<Real> distances(_grain_num); std::vector<Point> holder(_grain_num); const Real ndist = 1.0 / root; // Assign the relative center points positions, defining the grains according to a hexagonal // pattern unsigned int count = 0; for (unsigned int k = 0; k < (_dim == 3 ? root : 1); ++k) for (unsigned int j = 0; j < (_dim >= 2 ? root : 1); ++j) for (unsigned int i = 0; i < root; ++i) { // set x-coordinate holder[count](0) = i * ndist + (0.5 * ndist * (j % 2)) + _x_offset * ndist; // set y-coordinate holder[count](1) = j * ndist + (0.5 * ndist * (k % 2)); // set z-coordinate holder[count](2) = k * ndist; // increment counter count++; } // Assign center point values for (unsigned int grain = 0; grain < _grain_num; ++grain) for (unsigned int i = 0; i < LIBMESH_DIM; ++i) { if (_range(i) == 0) continue; Real perturbation_dist = (_range(i) / root * (_random.rand(_tid) * 2 - 1.0)) * _perturbation_percent; // Perturb -100 to 100% _centerpoints[grain](i) = _bottom_left(i) + _range(i) * holder[grain](i) + perturbation_dist; if (_centerpoints[grain](i) > _top_right(i)) _centerpoints[grain](i) = _top_right(i); if (_centerpoints[grain](i) < _bottom_left(i)) _centerpoints[grain](i) = _bottom_left(i); } // Assign grains to specific order parameters in a way that maximizes the distance _assigned_op = PolycrystalICTools::assignPointsToVariables(_centerpoints, _op_num, _mesh, _var); }