/// <summary> /// Checks if operation modes of all <see cref="IOpAmp"/>s is correct, if <paramref name="adjust"/> is set to true then adjusts the /// <see cref="IOpAmp"/> that did not operate correctly (it does not mean all <see cref="IOpAmp"/>s will operate correctly - iterative /// approach is needed). /// </summary> /// <param name="nodePotentials">Potentials at nodes, keys are simulation node indices</param> /// <param name="adjust">True if <see cref="_OpAmpOperation"/> should be adjusted to try and find correct operation modes</param> /// <returns></returns> private bool CheckOpAmpOperation(IEnumerable <KeyValuePair <int, double> > nodePotentials, bool adjust) { // Cast the potentials to a dictionary for an easier lookup, add 1 to keys because op-amp nodes are stored with regular indices var lookupPotentials = nodePotentials.ToDictionary((x) => x.Key, (x) => x.Value); // For each op-amp foreach (var opAmp in _OpAmps) { // And get its output node potential var outputVoltage = lookupPotentials[_OpAmpsNodes[opAmp].Output]; // The operation mode that is expected OpAmpOperationMode expectedOperationMode = OpAmpOperationMode.Active; // If output voltage is between supply voltages if (outputVoltage > opAmp.NegativeSupplyVoltage && outputVoltage < opAmp.PositiveSupplyVoltage) { // Active operation mode expectedOperationMode = OpAmpOperationMode.Active; } // Else if it's greater than positive supply voltage else if (outputVoltage >= opAmp.PositiveSupplyVoltage) { // Positive saturation expectedOperationMode = OpAmpOperationMode.PositiveSaturation; } else { // Last possibility - negative saturation expectedOperationMode = OpAmpOperationMode.NegativeSaturation; } // If the expected operation mode differs from the actual on if (expectedOperationMode != _OpAmpOperation[opAmp]) { // If adjustment was requested, set the op-amp's operation mode to the expected mode if (adjust) { _OpAmpOperation[opAmp] = expectedOperationMode; } // Return incorrect operation return(false); } } // Return correct operation - neither op-amp operated incorrectly return(true); }
/// <summary> /// Configures <see cref="IOpAmp"/> for operation in <paramref name="operationMode"/> in <paramref name="matrix"/>. Saturated op-amps remain /// inactive after this call - they will appear to be saturated but saturation voltage will be equal to 0. Op-amps have to be manually /// activated, for example using <see cref="ActivateSaturatedOpAmps(AdmittanceMatrix)"/> /// </summary> /// <param name="matrix"></param> /// <param name="opAmpIndex"></param> /// <param name="operationMode"></param> private void ConfigureOpAmpOperation(AdmittanceMatrix matrix, IOpAmpDescription opAmp, OpAmpOperationMode operationMode) { // Call appropriate method based on operation mode switch (_OpAmpOperation[opAmp]) { case OpAmpOperationMode.Active: { ConfigureOpAmpForActiveOperation(matrix, opAmp); } break; case OpAmpOperationMode.PositiveSaturation: case OpAmpOperationMode.NegativeSaturation: { ConfigureOpAmpForSaturation(matrix, opAmp); } break; default: { throw new Exception("Unhandled case"); } } }