void Ring::buildTopDown() { double startRadius = buildStartRadius()-ringGap(); if (ringInnerRadius()>0){ logWARNING("inner radius was set for a top-down endcap building. Ignoring ringInnerRadius."); } if (ringOuterRadius()>0) { if (ringGap()!=0) logWARNING("outerRadius and ringGap were both specified. Ignoring ringGap."); startRadius = ringOuterRadius(); } buildStartRadius(startRadius); RectangularModule* rmod = GeometryFactory::make<RectangularModule>(); rmod->store(propertyTree()); auto optimalRingParms = computeOptimalRingParametersRectangle(rmod->width(), buildStartRadius()); int numMods = optimalRingParms.second; EndcapModule* emod = GeometryFactory::make<EndcapModule>(rmod); emod->store(propertyTree()); emod->build(); emod->translate(XYZVector(buildStartRadius() - rmod->length()/2, 0, 0)); minRadius_ = buildStartRadius() - rmod->length(); maxRadius_ = buildStartRadius(); if (numModules.state()) numMods = numModules(); else numModules(numMods); buildModules(emod, numMods, smallDelta()); delete emod; }
template<typename Iterator> pair<vector<double>, vector<double>> StraightRodPair::computeZListPair(Iterator begin, Iterator end, double startZ, int recursionCounter) { bool fixedStartZ = true; vector<double> zPlusList = computeZList(begin, end, startZ, BuildDir::RIGHT, zPlusParity(), fixedStartZ); vector<double> zMinusList = computeZList(begin, end, startZ, BuildDir::LEFT, -zPlusParity(), !fixedStartZ); double zUnbalance = (zPlusList.back()+(*(end-1))->length()/2) + (zMinusList.back()-(*(end-1))->length()/2); // balancing uneven pos/neg strings if (++recursionCounter == 100) { // this stops infinite recursion if the balancing doesn't converge std::ostringstream tempSS; tempSS << "Balanced module placement in rod pair at avg build radius " << (maxBuildRadius()+minBuildRadius())/2. << " didn't converge!! Layer is skewed"; tempSS << "Unbalance is " << zUnbalance << " mm"; logWARNING(tempSS); return std::make_pair(zPlusList, zMinusList); } if (fabs(zUnbalance) > 0.1) { // 0.1 mm unbalance is tolerated return computeZListPair(begin, end, startZ-zUnbalance/2, // countering the unbalance by displacing the startZ (by half the inverse unbalance, to improve convergence) recursionCounter); } else { std::ostringstream tempSS; tempSS << "Balanced module placement in rod pair at avg build radius " << (maxBuildRadius()+minBuildRadius())/2. << " converged after " << recursionCounter << " step(s).\n" << " Residual Z unbalance is " << zUnbalance << ".\n" << " Positive string has " << zPlusList.size() << " modules, negative string has " << zMinusList.size() << " modules.\n" << " Z+ rod starts at " << zPlusList.front() << ", Z- rod starts at " << zMinusList.front() << "."; logINFO(tempSS); return std::make_pair(zPlusList, zMinusList); } }
BvhReader::BvhReader(string bvhFilePath) { _bvhStream.open(bvhFilePath.c_str()); if (!_bvhStream) { logWARNING("Unable to open <%s>",bvhFilePath.c_str()); //cerr << "[WARNING] Unable to open <" << bvhFilePath << ">" << endl; } else { string token = ""; _bvhStream >> token; if (token != "HIERARCHY") { logWARNING("%s> is not a valid BVH file.", bvhFilePath.c_str()); //cerr << "[WARNING] <" << bvhFilePath << "> is not a valid BVH file." << endl; } } }
void StraightRodPair::buildFull(const RodTemplate& rodTemplate) { double startZ = startZMode() == StartZMode::MODULECENTER ? -(*rodTemplate.begin())->length()/2. : 0.; auto zListPair = computeZListPair(rodTemplate.begin(), rodTemplate.end(), startZ, 0); // actual module creation // CUIDADO log rod balancing effort buildModules(zPlusModules_, rodTemplate, zListPair.first, BuildDir::RIGHT, zPlusParity(), 1); double currMaxZ = zPlusModules_.size() > 1 ? MAX(zPlusModules_.rbegin()->planarMaxZ(), (zPlusModules_.rbegin()+1)->planarMaxZ()) : (!zPlusModules_.empty() ? zPlusModules_.rbegin()->planarMaxZ() : 0.); // CUIDADO this only checks the positive side... the negative side might actually have a higher fabs(maxZ) if the barrel is long enough and there's an inversion buildModules(zMinusModules_, rodTemplate, zListPair.second, BuildDir::LEFT, -zPlusParity(), -1); auto collisionsZPlus = solveCollisionsZPlus(); auto collisionsZMinus = solveCollisionsZMinus(); if (!collisionsZPlus.empty() || !collisionsZMinus.empty()) logWARNING("Some modules have been translated to avoid collisions. Check info tab"); if (compressed() && maxZ.state() && currMaxZ > maxZ()) compressToZ(maxZ()); currMaxZ = zPlusModules_.size() > 1 ? MAX(zPlusModules_.rbegin()->planarMaxZ(), (zPlusModules_.rbegin()+1)->planarMaxZ()) : (!zPlusModules_.empty() ? zPlusModules_.rbegin()->planarMaxZ() : 0.); maxZ(currMaxZ); }
void ConversionStation::Conversion::build() { //std::cout << " CONVERSION" << std::endl; if (inputNode_.size() > 0) { input = new Inoutput(); input->store(propertyTree()); input->store(inputNode_.begin()->second); input->check(); input->build(); if(input->elements[0]->unit().compare("g") == 0) { logWARNING("Converted element unit is 'g' in conversion rule."); } } if (outputNode_.size() > 0) { outputs = new Inoutput(); outputs->store(propertyTree()); outputs->store(outputNode_.begin()->second); outputs->check(); outputs->build(); } cleanup(); }
void StraightRodPair::compressToZ(double z) { if (zPlusModules_.empty()) return; logINFO("Layer slated for compression"); auto findMaxZModule = [&]() { return *std::max_element(zPlusModules_.begin(), zPlusModules_.end(), [](const BarrelModule& m1, const BarrelModule& m2) { return m1.planarMaxZ() < m2.planarMaxZ(); }); }; auto findMinZModule = [&]() { return *std::min_element(zMinusModules_.begin(), zMinusModules_.end(), [](const BarrelModule& m1, const BarrelModule& m2) { return m1.planarMinZ() < m2.planarMinZ(); }); }; double Deltap = fabs(z) - findMaxZModule().planarMaxZ(); double Deltam = -fabs(z) - findMinZModule().planarMinZ(); logINFO("Rod length cannot exceed " + any2str(z)); logINFO(" Z+ rod will be compressed by " + any2str(fabs(Deltap))); logINFO(" Z- rod will be compressed by " + any2str(fabs(Deltam))); if (allowCompressionCuts()) { logINFO("Compression algorithm is allowed to cut modules which fall out entirely from the maximum z line"); int zPlusOrigSize = zPlusModules_.size(); for (auto it = zPlusModules_.begin(); it != zPlusModules_.end();) { if (it->planarMinZ() > z) it = zPlusModules_.erase(it); else ++it; } logINFO(" " + any2str(zPlusOrigSize - zPlusModules_.size()) + " modules were cut from the Z+ rod"); if (zPlusOrigSize - zPlusModules_.size()) { Deltap = fabs(z) - findMaxZModule().planarMaxZ(); // we have to use findMaxZModule instead of checking only the last module as there might be inversions at high Z logINFO(" Z+ rod now exceeding by " + any2str(fabs(Deltap))); } int zMinusOrigSize = zMinusModules_.size(); for (auto it = zMinusModules_.begin(); it != zMinusModules_.end();) { if (it->planarMaxZ() < -z) it = zMinusModules_.erase(it); else ++it; } logINFO(" " + any2str(zMinusOrigSize - zMinusModules_.size()) + " modules were cut from the Z- rod"); if (zMinusOrigSize - zMinusModules_.size()) { Deltam = -fabs(z) - findMinZModule().planarMinZ(); logINFO(" Z- rod now exceeding by " + any2str(fabs(Deltam))); } } logINFO("Iterative compression of Z+ rod"); int i; static const int maxIterations = 50; for (i = 0; fabs(Deltap) > 0.1 && i < maxIterations; i++) { double deltap=Deltap/((findMaxZModule().center()).Z()); std::map<int, double> zGuards; zGuards[1] = zGuards[-1] = std::numeric_limits<double>::lowest(); int parity = zPlusParity(); for (auto it = zPlusModules_.begin(); it < zPlusModules_.end(); ++it, parity = -parity) { double translation = deltap*it->center().Z(); double minPhysZ = MIN(it->planarMinZ(), it->center().Z() - it->physicalLength()/2); if (minPhysZ + translation < zGuards[parity]) translation = zGuards[parity] - minPhysZ; it->translateZ(translation); double maxPhysZ = MAX(it->planarMaxZ(), it->center().Z() + it->physicalLength()/2); zGuards[parity] = maxPhysZ; } Deltap = fabs(z) - findMaxZModule().planarMaxZ(); } if (i == maxIterations) { logINFO("Iterative compression didn't terminate after " + any2str(maxIterations) + " iterations. Z+ rod still exceeds by " + any2str(fabs(Deltap))); logWARNING("Failed to compress Z+ rod. Still exceeding by " + any2str(fabs(Deltap)) + ". Check info tab."); } else logINFO("Z+ rod successfully compressed after " + any2str(i) + " iterations. Rod now only exceeds by " + any2str(fabs(Deltap)) + " mm."); logINFO("Iterative compression of Z- rod"); for (i = 0; fabs(Deltam) > 0.1 && i < maxIterations; i++) { double deltam=Deltam/((findMinZModule().center()).Z()); // this can be optimized std::map<int, double> zGuards; zGuards[1] = zGuards[-1] = std::numeric_limits<double>::max(); int parity = -zPlusParity(); for (auto it = zMinusModules_.begin(); it < zMinusModules_.end(); ++it, parity = -parity) { double translation = deltam*it->center().Z(); double maxPhysZ = MAX(it->planarMaxZ(), it->center().Z() + it->physicalLength()/2); if (maxPhysZ + translation > zGuards[parity]) translation = zGuards[parity] - maxPhysZ; it->translateZ(translation); double minPhysZ = MIN(it->planarMinZ(), it->center().Z() - it->physicalLength()/2); zGuards[parity] = minPhysZ; } Deltam = -fabs(z) - findMinZModule().planarMinZ(); } if (i == 20) { logINFO("Iterative compression didn't terminate after " + any2str(maxIterations) + " iterations. Z- rod still exceeds by " + any2str(fabs(Deltam))); logWARNING("Failed to compress Z- rod. Still exceeding by " + any2str(fabs(Deltam)) + ". Check info tab."); } else logINFO("Z- rod successfully compressed after " + any2str(i) + " iterations. Rod now only exceeds by " + any2str(fabs(Deltam)) + " mm."); }
void ConversionStation::routeConvertedElements(MaterialObject& localOutput, MaterialObject& serviceOutput, InactiveElement& inactiveElement) { MaterialObject::Element* inputElement; //double totalGrams = 0.0; double multiplier = 0.0; bool converted = false; std::set<std::string> warningMaterials; for (const MaterialObject::Element* currElement : serviceElements_) { //inputElements) { converted = false; //if the material need to be converted (flange station, or endcap station with right destination) if ((stationType_ == FLANGE) || (stationType_ == SECOND && currElement->destination.state() && currElement->destination().compare(stationName_()) == 0)) { for (const Conversion* currConversion : conversions) { inputElement = currConversion->input->elements[0]; if (inputElement->elementName().compare(currElement->elementName()) == 0) { converted = true; multiplier = currElement->quantityInUnit(inputElement->unit(), inactiveElement) / inputElement->quantityInUnit(inputElement->unit(), inactiveElement); for (const MaterialObject::Element* outputElement : currConversion->outputs->elements) { MaterialObject::Element * newElement = new MaterialObject::Element(*outputElement, multiplier); if(currElement->debugInactivate()) { //apply the inactivation also to converteds newElement->debugInactivate(true); } //TODO: check if is ok to do this if(currElement->destination.state() && !newElement->destination.state()) { //apply the same destination of converted element (only if not defined in output conversion rule) newElement->destination(currElement->destination()); } if (newElement->service()) { if (newElement->unit().compare("g") != 0) { serviceOutput.addElement(newElement); } else { logERROR(err_service1 + newElement->elementName() + err_service2); } } else { localOutput.addElement(newElement); } } } } } if (!converted) { serviceOutput.addElement(currElement); warningMaterials.insert(currElement->elementName()); } } for(auto& warningMaterial : warningMaterials) { logWARNING("Element \"" + warningMaterial + "\" ignored by station \"" + stationName_() + "\"."); } /* for (const Conversion* currConversion : conversions) { inputElement = currConversion->input->elements[0]; totalGrams = 0.0; for (const MaterialObject::Element* currElement : inputElements) { if (inputElement->elementName().compare(currElement->elementName()) == 0) { totalGrams += currElement->quantityInGrams(inactiveElement); } } multiplier = totalGrams / inputElement->quantityInGrams(inactiveElement); for (const MaterialObject::Element* outputElement : currConversion->outputs->elements) { MaterialObject::Element * newElement = new MaterialObject::Element(*outputElement, multiplier); if (newElement->service()) { serviceOutput.addElement(newElement); } else { localOutput.addElement(newElement); } } } */ }
void Ring::buildBottomUp() { double startRadius = buildStartRadius()+ringGap(); if (ringOuterRadius()>0){ logWARNING("outer radius was set for a bottom-up endcap building. Ignoring ringOuterRadius."); } if (ringInnerRadius()>0) { if (ringGap()!=0) logWARNING("innerRadius and ringGap were both specified. Ignoring ringGap."); startRadius = ringInnerRadius(); } buildStartRadius(startRadius); int numMods; double modLength; EndcapModule* emod = nullptr; if (moduleShape() == ModuleShape::WEDGE) { WedgeModule* wmod = GeometryFactory::make<WedgeModule>(); wmod->store(propertyTree()); auto optimalRingParms = computeOptimalRingParametersWedge(wmod->waferDiameter(), buildStartRadius()); double alpha = optimalRingParms.first; numMods = optimalRingParms.second; wmod->buildAperture(alpha); wmod->buildDistance(buildStartRadius()); wmod->buildCropDistance(buildCropRadius()); wmod->build(); modLength = wmod->length(); emod = GeometryFactory::make<EndcapModule>(wmod); } else { RectangularModule* rmod = GeometryFactory::make<RectangularModule>(); rmod->store(propertyTree()); rmod->build(); auto optimalRingParms = computeOptimalRingParametersRectangle(rmod->width(), buildStartRadius() + rmod->length()); numMods = optimalRingParms.second; modLength = rmod->length(); emod = GeometryFactory::make<EndcapModule>(rmod); } emod->store(propertyTree()); emod->build(); emod->translate(XYZVector(buildStartRadius() + modLength/2, 0, 0)); minRadius_ = buildStartRadius(); maxRadius_ = buildStartRadius() + modLength; if (numModules.state()) numMods = numModules(); else numModules(numMods); buildModules(emod, numMods, smallDelta()); delete emod; }