OpticalGraph.cc revision 10447:a465576671d4
1
2#include "model/optical_graph/OpticalGraph.h"
3
4#include "model/OpticalModel.h"
5#include "model/optical_graph/OpticalNode.h"
6#include "model/optical_graph/OpticalLaser.h"
7#include "model/optical_graph/OpticalModulator.h"
8#include "model/optical_graph/OpticalFilter.h"
9#include "model/optical_graph/OpticalDetector.h"
10#include "model/optical_graph/OpticalWavelength.h"
11
12namespace DSENT
13{
14    // Initialize the next visited number to be one above the initial number
15    // used by OpticalNode
16    int OpticalGraph::msTreeNum = OpticalNode::OPTICAL_NODE_INIT_VISITED_NUM + 1;
17
18    OpticalGraph::OpticalGraph(const String& instance_name_, OpticalModel* model_)
19        : m_instance_name_(instance_name_), m_model_(model_)
20    {
21
22    }
23
24    OpticalGraph::~OpticalGraph()
25    {
26
27    }
28
29    const String& OpticalGraph::getInstanceName() const
30    {
31        return m_instance_name_;
32    }
33
34    //-------------------------------------------------------------------------
35    // Perform Datapath power optimization
36    //-------------------------------------------------------------------------
37    bool OpticalGraph::performPowerOpt(OpticalNode* node_, const WavelengthGroup& wavelengths_, unsigned int number_detectors_, double util_)
38    {
39        // Total number of iterations
40        unsigned int number_iterations = 1250;
41        // Maximum IL + ER
42        double IL_ER_max = 10;
43        // Figure out the step size used in the sweep
44        double step = (double) (IL_ER_max / sqrt(2 * number_iterations));
45
46        // Assume it is possible
47        bool possible = true;
48
49        // Begin optical data path power optimization
50        Log::printLine(getInstanceName() + " -> Beginning optical data path power optimization");
51
52        // Trace the specified wavelengths
53        OpticalWavelength* wavelength = traceWavelength(wavelengths_, node_);
54
55        // For each data path found in the wavelength
56        const vector<OpticalDataPath>* data_paths = wavelength->getDataPaths();
57        for (unsigned int i = 0; i < data_paths->size(); ++i)
58        {
59            const OpticalDataPath& data_path = data_paths->at(i);
60            // Default to worst possible modulator
61            double best_power = 1e99;
62            double best_IL = IL_ER_max - step;
63            double best_ER = step;
64
65            // Perform power optimization for this data path
66            Log::printLine(getInstanceName() + " -> Optimize data path - Laser = " + data_path.laser->getInstanceName()
67                + ", Modulator = " + data_path.modulator->getInstanceName());
68
69            if (data_path.modulator->canOptimizeLoss())
70            {
71                // Iterate over IL and ER to find optimal set of IL and ER
72                for (double IL = step; IL < IL_ER_max; IL += step)
73                {
74                    for (double ER = step; ER <= (IL_ER_max - IL); ER += step)
75                    {
76                        // Ask the modulator to try this new ER and IL
77                        bool success = data_path.modulator->setModulatorSpec(IL, ER);
78                        // If the modulator was successful
79                        if (success)
80                        {
81                            double laser_power = wavelength->getLaserPower(number_detectors_);
82                            double modulator_power = data_path.modulator->getPower(util_);
83                            double total_power = laser_power + modulator_power;
84                            // If this is the new lowest power point
85                            if (total_power < best_power)
86                            {
87                                best_power = total_power;
88                                best_IL = IL;
89                                best_ER = ER;
90                            }
91                        }
92                    }
93                }
94
95                // Set IL and ER to the best ones we found
96                bool success = data_path.modulator->setModulatorSpec(best_IL, best_ER);
97                // If the best one we found was still not possible...
98                possible = possible && success;
99
100                // Print best IL and ER
101                Log::printLine(getInstanceName() + " -> Best IL=" + (String) best_IL + ", Best ER=" + (String) best_ER +
102                    ", Best Laser/Mod Power=" + (String) best_power);
103            }
104            else
105            {
106                // Perform power optimization for this data path
107                Log::printLine(getInstanceName() + " -> Data path not set to allow optimization");
108            }
109        }
110
111        // End optical data path power optimization
112        Log::printLine(getInstanceName() + " -> End optical data path power optimization");
113
114        delete wavelength;
115        return possible;
116    }
117
118
119    //-------------------------------------------------------------------------
120    // Trace wavelength(s), returning a wavelength data structure
121    //-------------------------------------------------------------------------
122    OpticalWavelength* OpticalGraph::traceWavelength(const WavelengthGroup& wavelengths_, OpticalNode* node_)
123    {
124        setTreeNum(getTreeNum() + 1);
125        OpticalWavelength* wavelength = new OpticalWavelength("TraceWavelength", wavelengths_);
126        return traceWavelength(wavelength, node_, NULL, NULL, 0.0);
127    }
128
129    OpticalWavelength* OpticalGraph::traceWavelength(OpticalWavelength* wavelength_, OpticalNode* node_, OpticalLaser* laser_, OpticalModulator* modulator_, double loss_)
130    {
131        // If the node has already been visited, don't do anything!
132        if (node_->getVisitedNum() != getTreeNum())
133        {
134            // Set the new parity for this node
135            node_->setVisitedNum(getTreeNum());
136
137            // Calculate the loss of the current path
138            double current_loss = loss_ + node_->getLoss();
139            // Check if the current node is a laser, modulator or detector
140            if(node_->getType() == OpticalNode::LASER)
141            {
142                // Set the laser lighting up the wavelength
143                ASSERT(laser_ == NULL, "[Error] " + getInstanceName() + " -> Multiple " +
144                    "Lasers lighting up the wavelength!");
145                laser_ = (OpticalLaser*) node_;
146            }
147            else if (node_->getType() == OpticalNode::MODULATOR)
148            {
149                // Check that the path already lit up by a laser and there are no
150                // modulators already driving data
151                ASSERT(laser_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
152                    "modulator (" + node_->getInstanceName() + ") prior to being lit up by a laser!");
153                ASSERT(modulator_ == NULL, "[Error] " + getInstanceName() + " -> Two modulators are driving" +
154                    " the same optical data path (" + node_->getInstanceName() + ")!");
155                modulator_ = (OpticalModulator*) node_;
156            }
157            else if (node_->getType() == OpticalNode::DETECTOR)
158            {
159                // Check that the path is both lit up by a laser and there is
160                // a modulator driving data
161                ASSERT(laser_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
162                    "detector (" + node_->getInstanceName() + ") prior to being lit up by a laser!");
163                ASSERT(modulator_ != NULL, "[Error] " + getInstanceName() + " -> Wavelength reaches a " +
164                    "detector (" + node_->getInstanceName() + ") prior to being driven by a modulator!");
165                // Add a detector to the wavelength
166                wavelength_->addDataPath(laser_, modulator_, (OpticalDetector*) node_, current_loss);
167            }
168
169            // Traverse downstream nodes to calculate the delay through each downstream path
170            vector<OpticalNode*>* d_nodes = node_->getDownstreamNodes();
171            bool trace_downstream = (node_->getType() != OpticalNode::DETECTOR);
172            // Do special things when traversing filters
173            if (node_->getType() == OpticalNode::FILTER)
174            {
175                OpticalFilter* filter_node = (OpticalFilter*) node_;
176                if (filter_node->isDropped(wavelength_->getWavelengths()))
177                    traceWavelength(wavelength_, filter_node->getDropPort(), laser_, modulator_, loss_ + filter_node->getDropLoss());
178
179                // If the filter is not modeled as a complete drop, continue tracing downstream
180                trace_downstream = !filter_node->getDropAll();
181            }
182
183            if (trace_downstream)
184            {
185                // Trace downstream nodes
186                for (unsigned int i = 0; i < d_nodes->size(); ++i)
187                    traceWavelength(wavelength_, d_nodes->at(i), laser_, modulator_, current_loss);
188            }
189        }
190        return wavelength_;
191    }
192
193    //-------------------------------------------------------------------------
194    OpticalGraph::OpticalGraph(const OpticalGraph& /* graph_ */)
195    {
196        // Disabled
197    }
198
199    OpticalModel* OpticalGraph::getModel()
200    {
201        return m_model_;
202    }
203
204    void OpticalGraph::setTreeNum(int tree_num_)
205    {
206        msTreeNum = tree_num_;
207        return;
208    }
209
210    int OpticalGraph::getTreeNum()
211    {
212        return msTreeNum;
213    }
214
215} // namespace DSENT
216
217