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); }
void MultiSmoothCircleIC::computeCircleCenters() { _centers.resize(_numbub); for (unsigned int i = 0; i < _numbub; i++) { //Vary circle center positions unsigned int num_tries = 0; Real rr = 0.0; Point newcenter = 0.0; while (rr < _bubspac && num_tries < _numtries) { num_tries++; //Moose::out<<"num_tries: "<<num_tries<<std::endl; Real ran1 = _random.rand(_tid); Real ran2 = _random.rand(_tid); Real ran3 = _random.rand(_tid); newcenter(0) = _bottom_left(0) + ran1*_range(0); newcenter(1) = _bottom_left(1) + ran2*_range(1); newcenter(2) = _bottom_left(2) + ran3*_range(2); for (unsigned int j = 0; j < i; j++) { if (j == 0) rr = _range.norm(); Real tmp_rr = _mesh.minPeriodicDistance(_var.number(), _centers[j], newcenter); if (tmp_rr < rr) rr = tmp_rr; } if (i == 0) rr = _range.norm(); } if (num_tries == _numtries) mooseError("Too many tries in MultiSmoothCircleIC"); _centers[i] = newcenter; } }
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; }
Real TwoParticleGrainsIC::value(const Point & p) { //_redius.resize(2); Real radius_left = 5.0; //_radius[0]; Real radius_right = 5.0; //_radius[1]; Point grain_center_left; grain_center_left(0) = _bottom_left(0) + _rangedomain(0)/2.0 - radius_left; grain_center_left(1) = _bottom_left(1) + _rangedomain(1)/2.0; grain_center_left(2) = _bottom_left(2) + _rangedomain(2)/2.0; Point grain_center_right; grain_center_right(0) = _bottom_left(0) + _rangedomain(0)/2.0 + radius_right; grain_center_right(1) = _bottom_left(1) + _rangedomain(1)/2.0; grain_center_right(2) = _bottom_left(2) + _rangedomain(2)/2.0; Real dist_left = (p - grain_center_left).size(); Real dist_right = (p - grain_center_right).size(); if ((dist_left <= radius_left && _op_index == 0) || (dist_right <= radius_right && _op_index == 1)) return 1.0; else return 0.0; }
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 Tricrystal2CircleGrainsIC::value(const Point & p) { Point grain_center_left; grain_center_left(0) = _bottom_left(0) + _range(0)/4.0; grain_center_left(1) = _bottom_left(1) + _range(1)/2.0; grain_center_left(2) = _bottom_left(2) + _range(2)/2.0; Point grain_center_right; grain_center_right(0) = _bottom_left(0) + _range(0)*3.0/4.0; grain_center_right(1) = _bottom_left(1) + _range(1)/2.0; grain_center_right(2) = _bottom_left(2) + _range(2)/2.0; Real radius = _range(0)/5.0; Real dist_left = (p - grain_center_left).size(); Real dist_right = (p - grain_center_right).size(); if ((dist_left <= radius && _op_index == 1) || (dist_right <= radius && _op_index == 2) || (dist_left > radius && dist_right > radius && _op_index == 0)) return 1.0; else return 0.0; }
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); }
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 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 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 MultiSmoothParticleIC::computeCircleCenters() { _centers.resize(_numbub); for (unsigned int i = 0; i < _numbub; i++) { //Vary circle center positions unsigned int num_tries = 0; Real rr = 0.0; Point newcenter = 0.0; while (rr < _bubspac && num_tries < _numtries) { num_tries++; //Moose::out<<"num_tries: "<<num_tries<<std::endl; Real ran1 = MooseRandom::rand(); Real ran2 = MooseRandom::rand(); Real ran3 = MooseRandom::rand(); newcenter(0) = _bottom_left(0) + ran1*_range(0); newcenter(1) = _bottom_left(1) + ran2*_range(1); newcenter(2) = _bottom_left(2) + ran3*_range(2); for (unsigned int j = 0; j < i; j++) { if (j == 0) rr = _range.size(); Real tmp_rr = _mesh.minPeriodicDistance(_var.number(), _centers[j], newcenter); if (tmp_rr < rr) rr = tmp_rr; } if (i == 0) rr = _range.size(); //Verify not out of bounds if (_avoid_bounds && newcenter(0) < _radii[i] + _int_width) newcenter(0) = _radii[i] + _int_width; if (_avoid_bounds && newcenter(0) > _range(0) - (_radii[i] + _int_width)) newcenter(0) = _range(0) - (_radii[i] + _int_width); if (_avoid_bounds && newcenter(1) < _radii[i] + _int_width) newcenter(1) = _radii[i] + _int_width; if (_avoid_bounds && newcenter(1) > _range(1) - (_radii[i] + _int_width)) newcenter(1) = _range(1) - (_radii[i] + _int_width); if (_range(2) != 0.0) { if (_avoid_bounds && newcenter(2) < _radii[i] + _int_width) newcenter(2) = _radii[i] + _int_width; if (_avoid_bounds && newcenter(2) > _range(2) - (_radii[i] + _int_width)) newcenter(2) = _range(2) - (_radii[i] + _int_width); } } if (num_tries == _numtries) mooseError("Too many tries in MultiSmoothParticleIC"); _centers[i] = newcenter; } }
void BimodalInverseSuperellipsoidsIC::computeSuperellipsoidCenters() { _centers.resize(_x_positions.size() + _npart); //First place the specified (large) particles from the input file for (unsigned int i = 0; i < _x_positions.size(); ++i) { _centers[i](0) = _x_positions[i]; _centers[i](1) = _y_positions[i]; _centers[i](2) = _z_positions[i]; } //Next place the randomly positioned (small) particles for (unsigned int i = _x_positions.size(); i < _x_positions.size() + _npart; i++) { unsigned int num_tries = 0; Real dsmall_min = 0.0; //minimum distance from the random particle to another random particle Real dlarge_max = 0.0; //minimum distance from the random particle to edge of the specified (large) particle Point newcenter = 0.0; while ((dsmall_min < _small_spac || dlarge_max < _large_spac) && num_tries < _numtries) { num_tries++; Real ran1 = _random.rand(_tid); Real ran2 = _random.rand(_tid); Real ran3 = _random.rand(_tid); newcenter(0) = _bottom_left(0) + ran1*_range(0); newcenter(1) = _bottom_left(1) + ran2*_range(1); newcenter(2) = _bottom_left(2) + ran3*_range(2); //First check to make sure we are INSIDE a larger particle for (unsigned int j = 0; j < _x_positions.size(); j++) { if (j == 0) dlarge_max = - _range.norm(); //Compute the distance r1 from the center of each specified superellipsoid to its outside edge //along the vector between the specified superellipsoid and the current randomly //positioned one //This uses the equation for a superellipse in polar coordinates and substitutes //distances for sin, cos functions Real dist = _mesh.minPeriodicDistance(_var.number(), _centers[j], newcenter); Point dist_vec = _mesh.minPeriodicVector(_var.number(), _centers[j], newcenter); //First calculate rmn1 = r1^(-n), replacing sin, cos functions with distances Real rmn1 = (std::pow(std::abs(dist_vec(0) / dist / _as[j]), _ns[j]) + std::pow(std::abs(dist_vec(1) / dist / _bs[j]), _ns[j]) + std::pow(std::abs(dist_vec(2) / dist / _cs[j]), _ns[j]) ); //Then calculate r1 from rmn1 Real r1 = std::pow(rmn1, (-1.0/_ns[j])); //Now calculate the distance r2 from the center of the randomly placed superellipsoid //to its outside edge in the same manner Real rmn2 = (std::pow(std::abs(dist_vec(0) / dist / _as[i]), _ns[i]) + std::pow(std::abs(dist_vec(1) / dist / _bs[i]), _ns[i]) + std::pow(std::abs(dist_vec(2) / dist / _cs[i]), _ns[i]) ); Real r2 = std::pow(rmn2, (-1.0/_ns[i])); //Calculate the distance between the edges for an interior particle Real tmp_dlarge_max = r1 - dist - r2; if (tmp_dlarge_max > dlarge_max) dlarge_max = tmp_dlarge_max; } //Then check for collisions between the randomly placed particles for (unsigned int j = _x_positions.size(); j < i; j++) { if (j == _x_positions.size()) dsmall_min = _range.norm(); Real dist = _mesh.minPeriodicDistance(_var.number(), _centers[j], newcenter); Point dist_vec = _mesh.minPeriodicVector(_var.number(), _centers[j], newcenter); Real rmn1 = (std::pow(std::abs(dist_vec(0) / dist / _as[j]), _ns[j]) + std::pow(std::abs(dist_vec(1) / dist / _bs[j]), _ns[j]) + std::pow(std::abs(dist_vec(2) / dist / _cs[j]), _ns[j]) ); Real r1 = std::pow(rmn1, (-1.0/_ns[j])); Real rmn2 = (std::pow(std::abs(dist_vec(0) / dist / _as[i]), _ns[i]) + std::pow(std::abs(dist_vec(1) / dist / _bs[i]), _ns[i]) + std::pow(std::abs(dist_vec(2) / dist / _cs[i]), _ns[i]) ); Real r2 = std::pow(rmn2, (-1.0/_ns[i])); //Calculate the distance between the edges Real tmp_dsmall_min = dist - r1 - r2; if (tmp_dsmall_min < dsmall_min) dsmall_min = tmp_dsmall_min; } //Cause while statement to exit for the first randomly placed particle if (i == _x_positions.size()) dsmall_min = _range.norm(); } if (num_tries == _numtries) mooseError("Too many tries in BimodalInverseSuperellipsoidsIC"); _centers[i] = newcenter; } }
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 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"; } } }