/** * @brief Clones this Universe and all of the Cells within it and returns it * @return a pointer to the Universe clone */ Universe* Universe::clone() { log_printf(DEBUG, "Cloning Universe %d", _id); /* Instantiate new Universe clone */ Universe* clone = new Universe(universe_id()); /* Loop over Cells in Universe and clone each one */ std::map<int, Cell*>::iterator iter1; for (iter1 = _cells.begin(); iter1 != _cells.end(); ++iter1) { /* If the Cell is filled with a Material, clone it */ if ((*iter1).second->getType() == MATERIAL) { /* Clone the Cell */ CellBasic* parent = static_cast<CellBasic*>((*iter1).second); CellBasic* cell_clone = parent->clone(); /* Add Cell clone to the list */ clone->addCell(cell_clone); cell_clone->setUniverse(clone->getId()); } /* Throw error message if Cell is FILL type */ else { log_printf(ERROR, "Unable to clone Universe %d since it contains Cell %d" "which is filled with a Universe rather than a Material"); } } return clone; }
/** * @brief Subdivides all of the Cells within this Universe into rings * and angular sectors. */ void Universe::subdivideCells() { log_printf(DEBUG, "Subdividing Cells for Universe %d", _id); std::map<int, Cell*>::iterator iter1; while (iter1 != _cells.end()) { for (iter1 = _cells.begin(); iter1 != _cells.end(); ++iter1) { if ((*iter1).second->getType() == MATERIAL) { CellBasic* cell = static_cast<CellBasic*>((*iter1).second); if (cell->getNumRings() > 0 || cell->getNumSectors() > 0) { std::vector<CellBasic*> newcells = cell->subdivideCell(); log_printf(DEBUG, "Cell %d in Universe %d has %d subcells", cell->getId(), _id, newcells.size()); std::vector<CellBasic*>::iterator iter2; for (iter2=newcells.begin(); iter2!=newcells.end(); ++iter2) addCell((*iter2)); _cells.erase(iter1); break; } } } } }
/** * @brief Returns a CellBasic in this Universe. * @param cell_id the integer the cell_id * @return Returns the CellFill pointer. */ CellBasic* Universe::getCellBasic(int cell_id) { CellBasic* cell = NULL; if (_cells.find(cell_id) == _cells.end()) log_printf(ERROR, "Unable to return Cell with ID = %d from Universe with " "ID = %d since the it does not contain this Cell", cell_id, _id); cell = static_cast<CellBasic*>(_cells.at(cell_id)); if (cell->getType() != MATERIAL) log_printf(WARNING, "Retrieving Cell %d from Universe %d, but it " "is not a MATERIAL type Cell", cell->getId(), _id); return cell; }
/** * @brief Subdivides the Cell into clones for fuel pin rings. */ void CellBasic::ringify() { /* If the user didn't request any rings, don't make any */ if (_num_rings == 0) return; int num_circles = 0; Circle* circle1 = NULL; Circle* circle2 = NULL; double radius1 = 0; double radius2 = 0; double x1 = 0.; double y1 = 0.; double x2 = 0.; double y2 = 0.; int halfspace1 = 0; int halfspace2 = 0; std::vector<Circle*> circles; /* See if the Cell contains 1 or 2 CIRCLE Surfaces */ std::map<int, surface_halfspace>::iterator iter1; for (iter1=_surfaces.begin(); iter1 != _surfaces.end(); ++iter1) { /* Determine if any of the Surfaces is a Circle */ if (iter1->second._surface->getSurfaceType() == CIRCLE) { int halfspace = iter1->second._halfspace; Circle* circle = static_cast<Circle*>(iter1->second._surface); /* Outermost bounding Circle */ if (halfspace == -1) { halfspace1 = halfspace; circle1 = circle; radius1 = circle1->getRadius(); x1 = circle1->getX0(); y1 = circle1->getY0(); } /* Innermost bounding circle */ else if (halfspace == +1) { halfspace2 = halfspace; circle2 = circle; radius2 = circle2->getRadius(); x2 = circle2->getX0(); y2 = circle2->getY0(); } num_circles++; } } /* Error checking */ if (num_circles == 0) log_printf(ERROR, "Unable to ringify Cell %d since it does not " "contain any CIRCLE type Surface(s)", _id); if (num_circles > 2) log_printf(NORMAL, "Unable to ringify Cell %d since it " "contains more than 2 CIRCLE Surfaces", _id); if (x1 != x2 && num_circles == 2) log_printf(ERROR, "Unable to ringify Cell %d since it contains " "Circle %d centered at x=%f and Circle %d at x=%f. " "Both Circles must have the same center.", _id, circle1->getId(), x1, circle2->getId(), x2); if (y1 != y2 && num_circles == 2) log_printf(ERROR, "Unable to ringify Cell %d since it contains " "Circle %d centered at y=%f and Circle %d at y=%f. " "Both Circles must have the same center.", _id, circle1->getId(), y1, circle2->getId(), y2); if (circle1 == NULL && circle2 != NULL) log_printf(ERROR, "Unable to ringify Cell %d since it only contains " "the positive halfpsace of Circle %d. Rings can only be " "created for Cells on the interior (negative halfspace) " "of a CIRCLE Surface.", _id, circle2->getId()); if (radius1 <= radius2) log_printf(ERROR, "Unable to ringify Cell %d since it contains 2 " "disjoint CIRCLE Surfaces: halfspace %d for Circle %d " "and halfspace %d for Circle %d. Switch the signs of " "the 2 halfspaces for each Surface.", _id, halfspace1, circle1->getId(), halfspace2, circle2->getId()); /* Compute the area to fill with each equal volume ring */ double area = M_PI * fabs(radius1*radius1 - radius2*radius2) / _num_rings; /* Generate successively smaller Circle Surfaces */ for (int i=0; i < _num_rings-1; i++) { radius2 = sqrt(radius1*radius1 - (area / M_PI)); Circle* circle = new Circle(x1, y1, radius1); circles.push_back(circle); radius1 = radius2; } /* Store smallest, innermost Circle */ Circle* circle = new Circle(x1, y1, radius1); circles.push_back(circle); /* Loop over Circles and create a new Cell clone for each ring */ std::vector<Circle*>::iterator iter2; std::vector<CellBasic*>::iterator iter3; for (iter2 = circles.begin(); iter2 != circles.end(); ++iter2) { /* Create Circles for each of the sectorized Cells */ if (_sectors.size() != 0) { for (iter3 = _sectors.begin(); iter3 != _sectors.end(); ++iter3) { log_printf(DEBUG, "Creating a new ring in sector Cell %d", (*iter3)->getId()); /* Create a new CellBasic clone */ CellBasic* ring = (*iter3)->clone(); ring->setNumSectors(0); ring->setNumRings(0); /* Add new bounding Circle surfaces to the clone */ ring->addSurface(-1, (*iter2)); /* Look ahead and check if we have an inner Circle to add */ if (iter2+1 == circles.end()) { _rings.push_back(ring); continue; } else ring->addSurface(+1, *(iter2+1)); /* Store the clone in the parent Cell's container of ring Cells */ _rings.push_back(ring); } } /* Create Circles for this un-sectorized Cell */ else { log_printf(DEBUG, "Creating new ring in un-sectorized Cell %d",_id); /* Create a new CellBasic clone */ CellBasic* ring = clone(); ring->setNumSectors(0); ring->setNumRings(0); /* Add new bounding Circle Surfaces to the clone */ ring->addSurface(-1, (*iter2)); /* Look ahead and check if we have an inner Circle to add */ if (iter2+1 == circles.end()) { _rings.push_back(ring); break; } else ring->addSurface(+1, *(iter2+1)); /* Store the clone in the parent Cell's container of ring Cells */ _rings.push_back(ring); } } /* Store all of the rings in the parent Cell's subcells container */ _subcells.clear(); _subcells.insert(_subcells.end(), _rings.begin(), _rings.end()); }
/** * @brief Subdivides the Cell into clones for fuel pin angular sectors. */ void CellBasic::sectorize() { /* If the user didn't request any sectors, don't make any */ if (_num_sectors == 0) return; double azim_angle; double delta_azim = 2. * M_PI / _num_sectors; double A, B; /* A container for each of the bouding planes for the sector Cells */ std::vector<Plane*> planes; log_printf(DEBUG, "Sectorizing Cell %d with %d sectors",_id, _num_sectors); /* Create each of the bounding planes for the sector Cells */ for (int i=0; i < _num_sectors; i++) { /* Figure out the angle for this plane */ azim_angle = i * delta_azim; /* Instantiate the plane */ A = cos(azim_angle); B = sin(azim_angle); Plane* plane = new Plane(A, B, 0.); planes.push_back(plane); log_printf(DEBUG, "Created sector Plane id = %d, angle = %f, A = %f, " "B = %f", i, azim_angle, A, B); } /* Create sectors using disjoint halfspaces of pairing Planes */ for (int i=0; i < _num_sectors; i++) { /* Create new CellBasic clone for this sector Cell */ CellBasic* sector = clone(); sector->setNumSectors(0); sector->setNumRings(0); log_printf(DEBUG, "Creating a new sector Cell %d for Cell %d", sector->getId(), _id); /* Add new bounding planar Surfaces to the clone */ sector->addSurface(+1, planes.at(i)); if (_num_sectors != 2) { if (i+1 < _num_sectors) sector->addSurface(-1, planes.at(i+1)); else sector->addSurface(-1, planes.at(0)); } /* Store the clone in the parent Cell's container of sector Cells */ _sectors.push_back(sector); } /* Store all of the sectors in the parent Cell's subcells container */ _subcells.clear(); _subcells.insert(_subcells.end(), _sectors.begin(), _sectors.end()); }
/** * @brief Initializes the FSR volumes and Materials array. * @details This method assigns each FSR a unique, monotonically increasing * ID, sets the Material for each FSR, and assigns a volume based on * the cumulative length of all of the segments inside the FSR. */ void CPUSolver::initializeFSRs() { log_printf(INFO, "Initializing flat source regions..."); /* Delete old FSR arrays if they exist */ if (_FSR_volumes != NULL) delete [] _FSR_volumes; if (_FSR_materials != NULL) delete [] _FSR_materials; _FSR_volumes = (FP_PRECISION*)calloc(_num_FSRs, sizeof(FP_PRECISION)); _FSR_materials = new Material*[_num_FSRs]; _FSR_locks = new omp_lock_t[_num_FSRs]; int num_segments; segment* curr_segment; segment* segments; FP_PRECISION volume; CellBasic* cell; Material* material; Universe* univ_zero = _geometry->getUniverse(0); /* Set each FSR's "volume" by accumulating the total length of all Tracks * inside the FSR. Loop over azimuthal angles, Tracks and Track segments. */ for (int i=0; i < _tot_num_tracks; i++) { int azim_index = _tracks[i]->getAzimAngleIndex(); num_segments = _tracks[i]->getNumSegments(); segments = _tracks[i]->getSegments(); for (int s=0; s < num_segments; s++) { curr_segment = &segments[s]; volume = curr_segment->_length * _azim_weights[azim_index]; _FSR_volumes[curr_segment->_region_id] += volume; } } /* Loop over all FSRs to extract FSR material pointers */ #pragma omp parallel for private(cell, material) schedule(guided) for (int r=0; r < _num_FSRs; r++) { /* Get the Cell corresponding to this FSR from the geometry */ cell = _geometry->findCellContainingFSR(r); /* Get the Cell's Material and assign it to the FSR */ material = _geometry->getMaterial(cell->getMaterial()); _FSR_materials[r] = material; log_printf(DEBUG, "FSR ID = %d has Cell ID = %d and Material ID = %d " "and volume = %f", r, cell->getId(), _FSR_materials[r]->getUid(), _FSR_volumes[r]); } /* Loop over all FSRs to initialize OpenMP locks */ #pragma omp parallel for schedule(guided) for (int r=0; r < _num_FSRs; r++) omp_init_lock(&_FSR_locks[r]); return; }