diff --git a/Version8/Source/General/CNTSLineConstants.pas b/Version8/Source/General/CNTSLineConstants.pas index 0878439d8..3fc464bb0 100644 --- a/Version8/Source/General/CNTSLineConstants.pas +++ b/Version8/Source/General/CNTSLineConstants.pas @@ -272,7 +272,12 @@ procedure TCNTSLineConstants.Calc(f: double); // Mutual Impedances - between CN/TS cores and bare neutrals For i := 1 to FNumConds Do Begin For j := 1 to i-1 Do Begin - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + if not FEquivalentSpacing then Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])) + else + begin + if ((j <= FNumPhases) and (i > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + end; Zmat.SetElemSym(i, j, Cadd(Cmulreal(Lfactor, ln(1.0/Dij)), Get_Ze(i,j))); End; End; @@ -282,7 +287,12 @@ procedure TCNTSLineConstants.Calc(f: double); idxi := i + FNumConds; For j := 1 to i-1 Do Begin // CN/TS to other CN/TS idxj := j + FNumConds; - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + if not FEquivalentSpacing then Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])) + else + begin + if ((j <= FNumPhases) and (i > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + end; Zmat.SetElemSym(idxi, idxj, Cadd(Cmulreal(Lfactor, ln(1.0/Dij)), Get_Ze(i,j))); End; for j := 1 to FNumConds do begin // CN/TS to cores and bare neutrals @@ -292,7 +302,12 @@ procedure TCNTSLineConstants.Calc(f: double); if i = j then begin // CN to its own phase core Dij := RadCN; end else begin // CN to another phase or bare neutral - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + if not FEquivalentSpacing then Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])) + else + begin + if ((i <= FNumPhases) and (j > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + end; Dij := Power (Power(Dij, FkStrand^[i]) - Power(RadCN, FkStrand^[i]), 1.0 / FkStrand^[i]); end; @@ -302,7 +317,12 @@ procedure TCNTSLineConstants.Calc(f: double); if i = j then begin // TS to its own phase core Dij := GmrTS; end else begin // TS to another phase or bare neutral - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + if not FEquivalentSpacing then Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])) + else + begin + if ((i <= FNumPhases) and (j > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + end; end; end; Zmat.SetElemSym(idxi, idxj, Cadd(Cmulreal(Lfactor, ln(1.0/Dij)), Get_Ze(i,j))); diff --git a/Version8/Source/General/CableConstants.pas b/Version8/Source/General/CableConstants.pas index 8a892d4ba..0a8dd1af7 100644 --- a/Version8/Source/General/CableConstants.pas +++ b/Version8/Source/General/CableConstants.pas @@ -89,18 +89,38 @@ function TCableConstants.ConductorsInSameSpace( var ErrorMessage: String): Boole End; End; *) - For i := 1 to FNumConds do Begin - if i <= FNumPhases then Ri := FRadius^[i] else Ri := 0.5 * FDiaCable^[i]; - for j := i+1 to FNumConds do Begin - if j <= FNumPhases then Rj := FRadius^[j] else Rj := 0.5 * FDiaCable^[j]; - Dij := Sqrt(SQR(FX^[i] - FX^[j]) + SQR(FY^[i] - FY^[j])); - if (Dij < (Ri + Rj)) then Begin - Result := TRUE; - ErrorMessage := Format('Cable conductors %d and %d occupy the same space.', [i, j ]); - Exit; + if FEquivalentSpacing then + begin + For i := 1 to FNumConds do Begin + if i <= FNumPhases then Ri := FRadius^[i] else Ri := 0.5 * FDiaCable^[i]; + for j := i+1 to FNumConds do Begin + if j <= FNumPhases then Rj := FRadius^[j] else Rj := 0.5 * FDiaCable^[j]; + if ((i <= FNumPhases) and (j > FNumPhases)) then Dij := FEqDist[2] + else Dij := FEqDist[1]; + + if (Dij < (Ri + Rj)) then Begin + Result := TRUE; + ErrorMessage := Format('Cable conductors %d and %d occupy the same space.', [i, j ]); + Exit; + End; End; End; - End; + end + else + begin + For i := 1 to FNumConds do Begin + if i <= FNumPhases then Ri := FRadius^[i] else Ri := 0.5 * FDiaCable^[i]; + for j := i+1 to FNumConds do Begin + if j <= FNumPhases then Rj := FRadius^[j] else Rj := 0.5 * FDiaCable^[j]; + Dij := Sqrt(SQR(FX^[i] - FX^[j]) + SQR(FY^[i] - FY^[j])); + if (Dij < (Ri + Rj)) then Begin + Result := TRUE; + ErrorMessage := Format('Cable conductors %d and %d occupy the same space.', [i, j ]); + Exit; + End; + End; + End; + end; end; function TCableConstants.Get_EpsR(i: Integer): Double; diff --git a/Version8/Source/General/LineConstants.pas b/Version8/Source/General/LineConstants.pas index 90b521a98..faaa708e9 100644 --- a/Version8/Source/General/LineConstants.pas +++ b/Version8/Source/General/LineConstants.pas @@ -44,6 +44,9 @@ TLineConstants = class(TObject) FNumPhases :Integer; FX :pDoubleArray; FY :pDoubleArray; + FEqDist :array of Double; // This array always has four elements EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + FEquivalentSpacing :Boolean; // to tell the calcs when to use equivalent spacing info + FRdc :pDoubleArray; // ohms/m FRac :pDoubleArray; // ohms/m FGMR :pDoubleArray; // m @@ -72,6 +75,7 @@ TLineConstants = class(TObject) function Get_Rac(i, units: Integer): Double; function Get_X(i, units: Integer): Double; function Get_Y(i, units: Integer): Double; + function Get_FEqDist(i, units: Integer): Double; function Get_YCmatrix(f, Lngth: double; Units: Integer): Tcmatrix; function Get_Ze(i, j: Integer): Complex; function Get_Zint(i: Integer): Complex; @@ -83,11 +87,13 @@ TLineConstants = class(TObject) procedure Set_Rac(i, units: Integer; const Value: Double); procedure Set_X(i, units: Integer; const Value: Double); procedure Set_Y(i, units: Integer; const Value: Double); + procedure Set_FEqDist(i, units: Integer; const Value: Double); procedure Set_Frequency(const Value: Double); procedure Set_Frhoearth(const Value: Double); // m procedure Set_FEpsRMedium(const Value: Double); // unit-less procedure Set_FheightOffset(const Value: Double); // m procedure Set_FuserHeightUnit(const Value: Integer); // Whatever the user defined. The height is always saved in meters here. + procedure Set_FEquivalentSpacing(const Value: Boolean); // This allows you to compute capacitance using a different radius -- for bundled conductors function Get_Capradius(i, units: Integer): Double; @@ -111,6 +117,8 @@ TLineConstants = class(TObject) Property X[i, units:Integer]:Double Read Get_X Write Set_X; Property Y[i, units:Integer]:Double Read Get_Y Write Set_Y; + Property EqDist[i, units:Integer]:Double Read Get_FEqDist Write Set_FEqDist; + Property Rdc[i, units:Integer]:Double Read Get_Rdc Write Set_Rdc; Property Rac[i, units:Integer]:Double Read Get_Rac Write Set_Rac; Property radius[i, units:Integer]:Double Read Get_radius Write Set_radius; @@ -122,6 +130,7 @@ TLineConstants = class(TObject) Property EpsRMedium:Double read FEpsRMedium write Set_FEpsRMedium; Property heightOffset:Double read Get_FheightOffset write Set_FheightOffset; Property userHeightUnit:Integer read FuserHeightUnit write Set_FuserHeightUnit; + Property EquivalentSpacing:Boolean read FEquivalentSpacing write Set_FEquivalentSpacing; {These two properties will auto recalc the impedance matrices if frequency is different} {Converts to desired units when executed; Returns Pointer to Working Verstion} @@ -204,7 +213,12 @@ procedure TLineConstants.Calc(f: double); For i := 1 to FNumConds Do Begin For j := 1 to i-1 Do Begin - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + if not FEquivalentSpacing then Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])) + else + begin + if ((j <= FNumPhases) and (i > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + end; FZmatrix.SetElemSym(i, j, Cadd(Cmulreal(Lfactor, ln(1.0/Dij)), Get_Ze(i,j))); End; End; @@ -220,13 +234,30 @@ procedure TLineConstants.Calc(f: double); For i := 1 to FnumConds Do Begin - FYCMatrix.SetElement(i, i, cmplx(0.0, pfactor * ln(2.0*Fy^[i]/Fcapradius^[i]))); + if not FEquivalentSpacing then FYCMatrix.SetElement(i, i, cmplx(0.0, pfactor * ln(2.0*Fy^[i]/Fcapradius^[i]))) + else + begin + if (i > FNumPhases) then FYCMatrix.SetElement(i, i, cmplx(0.0, pfactor * ln(2.0*FEqDist[4]/Fcapradius^[i]))) + else FYCMatrix.SetElement(i, i, cmplx(0.0, pfactor * ln(2.0*FEqDist[3]/Fcapradius^[i]))); + end; End; For i := 1 to FNumConds Do Begin For j := 1 to i-1 Do Begin - Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); - Dijp := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]+Fy^[j])); // distance to image j + if not FEquivalentSpacing then + begin + Dij := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]-Fy^[j])); + Dijp := sqrt(sqr(Fx^[i]-Fx^[j]) + sqr(Fy^[i]+Fy^[j])); // distance to image j + end + else + begin + if ((j <= FNumPhases) and (i > FNumPhases)) then Dij := FEqDist[2] // EqDistPhN + else Dij := FEqDist[1]; // EqDistPhPh (including N-N conductorss) + + if ((j <= FNumPhases) and (i > FNumPhases)) then Dijp := (FEqDist[3] + FEqDist[4]) // AvgHeightPhase + AvgHeightNeutral + else if ((i <= FNumPhases) and (j <= FNumPhases)) then Dijp := (2 * FEqDist[3]) // 2 * AvgHeightPhase + else Dijp := (2 * FEqDist[4]) // 2 * AvgHeightNeutral + end; FYCMatrix.SetElemSym(i, j, cmplx(0.0, pfactor * ln(Dijp/Dij))); End; End; @@ -249,27 +280,53 @@ function TLineConstants.ConductorsInSameSpace( var ErrorMessage: String): Boolea {Check all conductors to make sure none occupy the same space or are defined at 0,0} Result := FALSE; - {Check for 0 Y coordinate} - For i := 1 to FNumConds do Begin - if (FY^[i] <= 0.0) then Begin - Result := TRUE; - ErrorMessage := Format('Conductor %d height must be > 0. ', [ i ]); - Exit + if FEquivalentSpacing then + begin + {Check for 0 Y coordinate} + if (FEqDist[3] <= 0.0) or (FEqDist[4] <= 0.0) then Begin + Result := TRUE; + ErrorMessage := 'Conductor average heights (overhead equivalent spacing) must be > 0.'; + Exit + End; + {Check for overlapping conductors} + For i := 1 to FNumConds do Begin + for j := i+1 to FNumConds do Begin + if ((i <= FNumPhases) and (j > FNumPhases)) then Dij := FEqDist[2] + else Dij := FEqDist[1]; + + if (Dij < (Fradius^[i]+Fradius^[j])) then Begin + Result := TRUE; + ErrorMessage := Format('Conductors %d and %d occupy the same space.', + [i, j ]); + Exit; + End; End; - End; + End; + end + else begin + {Check for 0 Y coordinate} + For i := 1 to FNumConds do Begin + if (FY^[i] <= 0.0) then Begin + Result := TRUE; + ErrorMessage := Format('Conductor %d height must be > 0. ', [ i ]); + Exit + End; + End; - {Check for overlapping conductors} - For i := 1 to FNumConds do Begin - for j := i+1 to FNumConds do Begin - Dij := Sqrt(SQR(FX^[i] - FX^[j]) + SQR(FY^[i] - FY^[j])); - if (Dij < (Fradius^[i]+Fradius^[j])) then Begin - Result := TRUE; - ErrorMessage := Format('Conductors %d and %d occupy the same space.', - [i, j ]); - Exit; + {Check for overlapping conductors} + For i := 1 to FNumConds do Begin + for j := i+1 to FNumConds do Begin + Dij := Sqrt(SQR(FX^[i] - FX^[j]) + SQR(FY^[i] - FY^[j])); + if (Dij < (Fradius^[i]+Fradius^[j])) then Begin + Result := TRUE; + ErrorMessage := Format('Conductors %d and %d occupy the same space.', + [i, j ]); + Exit; + End; End; End; - End; + end; + end; constructor TLineConstants.Create( NumConductors: Integer); @@ -286,6 +343,9 @@ constructor TLineConstants.Create( NumConductors: Integer); FRdc := Allocmem(Sizeof(FRdc^[1])*FNumConds); FRac := Allocmem(Sizeof(FRac^[1])*FNumConds); + SetLength(FEqDist, 4); // This array always has four elements EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + FEquivalentSpacing := FALSE; + {Initialize to not set} For i := 1 to FNumConds Do FGMR^[i] := -1.0; @@ -370,6 +430,11 @@ function TLineConstants.Get_Y(i, units: Integer): Double; Result := FY^[i] * From_Meters(Units); end; +function TLineConstants.Get_FEqDist(i, units: Integer): Double; +begin + Result := FEqDist[i] * From_Meters(Units); // This array has only four elements PhPh, PhN, AvgHeightPh, AvgHeightN +end; + function TLineConstants.Get_YCmatrix(f, Lngth: double; Units: Integer): Tcmatrix; {Makes a new YCmatrix and correct for lengths and units as it copies} @@ -401,12 +466,22 @@ function TLineConstants.Get_YCmatrix(f, Lngth: double; function TLineConstants.Get_Ze(i, j: Integer): Complex; Var LnArg, hterm, xterm:Complex; - mij , thetaij, Dij, Fyi, Fyj:double; + mij , thetaij, Dij, Fyi, Fyj, Fxi_Fxj:double; term1, term2, term3, term4, term5:double; begin - Fyi := Abs(Fy^[i]); - Fyj := Abs(Fy^[j]); + if not FEquivalentSpacing then Fyi := Abs(Fy^[i]) + else if i <= FNumPhases then Fyi := Abs(FEqDist[3]) + else Fyi := Abs(FEqDist[4]); + + if not FEquivalentSpacing then Fyj := Abs(Fy^[j]) + else if j <= FNumPhases then Fyj := Abs(FEqDist[3]) + else Fyj := Abs(FEqDist[4]); + + // If the spacing uses equivalent distance, assume the equivalent distance is on the X axis. + if not FEquivalentSpacing then Fxi_Fxj := Fx^[i] - Fx^[j] + else if ((i <= FNumPhases) and (j <= FNumPhases)) or ((i > FNumPhases) and (j > FNumPhases)) then Fxi_Fxj := FEqDist[1] + else Fxi_Fxj := FEqDist[2]; CASE ActiveEarthModel[ActiveActor] of @@ -421,7 +496,7 @@ function TLineConstants.Get_Ze(i, j: Integer): Complex; thetaij := 0.0; Dij := 2.0*Fyi; end else begin - Dij := sqrt(sqr(Fyi + Fyj) + sqr(Fx^[i] - Fx^[j])); + Dij := sqrt(sqr(Fyi + Fyj) + sqr(Fxi_Fxj)); thetaij := ArcCos( (Fyi + Fyj)/ Dij); End; mij := 2.8099e-3 * Dij * sqrt(FFrequency/Frhoearth); @@ -446,7 +521,7 @@ function TLineConstants.Get_Ze(i, j: Integer): Complex; DERI: Begin If i<>j Then Begin hterm := Cadd(cmplx(Fyi + Fyj, 0.0), CmulReal(Cinv(Fme),2.0)); - xterm := cmplx(Fx^[i] - Fx^[j], 0.0); + xterm := cmplx(Fxi_Fxj, 0.0); LnArg := Csqrt(Cadd(Cmul(hterm, hterm),cmul(xterm, xterm))); Result := Cmul(Cmplx(0.0, Fw*Mu0/twopi) , Cln(lnArg)); End Else Begin @@ -617,6 +692,15 @@ procedure TLineConstants.Set_FuserHeightUnit(const Value: Integer); end; end; +procedure TLineConstants.Set_FEquivalentSpacing(const Value: Boolean); +begin + If Value <> FEquivalentSpacing then + begin + FEquivalentSpacing := Value; + FRhoChanged := TRUE; // using this for both EpsRMedium, Rho, heightOffset and FuserHeightUnit and for this one as well. + end; +end; + procedure TLineConstants.Set_GMR(i, units: Integer; const Value: Double); begin If (i>0) and (i<=FNumConds) Then Begin @@ -659,6 +743,11 @@ procedure TLineConstants.Set_Y(i, units: Integer; const Value: Double); If (i>0) and (i<=FNumConds) Then FY^[i] := Value * To_Meters(units); end; +procedure TLineConstants.Set_FEqDist(i, units: Integer; const Value: Double); +begin + if (i > 4) then exit; // This array has only four elements PhPh, PhN, AvgHeightPh, AvgHeightN + FEqDist[i] := Value * To_Meters(units); +end; procedure TLineConstants.AddHeightOffset(); var diff --git a/Version8/Source/General/LineGeometry.pas b/Version8/Source/General/LineGeometry.pas index e58ed5455..435f993d6 100644 --- a/Version8/Source/General/LineGeometry.pas +++ b/Version8/Source/General/LineGeometry.pas @@ -62,6 +62,9 @@ TLineGeometryObj = class(TDSSObject) FWireData :pConductorDataArray; FX :pDoubleArray; FY :pDoubleArray; + FEqDist :array of Double; // This array always has four elements EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + FEquivalentSpacing :Boolean; // to tell the calcs when to use equivalent spacing info + FCondsUser :String; // use this to preserve conductors array for dumping to avoid losing user-defined None positions. FUnits :pIntegerArray; FLastUnit :Integer; DataChanged :Boolean; @@ -144,7 +147,7 @@ implementation USES ParserDel, DSSClassDefs, DSSGlobals, Ucomplex, Utilities, LineUnits, OHLineConstants, CNTSLineConstants; -Const NumPropsThisClass = 19; +Const NumPropsThisClass = 20; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - constructor TLineGeometry.Create; // Creates superstructure for all Line objects @@ -196,6 +199,7 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object PropertyName^[17] := 'Seasons'; PropertyName^[18] := 'Ratings'; PropertyName^[19] := 'LineType'; + PropertyName^[20] := 'conductors'; PropertyHelp^[1] := 'Number of conductors in this geometry. Default is 3. Triggers memory allocations. Define first!'; PropertyHelp^[2] := 'Number of phases. Default =3; All other conductors are considered neutrals and might be reduced out.'; @@ -236,6 +240,11 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object PropertyHelp^[19] := 'Code designating the type of line. ' + CRLF + 'One of: OH, UG, UG_TS, UG_CN, SWT_LDBRK, SWT_FUSE, SWT_SECT, SWT_REC, SWT_DISC, SWT_BRK, SWT_ELBOW, BUSBAR' + CRLF + CRLF + 'OpenDSS currently does not use this internally. For whatever purpose the user defines. Default is OH.' ; + PropertyHelp^[20] := 'Array of conductor names for use in line constants calculation.' + CRLF + + 'Must be used in conjunction with the Spacing property.' + CRLF + + 'Specify the Spacing first, and "ncond" wires.' + CRLF + + 'Specify the conductor type followed by the conductor name. e.g., "conductors=[cndata.cncablename, tsdata.tscablename, wiredata.wirename]"'+ CRLF + + 'If a given position in the spacing is not to be used in the line, use "none" in the entry of the conductors array.'; ActiveProperty := NumPropsThisClass; inherited DefineProperties; // Add defs of inherited properties to bottom of list @@ -257,13 +266,14 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Function TLineGeometry.Edit(ActorID : Integer):Integer; VAR - i, + i, j, istart, istop, ParamPointer :Integer; ParamName, Param :String; - + dotpos, actualNConds, actualNPhases :Integer; + CondName, CondClass :String; BEGIN Result := 0; @@ -307,11 +317,22 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object ActiveLineSpacingObj := LineSpacingClass[ActorID].GetActiveObj; if (FNConds = ActiveLineSpacingObj.NWires) then begin FLastUnit := ActiveLineSpacingObj.Units; - for i:=1 to FNConds do begin - FX^[i] := ActiveLineSpacingObj.Xcoord[i]; - FY^[i] := ActiveLineSpacingObj.Ycoord[i]; - FUnits^[i] := FLastUnit; + FEquivalentSpacing :=ActiveLineSpacingObj.EquivalentSpacing; + if ActiveLineSpacingObj.EquivalentSpacing then + begin + FEqDist[1] := ActiveLineSpacingObj.EqDistPhPh; + FEqDist[2] := ActiveLineSpacingObj.EqDistPhN; + FEqDist[3] := ActiveLineSpacingObj.AvgHeightPh; + FEqDist[4] := ActiveLineSpacingObj.AvgHeightN; end + else + begin + for i:=1 to FNConds do begin + FX^[i] := ActiveLineSpacingObj.Xcoord[i]; + FY^[i] := ActiveLineSpacingObj.Ycoord[i]; + FUnits^[i] := FLastUnit; + end; + end; end else DoSimpleMsg('LineSpacing object ' + FSpacingType + ' has the wrong number of wires.', 10103); end else @@ -382,6 +403,149 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object NumAmpRatings := InterpretDblArray(Param, NumAmpRatings, Pointer(AmpRatings)); End; 19: FLineType := LineTypeList.Getcommand(Param); + 20: Begin + + // First we need to parse the list of conductors to find None values + // Then we need to redefine Nconds to reallocate + actualNConds := 0; + actualNPhases := 0; + // Line constants type defined by the first found valid conductor + AuxParser[ActorID].CmdString := Parser[ActorID].StrValue; + FCondsUser := Parser[ActorID].StrValue; + For i := 1 to FNConds Do + begin + AuxParser[ActorID].NextParam; + if CompareText(AuxParser[ActorID].StrValue, 'None')=0 then continue; + if CompareText(AuxParser[ActorID].StrValue, '')=0 then continue; + actualNConds := actualNConds + 1; + if i <= FNPhases then actualNPhases := actualNPhases + 1; + end; + + j := 0; + if FNConds <> NConds then + begin + NConds := actualNConds; // allocates + Nphases := actualNPhases; + LineSpacingClass[ActorID].SetActive(FSpacingType); + ActiveLineSpacingObj := LineSpacingClass[ActorID].GetActiveObj; + FLastUnit := ActiveLineSpacingObj.Units; + FEquivalentSpacing := ActiveLineSpacingObj.EquivalentSpacing; + AuxParser[ActorID].CmdString := Parser[ActorID].StrValue; + for i:=1 to ActiveLineSpacingObj.NWires do begin + AuxParser[ActorID].NextParam; + if CompareText(AuxParser[ActorID].StrValue, 'None')=0 then continue; + if CompareText(AuxParser[ActorID].StrValue, '')=0 then continue; + j := j + 1; + if not ActiveLineSpacingObj.EquivalentSpacing then + begin + FX^[j] := ActiveLineSpacingObj.Xcoord[i]; + FY^[j] := ActiveLineSpacingObj.Ycoord[i]; + FUnits^[j] := FLastUnit; + end; + end; + if ActiveLineSpacingObj.EquivalentSpacing then + begin + FEqDist[1] := ActiveLineSpacingObj.EqDistPhPh; + FEqDist[2] := ActiveLineSpacingObj.EqDistPhN; + FEqDist[3] := ActiveLineSpacingObj.AvgHeightPh; + FEqDist[4] := ActiveLineSpacingObj.AvgHeightN; + end; + + end; + + istart := 1; + istop := FNConds; + + // Line constants type defined by the first found valid conductor + AuxParser[ActorID].CmdString := Parser[ActorID].StrValue; + for i := istart to istop do begin + AuxParser[ActorID].NextParam; + while CompareText(AuxParser[ActorID].StrValue, 'None')=0 do + begin + AuxParser[ActorID].NextParam; + end; + if AuxParser[ActorID].StrValue = '' then continue; + + CondClass := ''; + CondName := ''; + dotpos := Pos('.', AuxParser[ActorID].StrValue); + CASE dotpos OF + 0:begin + DoSimpleMsg ('You must define the conductor class for all the valid conductors in the "conductors" array (LineGeometry.'+name+').', 10103); + exit; + end; + ELSE Begin + CondClass := Copy(AuxParser[ActorID].StrValue, 1, dotpos-1); + CondName := Copy(AuxParser[ActorID].StrValue, dotpos+1, Length(AuxParser[ActorID].StrValue)); + End; + End; + if LowerCase(CondClass) = 'wiredata' then + begin + if i <= NPhases then ChangeLineConstantsType(Overhead); + break; + end + else if LowerCase(CondClass) = 'cndata' then + begin + if i <= NPhases then ChangeLineConstantsType(ConcentricNeutral); + break; + end + else if LowerCase(CondClass) = 'tsdata' then + begin + if i <= NPhases then ChangeLineConstantsType(TapeShield); + break; + end + else + begin + DoSimpleMsg ('You must use valid conductor classes (wiredata, cndata, tsdata) for all the conductors in the "conductors" array (LineGeometry.'+name+').', 10103); + exit; + end; + + end; + + + AuxParser[ActorID].CmdString := Parser[ActorID].StrValue; + for i := istart to istop do begin + AuxParser[ActorID].NextParam; // ignore any parameter name not expecting any + while CompareText(AuxParser[ActorID].StrValue, 'None')=0 do + begin + AuxParser[ActorID].NextParam; + end; + if AuxParser[ActorID].StrValue = '' then continue; + + CondClass := ''; + CondName := ''; + dotpos := Pos('.', AuxParser[ActiveActor].StrValue); + CASE dotpos OF + 0:begin + DoSimpleMsg ('You must define the conductor class for all the valid conductors in the "conductors" array (LineGeometry.'+name+').', 10103); + exit; + end; + ELSE Begin + CondClass := Copy(AuxParser[ActiveActor].StrValue, 1, dotpos-1); + CondName := Copy(AuxParser[ActiveActor].StrValue, dotpos+1, Length(AuxParser[ActiveActor].StrValue)); + End; + End; + if LowerCase(CondClass) = 'wiredata' then WireDataClass[ActorID].Code := CondName + else if LowerCase(CondClass) = 'cndata' then CNDataClass[ActorID].code := CondName + else if LowerCase(CondClass) = 'tsdata' then TSDataClass[ActorID].code := CondName; + FCondName[i] := CondName; + + if Assigned(ActiveConductorDataObj) then begin + FWireData^[i] := ActiveConductorDataObj; + if (i=1) then begin + If (ActiveConductorDataObj.NormAmps > 0.0) and (Normamps = 0.0) Then Normamps := ActiveConductorDataObj.NormAmps; + If (ActiveConductorDataObj.Emergamps > 0.0) and (Emergamps = 0.0) Then Emergamps := ActiveConductorDataObj.EmergAmps; + If (ActiveConductorDataObj.NumAmpRatings > 1) and (NumAmpRatings = 1) Then NumAmpRatings := ActiveConductorDataObj.NumAmpRatings; + If (length(ActiveConductorDataObj.AmpRatings) > 1) and (length(AmpRatings) = 1) + Then Begin + setlength(AmpRatings,NumAmpRatings); + AmpRatings := ActiveConductorDataObj.AmpRatings; + End; + end; + end else + DoSimpleMsg('Conductor Object "' + FCondName[i] + '" not defined. Must be previously defined.', 10103) + end + End; ELSE // Inherited parameters ClassEdit(ActiveLineGeometryObj, Parampointer - NumPropsThisClass) @@ -423,7 +587,7 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object END; Case ParamPointer of - 1,4..7,11..16: DataChanged := TRUE; + 1,4..7,11..16,20: DataChanged := TRUE; END; ParamName := Parser[ActorID].NextParam; @@ -449,12 +613,15 @@ constructor TLineGeometry.Create; // Creates superstructure for all Line object NConds := OtherLineGeometry.NWires; // allocates FNphases := OtherLineGeometry.FNphases; FSpacingType := OtherLineGeometry.FSpacingType; + FEquivalentSpacing := OtherLineGeometry.FEquivalentSpacing; For i := 1 to FNConds Do FPhaseChoice^[i] := OtherLineGeometry.FPhaseChoice^[i]; For i := 1 to FNConds Do FCondName^[i] := OtherLineGeometry.FCondName^[i]; For i := 1 to FNConds Do FWireData^[i] := OtherLineGeometry.FWireData^[i]; For i := 1 to FNConds Do FX^[i] := OtherLineGeometry.FX^[i]; For i := 1 to FNConds Do FY^[i] := OtherLineGeometry.FY^[i]; + For i := 1 to 4 Do FEqDist[i] := OtherLineGeometry.FEqDist[i]; For i := 1 to FNConds Do FUnits^[i] := OtherLineGeometry.FUnits^[i]; + FLastUnit := OtherLineGeometry.FLastUnit; // Useful if template geometry uses a spacing DataChanged := TRUE; NormAmps := OtherLineGeometry.NormAmps; EmergAmps := OtherLineGeometry.EmergAmps; @@ -528,6 +695,8 @@ constructor TLineGeometryObj.Create(ParClass:TDSSClass; const LineGeometryName:S FWireData := nil; FX := nil; FY := nil; + FEqDist := nil; + FEquivalentSpacing := FALSE; Funits := nil; FLineData := Nil; FSpacingType := ''; @@ -563,6 +732,7 @@ destructor TLineGeometryObj.Destroy; Reallocmem(Fwiredata, 0); Reallocmem(FY, 0); Reallocmem(FX, 0); + SetLength(FEqDist, 0); Reallocmem(Funits, 0); Reallocmem(FPhaseChoice, 0); @@ -575,6 +745,8 @@ destructor TLineGeometryObj.Destroy; Var i,j :Integer; + cond_type :Integer; + conductor_array :String; Begin Inherited DumpProperties(F, Complete); @@ -584,15 +756,50 @@ destructor TLineGeometryObj.Destroy; For i := 1 to 2 Do Begin Writeln(F,'~ ',PropertyName^[i],'=',GetPropertyValue(i)); End; - For j := 1 to FNConds Do Begin - ActiveCond := j; - Writeln(F,'~ ',PropertyName^[3],'=',GetPropertyValue(3)); - Writeln(F,'~ ',PropertyName^[4],'=',GetPropertyValue(4)); - Writeln(F,'~ ',PropertyName^[5],'=',GetPropertyValue(5)); - Writeln(F,'~ ',PropertyName^[6],'=',GetPropertyValue(6)); - Writeln(F,'~ ',PropertyName^[7],'=',GetPropertyValue(7)); + If not FEquivalentSpacing then + begin + // Avoid spacing and wire arrays as the information has been dumped + // already on each of the conductor positions. + For j := 1 to FNConds Do Begin + ActiveCond := j; + Writeln(F,'~ ',PropertyName^[3],'=',GetPropertyValue(3)); + + if FWireData^[FActiveCond] is TCNDataObj then cond_type := 13 // cncable + else if FWireData^[FActiveCond] is TTSDataObj then cond_type := 14 // tscable + else cond_type := 4; // wire + + Writeln(F,'~ ',PropertyName^[cond_type],'=',GetPropertyValue(cond_type)); + Writeln(F,'~ ',PropertyName^[5],'=',GetPropertyValue(5)); + Writeln(F,'~ ',PropertyName^[6],'=',GetPropertyValue(6)); + Writeln(F,'~ ',PropertyName^[7],'=',GetPropertyValue(7)); + End; + end + else + begin + Writeln(F,'~ ',PropertyName^[11],'=',GetPropertyValue(11)); + if FCondsUser <> '' then // Use the saved conductors array string as it will include None values that would get ignored otherwise. + Writeln(F,'~ ', PropertyName^[20], '=[',FCondsUser,']') + else + begin + conductor_array:= ''; + For j := 1 to FNConds Do Begin + if FWireData^[j] is TCNDataObj then conductor_array := conductor_array + 'cndata.' + FCondName^[j] + ',' // cncable + else if FWireData^[j] is TTSDataObj then conductor_array := conductor_array + 'tsdata.' + FCondName^[j] + ',' // tscable + else conductor_array := conductor_array + 'wiredata.' + FCondName^[j] + ','; // wire + end; + Writeln(F,'~ ', PropertyName^[20], '=[',conductor_array,']'); + end; + + end; + + + + For i := 8 to 10 Do Begin + Writeln(F,'~ ',PropertyName^[i],'=',GetPropertyValue(i)); End; - For i := 8 to NumProperties Do Begin + + For i := 17 to 19 Do Begin + Writeln(F,'~ ',PropertyName^[i],'=',GetPropertyValue(i)); End; @@ -609,6 +816,8 @@ function TLineGeometryObj.GetPropertyValue(Index: Integer): String; begin CASE Index OF + 1 : Result := Format('%d',[FNConds]); + 2 : Result := Format('%d',[FNphases]); 3 : Result := Format('%d',[FActiveCond]); 4,13,14: Result := FCondName^[FActiveCond]; 5 : Result := Format('%-g',[FX^[FActiveCond]]); @@ -629,6 +838,11 @@ function TLineGeometryObj.GetPropertyValue(Index: Integer): String; Result := Result + ']'; End; 19: Result := LineTypeList.Get(FLineType); + 20: Begin // Similar to 12,15,16 but with conductor data class prepended + Result := '['; + for i:= 1 to FNConds do Result := Result + FCondName^[i] + ' '; + Result := Result + ']'; + End; ELSE // Inherited parameters Result := Inherited GetPropertyValue(Index); @@ -838,6 +1052,7 @@ procedure TLineGeometryObj.set_Nconds(const Value: Integer); Reallocmem( FWireData, Sizeof(FWireData^[1]) *FNconds); Reallocmem( FX, Sizeof(FX^[1]) *FNconds); Reallocmem( FY, Sizeof(FY^[1]) *FNconds); + SetLength(FEqDist, 4); // always four elements Reallocmem( FUnits, Sizeof(Funits^[1]) *FNconds); Reallocmem( FPhaseChoice, Sizeof(FPhaseChoice^[1]) *FNconds); @@ -858,6 +1073,12 @@ procedure TLineGeometryObj.set_Nconds(const Value: Integer); end; // For i := 1 to FNconds Do FPhaseChoice^[i] := Unknown; // This was defined previously (ChangeLineConstantsType) // and overrides previous allocations + + For i := 1 to 4 Do + Begin + FEqDist[i] := 0.0; + end; + FLastUnit := UNITS_FT; end; @@ -896,9 +1117,22 @@ procedure TLineGeometryObj.UpdateLineGeometryData(f:Double); tsd : TTSDataObj; begin + FLineData.EquivalentSpacing := FEquivalentSpacing; + if FEquivalentSpacing then + begin + // Always four elements: EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + FLineData.EqDist[1, FLastUnit] := FEqDist[1]; + FLineData.EqDist[2, FLastUnit] := FEqDist[2]; + FLineData.EqDist[3, FLastUnit] := FEqDist[3] + FLineData.heightOffset * To_Meters(FLineData.userHeightUnit) * From_Meters(FLastUnit); + FLineData.EqDist[4, FLastUnit] := FEqDist[4] + FLineData.heightOffset * To_Meters(FLineData.userHeightUnit) * From_Meters(FLastUnit); + end; For i := 1 to FNconds Do Begin - FLineData.X[i, Funits^[i]] := FX^[i]; - FLineData.Y[i, Funits^[i]] := FY^[i] + FLineData.heightOffset * To_Meters(FLineData.userHeightUnit) * From_Meters(Funits^[i]); + if not FEquivalentSpacing then + begin + FLineData.X[i, Funits^[i]] := FX^[i]; + FLineData.Y[i, Funits^[i]] := FY^[i] + FLineData.heightOffset * To_Meters(FLineData.userHeightUnit) * From_Meters(Funits^[i]); + end; + FLineData.radius[i, FWireData^[i].RadiusUnits] := FWireData^[i].Radius; FLineData.capradius[i, FWireData^[i].RadiusUnits] := FWireData^[i].capRadius; FLineData.GMR[i, FWireData^[i].GMRUnits] := FWireData^[i].GMR; @@ -987,9 +1221,12 @@ procedure TLineGeometryObj.LoadSpacingAndWires(Spc: TLineSpacingObj; Wires: pCon j := j + 1; FCondName^[j] := Wires^[i].Name; FWireData^[j] := Wires^[i]; - FX^[j] := Spc.Xcoord[i]; - FY^[j] := Spc.Ycoord[i]; - FUnits^[j] := Spc.Units; + if not Spc.EquivalentSpacing then + begin + FX^[j] := Spc.Xcoord[i]; + FY^[j] := Spc.Ycoord[i]; + FUnits^[j] := Spc.Units; + end; if ((Wires^[i].NormAmps < NormAmps) or (NormAmps = 0)) and (j <= FNPhases) then begin NormAmps := Wires^[i].NormAmps; @@ -998,6 +1235,16 @@ procedure TLineGeometryObj.LoadSpacingAndWires(Spc: TLineSpacingObj; Wires: pCon end; end; + if Spc.EquivalentSpacing then + begin + FEqDist[1] := Spc.EqDistPhPh; + FEqDist[2] := Spc.EqDistPhN; + FEqDist[3] := Spc.AvgHeightPh; + FEqDist[4] := Spc.AvgHeightN; + FLastUnit := Spc.Units; + end; + + FEquivalentSpacing := Spc.EquivalentSpacing; DataChanged := TRUE; diff --git a/Version8/Source/General/LineSpacing.pas b/Version8/Source/General/LineSpacing.pas index 051a18d0f..46e5be41a 100644 --- a/Version8/Source/General/LineSpacing.pas +++ b/Version8/Source/General/LineSpacing.pas @@ -48,6 +48,11 @@ TLineSpacingObj = class(TDSSObject) FX :pDoubleArray; FY :pDoubleArray; FUnits :Integer; + FEqDistPhPh :Double; + FEqDistPhN :Double; + FAvgHeightPh :Double; + FAvgHeightN :Double; + FEquivalentSpacing :Boolean; DataChanged :Boolean; procedure set_Nwires(const Value: Integer); @@ -68,9 +73,14 @@ TLineSpacingObj = class(TDSSObject) // CIM XML accessors Property Xcoord[i:Integer]: Double Read Get_FX; Property Ycoord[i:Integer]: Double Read Get_FY; + Property EqDistPhPh: Double Read FEqDistPhPh; + Property EqDistPhN: Double Read FEqDistPhN; + Property AvgHeightPh: Double Read FAvgHeightPh; + Property AvgHeightN: Double Read FAvgHeightN; Property NWires: Integer Read FNConds Write set_Nwires; Property NPhases: Integer Read FNPhases; Property Units: Integer Read FUnits; + Property EquivalentSpacing: Boolean Read FEquivalentSpacing; end; VAR @@ -80,7 +90,7 @@ implementation USES ParserDel, DSSClassDefs, DSSGlobals, Ucomplex, Utilities, LineUNits; -Const NumPropsThisClass = 5; +Const NumPropsThisClass = 10; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - constructor TLineSpacing.Create; // Creates superstructure for all Line objects @@ -117,13 +127,22 @@ constructor TLineSpacing.Create; // Creates superstructure for all Line objects PropertyName^[3] := 'x'; PropertyName^[4] := 'h'; PropertyName^[5] := 'units'; - + PropertyName^[6] := 'detailed'; + PropertyName^[7] := 'EqDistPhPh'; + PropertyName^[8] := 'EqDistPhN'; + PropertyName^[9] := 'AvgPhaseHeight'; + PropertyName^[10] := 'AvgNeutralHeight'; PropertyHelp^[1] := 'Number of wires in this geometry. Default is 3. Triggers memory allocations. Define first!'; PropertyHelp^[2] := 'Number of retained phase conductors. If less than the number of wires, list the retained phase coordinates first.'; PropertyHelp^[3] := 'Array of wire X coordinates.'; PropertyHelp^[4] := 'Array of wire Heights.'; PropertyHelp^[5] := 'Units for x and h: {mi|kft|km|m|Ft|in|cm } Initial default is "ft", but defaults to last unit defined'; + PropertyHelp^[6] := '{Yes/True | No/False} Default = Yes. Determines whether the spacing uses a detailed cross-section coordinates with x and h arrays (Yes/True), or uses equivalent spacing fields (No/False). The equivalent spacing fields are EqDistPhPh, EqDistPhN, AvgPhaseHeight and AvgNeutralHeight.'; + PropertyHelp^[7] := 'Equivalent distance between phase conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates. '; + PropertyHelp^[8] := 'Equivalent distance between phase and neutral conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates.'; + PropertyHelp^[9] := 'Average height of phase conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates.'; + PropertyHelp^[10]:= 'Average height of neutral conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates.'; ActiveProperty := NumPropsThisClass; inherited DefineProperties; // Add defs of inherited properties to bottom of list @@ -190,6 +209,11 @@ constructor TLineSpacing.Create; // Creates superstructure for all Line objects 3: InterpretArray (Param, X); 4: InterpretArray (Param, H); 5: FUnits := GetUnitsCode(Param); + 6: FEquivalentSpacing := not InterpretYesNo(Param); + 7: FEqDistPhPh := Parser[ActorID].DblValue; + 8: FEqDistPhN := Parser[ActorID].DblValue; + 9: FAvgHeightPh := Parser[ActorID].DblValue; + 10: FAvgHeightN := Parser[ActorID].DblValue; ELSE // Inherited parameters ClassEdit(ActiveLineSpacingObj, Parampointer - NumPropsThisClass) @@ -223,6 +247,11 @@ constructor TLineSpacing.Create; // Creates superstructure for all Line objects FNPhases := OtherLineSpacing.NPhases; For i := 1 to FNConds Do FX^[i] := OtherLineSpacing.FX^[i]; For i := 1 to FNConds Do FY^[i] := OtherLineSpacing.FY^[i]; + FEquivalentSpacing := OtherLineSpacing.EquivalentSpacing; + FEqDistPhPh := OtherLineSpacing.EqDistPhPh; + FEqDistPhN := OtherLineSpacing.EqDistPhN; + FAvgHeightPh := OtherLineSpacing.AvgHeightPh; + FAvgHeightN := OtherLineSpacing.AvgHeightN; FUnits := OtherLineSpacing.FUnits; DataChanged := TRUE; For i := 1 to ParentClass.NumProperties Do PropertyValue[i] := OtherLineSpacing.PropertyValue[i]; @@ -290,6 +319,11 @@ constructor TLineSpacingObj.Create(ParClass:TDSSClass; const LineSpacingName:Str Funits := UNITS_FT; NWires := 3; // Allocates terminals FNPhases := 3; + FEqDistPhPh := 0.0; + FEqDistPhN := 0.0; + FAvgHeightPh := 0.0; + FAvgHeightN := 0.0; + FEquivalentSpacing := FALSE; InitPropertyValues(0); END; @@ -316,7 +350,9 @@ destructor TLineSpacingObj.Destroy; WITH ParentClass Do Begin - For i := 1 to 5 Do Begin + For i := 1 to 10 Do Begin +// if (not FEquivalentSpacing and (i > 5)) then continue +// else if (FEquivalentSpacing and ((i = 3) or (i = 4))) then continue; Writeln(F,'~ ',PropertyName^[i],'=',GetPropertyValue(i)); End; End; @@ -369,6 +405,11 @@ procedure TLineSpacingObj.InitPropertyValues(ArrayOffset: Integer); PropertyValue[3] := '0'; PropertyValue[4] := '32'; PropertyValue[5] := 'ft'; + PropertyValue[6] := 'Yes'; + PropertyValue[7] := '0'; + PropertyValue[8] := '0'; + PropertyValue[9] := '0'; + PropertyValue[10] := '0'; inherited InitPropertyValues(NumPropsThisClass); diff --git a/VersionC/General/CNTSLineConstants.cpp b/VersionC/General/CNTSLineConstants.cpp index 099f31115..fa2b5610b 100644 --- a/VersionC/General/CNTSLineConstants.cpp +++ b/VersionC/General/CNTSLineConstants.cpp @@ -253,7 +253,11 @@ void TCNTSLineConstants::Calc(double f) int stop1 = 0; for(stop1 = i - 1, j = 1; j <= stop1; j++) { - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if (!FEquivalentSpacing) {Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1]));} + else{ + if ((j <= FNumPhases) and (i > FNumPhases)) { Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + } Zmat->SetElemsym(i, j, cadd(cmulreal(LFactor, log(1.0 / Dij)), Get_Ze(i, j))); } } @@ -266,7 +270,11 @@ void TCNTSLineConstants::Calc(double f) for(stop1 = i - 1, j = 1; j <= stop1; j++) { // CN/TS to other CN/TS idxj = j + FNumConds; - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if (!FEquivalentSpacing) {Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1]));} + else{ + if ((j <= FNumPhases) and (i > FNumPhases)) { Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + } Zmat->SetElemsym(idxi, idxj, cadd(cmulreal(LFactor, log(1.0 / Dij)), Get_Ze(i, j))); } for(stop1 = FNumConds, j = 1; j <= stop1; j++) @@ -282,7 +290,11 @@ void TCNTSLineConstants::Calc(double f) else // CN to another phase or bare neutral { - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if (!FEquivalentSpacing) {Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1]));} + else{ + if ((i <= FNumPhases) and (j > FNumPhases)) { Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + } Dij = pow(pow(Dij, (double) FkStrand[i - 1]) - pow(RadCN, (double) FkStrand[i - 1]), 1.0 / FkStrand[i - 1]); } } @@ -296,7 +308,11 @@ void TCNTSLineConstants::Calc(double f) else // TS to another phase or bare neutral { - Dij = sqrt(pow(FX[i - 1] - FX[j - 1], 2) + pow(FY[i - 1] - FY[j - 1], 2)); + if (!FEquivalentSpacing) {Dij = sqrt(pow(FX[i - 1] - FX[j - 1], 2) + pow(FY[i - 1] - FY[j - 1], 2));} + else{ + if ((i <= FNumPhases) and (j > FNumPhases)) {Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + } } } Zmat->SetElemsym(idxi, idxj, cadd(cmulreal(LFactor, log(1.0 / Dij)), Get_Ze(i, j))); diff --git a/VersionC/General/CableConstants.cpp b/VersionC/General/CableConstants.cpp index 48def3f5e..8d3bad544 100644 --- a/VersionC/General/CableConstants.cpp +++ b/VersionC/General/CableConstants.cpp @@ -77,25 +77,52 @@ bool TCableConstants::ConductorsInSameSpace(String& ErrorMessage) End; End; */ - for(stop = FNumConds, i = 1; i <= stop; i++) - { - int stop1 = 0; - if(i <= FNumPhases) - Ri = Fradius[i - 1]; - else - Ri = 0.5 * FDiaCable[i - 1]; - for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) + if (FEquivalentSpacing) { + for(stop = FNumConds, i = 1; i <= stop; i++) { - if(j <= FNumPhases) - Rj = Fradius[j - 1]; + int stop1 = 0; + if(i <= FNumPhases) + Ri = Fradius[i - 1]; + else + Ri = 0.5 * FDiaCable[i - 1]; + for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) + { + if(j <= FNumPhases) + Rj = Fradius[j - 1]; + else + Rj = 0.5 * FDiaCable[j - 1]; + if ((i <= FNumPhases) and (j > FNumPhases)) {Dij = FEqDist[2 - 1];} + else {Dij = FEqDist[1 - 1];} + if(Dij < (Ri + Rj)) + { + result = true; + ErrorMessage = Format("Cable conductors %d and %d occupy the same space.", i, j); + return result; + } + } + } + } + else { + for(stop = FNumConds, i = 1; i <= stop; i++) + { + int stop1 = 0; + if(i <= FNumPhases) + Ri = Fradius[i - 1]; else - Rj = 0.5 * FDiaCable[j - 1]; - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); - if(Dij < (Ri + Rj)) + Ri = 0.5 * FDiaCable[i - 1]; + for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) { - result = true; - ErrorMessage = Format("Cable conductors %d and %d occupy the same space.", i, j); - return result; + if(j <= FNumPhases) + Rj = Fradius[j - 1]; + else + Rj = 0.5 * FDiaCable[j - 1]; + Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if(Dij < (Ri + Rj)) + { + result = true; + ErrorMessage = Format("Cable conductors %d and %d occupy the same space.", i, j); + return result; + } } } } diff --git a/VersionC/General/LineConstants.cpp b/VersionC/General/LineConstants.cpp index a103d95a9..f96f50968 100644 --- a/VersionC/General/LineConstants.cpp +++ b/VersionC/General/LineConstants.cpp @@ -98,7 +98,11 @@ void TLineConstants::Calc(double f) int stop1 = 0; for(stop1 = i - 1, j = 1; j <= stop1; j++) { - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if (!FEquivalentSpacing) {Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1]));} + else { + if ((j <= FNumPhases) and (i > FNumPhases)) {Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + } FZmatrix->SetElemsym(i, j, cadd(cmulreal(LFactor, log(1.0 / Dij)), Get_Ze(i, j))); } } @@ -112,15 +116,28 @@ void TLineConstants::Calc(double f) in case of bundled conductors can be specified different in Wiredata.*/ for(stop = FNumConds, i = 1; i <= stop; i++) { - FYCmatrix->SetElement(i, i, cmplx(0.0, Pfactor * log(2.0 * FY[i - 1] / Fcapradius[i - 1]))); + if (!FEquivalentSpacing) {FYCmatrix->SetElement(i, i, cmplx(0.0, Pfactor * log(2.0 * FY[i - 1] / Fcapradius[i - 1])));} + else { + if (i > FNumPhases) {FYCmatrix->SetElement(i, i, cmplx(0.0, Pfactor * log(2.0 * FEqDist[4 - 1] / Fcapradius[i - 1])));} + else {FYCmatrix->SetElement(i, i, cmplx(0.0, Pfactor * log(2.0 * FEqDist[3 - 1] / Fcapradius[i - 1])));} + } } for(stop = FNumConds, i = 1; i <= stop; i++) { int stop1 = 0; for(stop1 = i - 1, j = 1; j <= stop1; j++) { - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); - Dijp = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] + FY[j - 1])); // distance to image j + if (!FEquivalentSpacing) { + Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + Dijp = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] + FY[j - 1])); // distance to image j + } else { + if ((j <= FNumPhases) and (i > FNumPhases)) {Dij = FEqDist[2 - 1];} // EqDistPhN + else {Dij = FEqDist[1 - 1];} // EqDistPhPh (including N-N conductorss) + + if ((j <= FNumPhases) and (i > FNumPhases)) {Dijp = (FEqDist[3 - 1] + FEqDist[4 - 1]);} // AvgHeightPhase + AvgHeightNeutral + else if ((i <= FNumPhases) and (j <= FNumPhases)) { Dijp = (2 * FEqDist[3 - 1]);} // 2 * AvgHeightPhase + else {Dijp = (2 * FEqDist[4 - 1]);} // 2 * AvgHeightNeutral + } FYCmatrix->SetElemsym(i, j, cmplx(0.0, Pfactor * log(Dijp / Dij))); } } @@ -142,31 +159,58 @@ bool TLineConstants::ConductorsInSameSpace(string& ErrorMessage) int stop = 0; result = false; - /*Check for 0 Y coordinate*/ - for(stop = FNumConds, i = 1; i <= stop; i++) - { - if(FY[i - 1] <= 0.0) + if (FEquivalentSpacing) { + /*Check for 0 Y coordinate*/ + if(FEqDist[3 - 1] <= 0.0 || FEqDist[4 - 1] <= 0.0) { result = true; - ErrorMessage = Format("Conductor %d height must be > 0. ",i); + ErrorMessage = "Conductor average heights (overhead equivalent spacing) must be > 0."; return result; } + /*Check for overlapping conductors*/ + for(stop = FNumConds, i = 1; i <= stop; i++) + { + int stop1 = 0; + for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) + { + if ((i <= FNumPhases) and (j > FNumPhases)) {Dij = FEqDist[2 - 1];} + else {Dij = FEqDist[1 - 1];} + if(Dij < (Fradius[i - 1] + Fradius[j - 1])) + { + result = true; + ErrorMessage = Format("Conductors %d and %d occupy the same space.",i, j); + return result; + } + } + } } - - /*Check for overlapping conductors*/ - for(stop = FNumConds, i = 1; i <= stop; i++) - { - int stop1 = 0; - for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) + else{ + /*Check for 0 Y coordinate*/ + for(stop = FNumConds, i = 1; i <= stop; i++) { - Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); - if(Dij < (Fradius[i - 1] + Fradius[j - 1])) + if(FY[i - 1] <= 0.0) { result = true; - ErrorMessage = Format("Conductors %d and %d occupy the same space.",i, j); + ErrorMessage = Format("Conductor %d height must be > 0. ",i); return result; } } + + /*Check for overlapping conductors*/ + for(stop = FNumConds, i = 1; i <= stop; i++) + { + int stop1 = 0; + for(stop1 = FNumConds, j = i + 1; j <= stop1; j++) + { + Dij = sqrt(sqr(FX[i - 1] - FX[j - 1]) + sqr(FY[i - 1] - FY[j - 1])); + if(Dij < (Fradius[i - 1] + Fradius[j - 1])) + { + result = true; + ErrorMessage = Format("Conductors %d and %d occupy the same space.",i, j); + return result; + } + } + } } return result; } @@ -194,6 +238,9 @@ TLineConstants::TLineConstants(int NumConductors) FRDC.resize(FNumConds, 0); Frac.resize(FNumConds, 0); + FEqDist.resize(4, 0); + FEquivalentSpacing = false; + /*Initialize to not set*/ for(stop = FNumConds, i = 1; i <= stop; i++) @@ -252,6 +299,13 @@ double TLineConstants::Get_FheightOffset() return result; } +bool TLineConstants::Get_FEquivalentSpacing() +{ + bool result = false; + result = FEquivalentSpacing; + return result; +} + double TLineConstants::Get_Capradius(int i, int Units) { double result = 0.0; @@ -300,6 +354,13 @@ double TLineConstants::Get_Y(int i, int Units) result = FY[i - 1] * From_Meters(Units); return result; } + +double TLineConstants::Get_FEqDist(int i, int Units) +{ + double result = 0.0; + result = FEqDist[i - 1] * From_Meters(Units); // This array has only four elements PhPh, PhN, AvgHeightPh, AvgHeightN + return result; +} /*Makes a new YCmatrix and correct for lengths and units as it copies*/ /*Uses the reduced Zmatrix by default if it exists*/ @@ -343,13 +404,26 @@ complex TLineConstants::Get_Ze(int i, int j) double Dij = 0.0; double Fyi = 0.0; double Fyj = 0.0; + double Fxi_Fxj = 0.0; double term1 = 0.0; double term2 = 0.0; double term3 = 0.0; double term4 = 0.0; double term5 = 0.0; - Fyi = Abs(FY[i - 1]); - Fyj = Abs(FY[j - 1]); + + if (! FEquivalentSpacing) {Fyi = Abs(FY[i - 1]);} + else if (i <= FNumPhases) {Fyi = Abs(FEqDist[3 - 1]);} + else {Fyi = Abs(FEqDist[4 - 1]);} + + if (!FEquivalentSpacing) {Fyj = Abs(FY[j - 1]);} + else if (j <= FNumPhases) {Fyj = Abs(FEqDist[3 - 1]);} + else {Fyj = Abs(FEqDist[4 - 1]);} + + // If the spacing uses equivalent distance, assume the equivalent distance is on the X axis. + if (!FEquivalentSpacing) {Fxi_Fxj = FX[i - 1] - FX[j - 1];} + else if (((i <= FNumPhases) && (j <= FNumPhases)) || ((i > FNumPhases) && (j > FNumPhases))) {Fxi_Fxj = FEqDist[1 - 1];} + else {Fxi_Fxj = FEqDist[2 - 1];} + switch(ActiveEarthModel[ActiveActor]) { case SIMPLECARSON: @@ -368,7 +442,7 @@ complex TLineConstants::Get_Ze(int i, int j) } else { - Dij = sqrt(sqr(Fyi + Fyj) + sqr(FX[i - 1] - FX[j - 1])); + Dij = sqrt(sqr(Fyi + Fyj) + sqr(Fxi_Fxj)); thetaij = acos((Fyi + Fyj) / Dij); } mij = 2.8099e-3 * Dij * sqrt(FFrequency / FrhoEarth); @@ -390,7 +464,7 @@ complex TLineConstants::Get_Ze(int i, int j) if(i != j) { hterm = cadd(cmplx(Fyi + Fyj, 0.0), cmulreal(cinv(Fme), 2.0)); - xterm = cmplx(FX[i - 1] - FX[j - 1], 0.0); + xterm = cmplx(Fxi_Fxj, 0.0); logArg = csqrt(cadd(cmul(hterm, hterm), cmul(xterm, xterm))); result = cmul(cmplx(0.0, Fw * mu0 / TwoPi), CLn(logArg)); } @@ -615,6 +689,15 @@ void TLineConstants::Set_FuserHeightUnit(int Value) } } +void TLineConstants::Set_FEquivalentSpacing(bool Value) +{ + if (Value != FEquivalentSpacing) + { + FEquivalentSpacing = Value; + FRhoChanged = true; // using this for both EpsRMedium, Rho, heightOffset and FuserHeightUnit and for this one as well + } +} + void TLineConstants::Set_GMR(int i, int Units, double Value) { if((i > 0) && (i <= FNumConds)) @@ -664,6 +747,12 @@ void TLineConstants::Set_Y(int i, int Units, double Value) FY[i - 1] = Value * To_Meters(Units); } +void TLineConstants::Set_FEqDist(int i, int Units, double Value) +{ + if (i > 4) {return;} // This array has only four elements PhPh, PhN, AvgHeightPh, AvgHeightN + FEqDist[i - 1] = Value * To_Meters(Units); +} + void TLineConstants::AddHeightOffset() { for (int i = 0; i < FNumConds; i++) diff --git a/VersionC/General/LineConstants.h b/VersionC/General/LineConstants.h index 93212b800..855b5b455 100644 --- a/VersionC/General/LineConstants.h +++ b/VersionC/General/LineConstants.h @@ -51,6 +51,9 @@ class TLineConstants : public System::TObject int FNumPhases; std::vector FX; std::vector FY; + DoubleArray FEqDist; // This array always has four elements EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + bool FEquivalentSpacing; // to tell the calcs when to use equivalent spacing info + std::vector FRDC; // ohms/m std::vector Frac; // ohms/m std::vector FGMR; // m @@ -66,32 +69,36 @@ class TLineConstants : public System::TObject double FrhoEarth; // ohm-m Ucomplex::complex Fme; // factor for earth impedance bool FRhoChanged; - double FEpsRMedium; // unit-less + double FEpsRMedium; // unit-less double FheightOffset; // m int FuserHeightUnit; // m - double Get_GMR(int i, int Units); + double Get_GMR(int i, int Units); double Get_radius(int i, int Units); double Get_Rdc(int i, int Units); double Get_Rac(int i, int Units); double Get_X(int i, int Units); double Get_Y(int i, int Units); + double Get_FEqDist(int i, int Units); Ucmatrix::TcMatrix* Get_YCmatrix(double f, double Lngth, int Units); Ucomplex::complex Get_Ze(int i, int j); Ucomplex::complex Get_Zint(int i); Ucmatrix::TcMatrix* Get_Zmatrix(double f, double Lngth, int Units); double Get_FheightOffset(); + bool Get_FEquivalentSpacing(); void Set_GMR(int i, int Units, double Value); void Set_radius(int i, int Units, double Value); void Set_Rdc(int i, int Units, double Value); void Set_Rac(int i, int Units, double Value); void Set_X(int i, int Units, double Value); void Set_Y(int i, int Units, double Value); + void Set_FEqDist(int i, int Units, double Value); void Set_Frequency(double Value); void Set_Frhoearth(double Value); // m - void Set_FEpsRMedium(double Value); // unit-less - void Set_FheightOffset(double Value); // m - void Set_FuserHeightUnit(int Value); // Whatever the user defined. The height is always saved in meters here + void Set_FEpsRMedium(double Value); // unit-less + void Set_FheightOffset(double Value); // m + void Set_FuserHeightUnit(int Value); // Whatever the user defined. The height is always saved in meters here + void Set_FEquivalentSpacing(bool Value); // This allows you to compute capacitance using a different radius -- for bundled conductors double Get_Capradius(int i, int Units); @@ -109,7 +116,7 @@ class TLineConstants : public System::TObject virtual void Kron(int Norder); // Performs a Kron reduction leaving first Norder rows void Reduce(); // Kron reduce to Numphases only double get_FrhoEarth(); - double get_FEpsRMedium(); + double get_FEpsRMedium(); int get_FNumConds(); int get_FNumPhases(); diff --git a/VersionC/General/LineGeometry.cpp b/VersionC/General/LineGeometry.cpp index 51f0f5749..b1942988d 100644 --- a/VersionC/General/LineGeometry.cpp +++ b/VersionC/General/LineGeometry.cpp @@ -49,7 +49,7 @@ TLineGeometryObj::TLineGeometryObj() {} TLineGeometryObj* ActiveLineGeometryObj = nullptr; -const int NumPropsThisClass = 19; +const int NumPropsThisClass = 20; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Creates superstructure for all Line objects @@ -102,6 +102,7 @@ void TLineGeometry::DefineProperties() PropertyName[17 - 1] = "Seasons"; PropertyName[18 - 1] = "Ratings"; PropertyName[19 - 1] = "LineType"; + PropertyName[20 - 1] = "conductors"; PropertyHelp[1 - 1] = "Number of conductors in this geometry. Default is 3. Triggers memory allocations. Define first!"; PropertyHelp[2 - 1] = "Number of phases. Default =3; All other conductors are considered neutrals and might be reduced out."; PropertyHelp[3 - 1] = "Set this = number of the conductor you wish to define. Default is 1."; @@ -151,6 +152,11 @@ void TLineGeometry::DefineProperties() + CRLF + CRLF + "OpenDSS currently does not use this internally. For whatever purpose the user defines. Default is OH."; + PropertyHelp[20 - 1] = String("Array of conductor names for use in line constants calculation.") + CRLF + + "Must be used in conjunction with the Spacing property." + CRLF + + "Specify the Spacing first, and 'ncond' wires." + CRLF + + "Specify the conductor type followed by the conductor name. e.g., 'conductors=[cndata.cncablename, tsdata.tscablename, wiredata.wirename]'" + + CRLF + + "If a given position in the spacing is not to be used in the line, use 'none' in the entry of the conductors array."; ActiveProperty = NumPropsThisClass - 1; inherited::DefineProperties(); // Add defs of inherited properties to bottom of list } @@ -177,9 +183,16 @@ int TLineGeometry::Edit(int ActorID) { int result = 0; int i = 0; + int j = 0; int iStart = 0; int istop = 0; + int stop = 0; int ParamPointer = 0; + int actualNConds = 0; + int actualNPhases = 0; + int dotpos = 0; + String CondName = ""; + String CondClass = ""; String ParamName; String Param; result = 0; @@ -257,11 +270,19 @@ int TLineGeometry::Edit(int ActorID) { int stop = 0; with0->FLastUnit = ActiveLineSpacingObj->get_FUnits(); - for(stop = with0->Fnconds, i = 1; i <= stop; i++) - { - with0->FX[i - 1] = ActiveLineSpacingObj->Get_FX(i); - with0->FY[i - 1] = ActiveLineSpacingObj->Get_FY(i); - with0->FUnits[i - 1] = with0->FLastUnit; + with0->FEquivalentSpacing = ActiveLineSpacingObj->get_FEquivalentSpacing(); + if (ActiveLineSpacingObj->get_FEquivalentSpacing()) { + with0->FEqDist[1 - 1] = ActiveLineSpacingObj->get_FEqDistPhPh(); + with0->FEqDist[2 - 1] = ActiveLineSpacingObj->get_FEqDistPhN(); + with0->FEqDist[3 - 1] = ActiveLineSpacingObj->get_FAvgHeightPh(); + with0->FEqDist[4 - 1] = ActiveLineSpacingObj->get_FAvgHeightN(); + } else { + for(stop = with0->Fnconds, i = 1; i <= stop; i++) + { + with0->FX[i - 1] = ActiveLineSpacingObj->Get_FX(i); + with0->FY[i - 1] = ActiveLineSpacingObj->Get_FY(i); + with0->FUnits[i - 1] = with0->FLastUnit; + } } } else @@ -382,6 +403,145 @@ int TLineGeometry::Edit(int ActorID) case 19: with0->FLineType = LineTypeList.Getcommand(Param); break; + case 20: + // First we need to parse the list of conductors to find None values + // Then we need to redefine Nconds to reallocate + actualNConds = 0; + actualNPhases = 0; + // Line constants type defined by the first found valid conductor + AuxParser[ActorID]->SetCmdString(Parser[ActorID]->MakeString_()); + with0->FCondsUser = Parser[ActorID]->MakeString_(); + i = 0; + for(i = 1; i <= with0->Fnconds; i++) + { + String dummy = AuxParser[ActorID]->GetNextParam(); + if (CompareText(AuxParser[ActorID]->MakeString_(), "None") == 0) {continue;} + if (CompareText(AuxParser[ActorID]->MakeString_(), "") == 0) {continue;} + actualNConds++; + if (i <= with0->Fnphases) {actualNPhases++;} + } + + j = 0; + if (with0->Fnconds != with0->get_Nconds()) { + with0->Set_Nconds(actualNConds); // allocates + with0->Set_NPhases(actualNPhases); + LineSpacingClass[ActorID]->SetActive(with0->FSpacingType); + ActiveLineSpacingObj = ((TLineSpacingObj*) LineSpacingClass[ActorID]->GetActiveObj()); + with0->FLastUnit = ActiveLineSpacingObj->get_FUnits(); + with0->FEquivalentSpacing = ActiveLineSpacingObj->get_FEquivalentSpacing(); + AuxParser[ActorID]->SetCmdString(Parser[ActorID]->MakeString_()); + for(i = 1; i <= ActiveLineSpacingObj->Fnconds; i++) + { + String dummy = AuxParser[ActorID]->GetNextParam(); + if (CompareText(AuxParser[ActorID]->MakeString_(), "None") == 0) {continue;} + if (CompareText(AuxParser[ActorID]->MakeString_(), "") == 0) {continue;} + j++; + if (!ActiveLineSpacingObj->get_FEquivalentSpacing()) { + with0->FX[j - 1] = ActiveLineSpacingObj->Get_FX(i); + with0->FY[j - 1] = ActiveLineSpacingObj->Get_FY(i); + with0->FUnits[j - 1] = with0->FLastUnit; + } + } + if (ActiveLineSpacingObj->get_FEquivalentSpacing()) { + with0->FEqDist[1 - 1] = ActiveLineSpacingObj->get_FEqDistPhPh(); + with0->FEqDist[2 - 1] = ActiveLineSpacingObj->get_FEqDistPhN(); + with0->FEqDist[3 - 1] = ActiveLineSpacingObj->get_FAvgHeightPh(); + with0->FEqDist[4 - 1] = ActiveLineSpacingObj->get_FAvgHeightN(); + } + } + + iStart = 1; + istop = with0->Fnconds; + stop = 0; + + // Line constants type defined by the first found valid conductor + AuxParser[ActorID]->SetCmdString(Parser[ActorID]->MakeString_()); + for(stop = istop, i = iStart; i <= stop; i++) { + String dummy = AuxParser[ActorID]->GetNextParam(); + while (CompareText(AuxParser[ActorID]->MakeString_(), "None") == 0) { + String dummy = AuxParser[ActorID]->GetNextParam(); + } + if (AuxParser[ActorID]->MakeString_() == "") {continue;} + CondClass = ""; + CondName = ""; + dotpos = Pos(".", AuxParser[ActorID]->MakeString_()); + if(dotpos == 0) + { + DoSimpleMsg(String("") + "You must define the conductor class for all the valid conductors in the 'conductors' array (LineGeometry."+with0->get_Name()+").", 10103); + return result; + } + else { + CondClass = AuxParser[ActorID]->MakeString_().substr(0, dotpos - 1); + CondName = AuxParser[ActorID]->MakeString_().substr(dotpos, AuxParser[ActorID]->MakeString_().length()); + } + if (LowerCase(CondClass) == "wiredata") + { + if (i <= with0->get_Fnphases()) with0->ChangeLineConstantsType(Overhead); + break; + } + else if (LowerCase(CondClass) == "cndata") + { + if (i <= with0->get_Fnphases()) with0->ChangeLineConstantsType(ConcentricNeutral); + break; + } + else if (LowerCase(CondClass) == "tsdata") + { + if (i <= with0->get_Fnphases()) with0->ChangeLineConstantsType(TapeShield); + break; + } + else + { + DoSimpleMsg(String("") + "You must use valid conductor classes (wiredata, cndata, tsdata) for all the conductors in the 'conductors' array (LineGeometry."+with0->get_Name()+").", 10103); + return result; + } + + } + AuxParser[ActorID]->SetCmdString(Parser[ActorID]->MakeString_()); + for(stop = istop, i = iStart; i <= stop; i++) { + String dummy = AuxParser[ActorID]->GetNextParam(); // ignore any parameter name not expecting any + while (CompareText(AuxParser[ActorID]->MakeString_(), "None") == 0) { + String dummy = AuxParser[ActorID]->GetNextParam(); + } + if (AuxParser[ActorID]->MakeString_() == "") {continue;} + CondClass = ""; + CondName = ""; + dotpos = Pos(".", AuxParser[ActorID]->MakeString_()); + if(dotpos == 0) + { + DoSimpleMsg(String("") + "You must define the conductor class for all the valid conductors in the 'conductors' array (LineGeometry."+with0->get_Name()+").", 10103); + return result; + } + else { + CondClass = AuxParser[ActorID]->MakeString_().substr(0, dotpos - 1); + CondName = AuxParser[ActorID]->MakeString_().substr(dotpos, AuxParser[ActorID]->MakeString_().length()); + } + if (LowerCase(CondClass) == "wiredata"){WireDataClass[ActorID]->Set_Code(CondName);} + else if (LowerCase(CondClass) == "cndata"){CNDataClass[ActorID]->Set_Code(CondName);} + else if (LowerCase(CondClass) == "tsdata"){TSDataClass[ActorID]->Set_Code(CondName);} + with0->FCondName[i - 1] = CondName; + + if(ASSIGNED(ActiveConductorDataObj)) { + with0->FWireData[i - 1] = ActiveConductorDataObj; + if(i == 1) + { + if((ActiveConductorDataObj->NormAmps > 0.0) && (with0->NormAmps == 0.0)) + with0->NormAmps = ActiveConductorDataObj->NormAmps; + if((ActiveConductorDataObj->EmergAmps > 0.0) && (with0->EmergAmps == 0.0)) + with0->EmergAmps = ActiveConductorDataObj->EmergAmps; + if((ActiveConductorDataObj->NumAmpRatings > 1) && (with0->NumAmpRatings == 1)) + with0->NumAmpRatings = ActiveConductorDataObj->NumAmpRatings; + if((!ActiveConductorDataObj->AmpRatings.empty()) && (!with0->AmpRatings.empty())) + { + with0->AmpRatings.resize(with0->NumAmpRatings); + with0->AmpRatings = ActiveConductorDataObj->AmpRatings; + } + } + } + else { + DoSimpleMsg(String("Conductor Object \"") + (with0->FCondName)[i] + "\" not defined. Must be previously defined.", 10103); + } + } + break; // Inherited parameters default: ClassEdit(ActiveLineGeometryObj, ParamPointer - NumPropsThisClass); @@ -453,7 +613,7 @@ int TLineGeometry::Edit(int ActorID) } switch(ParamPointer) { - case 1: case 4: case 5: case 6: case 7: case 11: case 12: case 13: case 14: case 15: case 16: + case 1: case 4: case 5: case 6: case 7: case 11: case 12: case 13: case 14: case 15: case 16: case 20: with0->DataChanged = true; break; default: @@ -485,6 +645,7 @@ int TLineGeometry::MakeLike(const String LineName) with0->Set_Nconds(OtherLineGeometry->get_Fnconds()); // allocates with0->Fnphases = OtherLineGeometry->Fnphases; with0->FSpacingType = OtherLineGeometry->FSpacingType; + with0->FEquivalentSpacing = OtherLineGeometry->FEquivalentSpacing; for(stop = with0->Fnconds, i = 1; i <= stop; i++) { with0->FPhaseChoice[i - 1] = OtherLineGeometry->FPhaseChoice[i - 1]; @@ -505,10 +666,15 @@ int TLineGeometry::MakeLike(const String LineName) { (with0->FY)[i - 1] = (OtherLineGeometry->FY)[i - 1]; } + for(stop = 4, i = 1; i <= stop; i++) + { + (with0->FEqDist)[i - 1] = (OtherLineGeometry->FEqDist)[i - 1]; + } for(stop = with0->Fnconds, i = 1; i <= stop; i++) { (with0->FUnits)[i - 1] = (OtherLineGeometry->FUnits)[i - 1]; } + with0->FLastUnit = OtherLineGeometry->FLastUnit; // Useful if template geometry uses a spacing with0->FReduce = OtherLineGeometry->FReduce; with0->DataChanged = true; with0->NormAmps = OtherLineGeometry->NormAmps; @@ -587,6 +753,8 @@ TLineGeometryObj::TLineGeometryObj(TDSSClass* ParClass, const String LineGeometr FWireData.clear(); FX.clear(); FY.clear(); + FEqDist.clear(); + FEquivalentSpacing = false; FUnits.clear(); FLineData = nullptr; FSpacingType = ""; @@ -617,6 +785,7 @@ TLineGeometryObj::~TLineGeometryObj() FWireData.clear(); FY.clear(); FX.clear(); + FEqDist.clear(); FUnits.clear(); // inherited::Destroy(); } @@ -626,6 +795,8 @@ void TLineGeometryObj::DumpProperties(System::TTextRec& f, bool Complete) { int i = 0; int j = 0; + int cond_type = 0; + String conductor_array = ""; inherited::DumpProperties(f, Complete); /*# with ParentClass do */ { @@ -638,16 +809,45 @@ void TLineGeometryObj::DumpProperties(System::TTextRec& f, bool Complete) System::Write(f, "="); System::WriteLn(f, GetPropertyValue(i)); } } - for(stop = Fnconds, j = 1; j <= stop; j++) + if (!FEquivalentSpacing) { + // Avoid spacing and wire arrays as the information has been dumped + // already on each of the conductor positions + for(stop = Fnconds, j = 1; j <= stop; j++) + { + set_ActiveCond(j); + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[3 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(3)); } + + if (dynamic_cast (FWireData[FActiveCond - 1]) != nullptr) {cond_type = 13;} // cncable + else if (dynamic_cast (FWireData[FActiveCond - 1]) != nullptr) {cond_type = 14;} // tscable + else {cond_type = 4;} ; // wire + + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[cond_type - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(cond_type)); } + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[5 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(5)); } + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[6 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(6)); } + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[7 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(7)); } + } + } + else { + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[11 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(11)); } + if (FCondsUser != "") { // Use the saved conductors array string as it will include None values that would get ignored otherwise. + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[20 - 1]); System::Write(f, "=["); System::Write(f, FCondsUser); System::WriteLn(f, "]");} + } + else { + conductor_array = ""; + for(stop = Fnconds, j = 1; j <= stop; j++) { + if (dynamic_cast (FWireData[FActiveCond - 1]) != nullptr) {conductor_array += ("cndata." + FCondName[j - 1] + ",");} // cncable + else if (dynamic_cast (FWireData[FActiveCond - 1]) != nullptr) {conductor_array += ("tsdata." + FCondName[j - 1] + ",");} // tscable + else {conductor_array += ("wiredata." + FCondName[j - 1] + ",");;} ; // wire + } + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[20 - 1]); System::Write(f, "=["); System::Write(f, conductor_array); System::WriteLn(f, "]");} + } + + } + for(stop = 10, i = 8; i <= stop; i++) { - set_ActiveCond(j); - { System::Write(f, "~ "); System::Write(f, with0->PropertyName[3 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(3)); } - { System::Write(f, "~ "); System::Write(f, with0->PropertyName[4 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(4)); } - { System::Write(f, "~ "); System::Write(f, with0->PropertyName[5 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(5)); } - { System::Write(f, "~ "); System::Write(f, with0->PropertyName[6 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(6)); } - { System::Write(f, "~ "); System::Write(f, with0->PropertyName[7 - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(7)); } + { System::Write(f, "~ "); System::Write(f, with0->PropertyName[i - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(i)); } } - for(stop = with0->NumProperties, i = 8; i <= stop; i++) + for(stop = 19, i = 17; i <= stop; i++) { { System::Write(f, "~ "); System::Write(f, with0->PropertyName[i - 1]); System::Write(f, "="); System::WriteLn(f, GetPropertyValue(i)); } } @@ -662,6 +862,12 @@ String TLineGeometryObj::GetPropertyValue(int Index) /*Return Property Value for Active index*/ switch(Index) { + case 1: + result = Format("%d", Fnconds); + break; + case 2: + result = Format("%d", Fnphases); + break; case 3: result = Format("%d", FActiveCond); break; @@ -715,6 +921,17 @@ String TLineGeometryObj::GetPropertyValue(int Index) case 19: result = LineTypeList.Get(FLineType); break; + case 20: // Similar to 12,15,16 but with conductor data class prepended + { + int stop = 0; + result = "["; + for(stop = Fnconds, i = 1; i <= stop; i++) + { + result = result + FCondName[i - 1] + " "; + } + result = result + "]"; + } + break; // Inherited parameters default: result = inherited::GetPropertyValue(Index); @@ -1042,6 +1259,7 @@ void TLineGeometryObj::Set_Nconds(int Value) FWireData.resize(Fnconds); FX.resize(Fnconds); FY.resize(Fnconds); + FEqDist.resize(4); FUnits.resize(Fnconds); FPhaseChoice = (pConductorChoiceArray) realloc(FPhaseChoice, sizeof(FPhaseChoice[0]) * Fnconds); for(stop = Fnconds, i = 1; i <= stop; i++) @@ -1071,7 +1289,14 @@ void TLineGeometryObj::Set_Nconds(int Value) for(stop = Fnconds, i = 1; i <= stop; i++) { FUnits[i - 1] = -1; - } // default to ft + } + + for(stop = 4, i = 1; i <= stop; i++) + { + FEqDist[i - 1] = 0.0; + } + + // default to ft FLastUnit = UNITS_FT; } @@ -1109,10 +1334,19 @@ void TLineGeometryObj::UpdateLineGeometryData(double f) TTSDataObj* tsd = nullptr; int stop = 0; + FLineData->Set_FEquivalentSpacing(FEquivalentSpacing); + if (FEquivalentSpacing) { + FLineData->Set_FEqDist(1, FLastUnit, FEqDist[1 - 1]); + FLineData->Set_FEqDist(2, FLastUnit, FEqDist[2 - 1]); + FLineData->Set_FEqDist(3, FLastUnit, FEqDist[3 - 1] + FLineData->Get_FheightOffset() * To_Meters(FLineData->FuserHeightUnit) * From_Meters(FLastUnit)); + FLineData->Set_FEqDist(4, FLastUnit, FEqDist[4 - 1] + FLineData->Get_FheightOffset() * To_Meters(FLineData->FuserHeightUnit) * From_Meters(FLastUnit)); + } for(stop = Fnconds, i = 1; i <= stop; i++) { - FLineData->Set_X(i, FUnits[i - 1], FX[i - 1]); - FLineData->Set_Y(i, FUnits[i - 1], FY[i - 1] + FLineData->Get_FheightOffset() * To_Meters(FLineData->FuserHeightUnit) * From_Meters(FUnits[i - 1])); + if (!FEquivalentSpacing) { + FLineData->Set_X(i, FUnits[i - 1], FX[i - 1]); + FLineData->Set_Y(i, FUnits[i - 1], FY[i - 1] + FLineData->Get_FheightOffset() * To_Meters(FLineData->FuserHeightUnit) * From_Meters(FUnits[i - 1])); + } FLineData->Set_radius(i, FWireData[i - 1]->get_FRadiusUnits(), FWireData[i - 1]->get_Fcapradius60()); FLineData->Set_Capradius(i, FWireData[i - 1]->get_FRadiusUnits(), FWireData[i - 1]->get_Fcapradius60()); FLineData->Set_GMR(i, FWireData[i - 1]->get_FGMRUnits(), FWireData[i - 1]->get_FGMR60()); @@ -1124,8 +1358,8 @@ void TLineGeometryObj::UpdateLineGeometryData(double f) { auto with0 = ((TCNTSLineConstants*) FLineData); cnd = (TCNDataObj*) FWireData[i - 1]; - with0->Set_CondType(i, 1); //CN - with0->Set_EpsR(i, cnd->get_FEpsR()); + with0->Set_CondType(i, 1); //CN + with0->Set_EpsR(i, cnd->get_FEpsR()); with0->Set_InsLayer(i, cnd->get_FRadiusUnits(), cnd->get_FInsLayer()); with0->Set_DiaIns(i, cnd->get_FRadiusUnits(), cnd->get_FDiaIns()); with0->Set_DiaCable(i, cnd->get_FRadiusUnits(), cnd->get_FDiaCable()); @@ -1217,9 +1451,11 @@ void TLineGeometryObj::LoadSpacingAndWires(TLineSpacingObj* Spc, const pConducto j++; FCondName[j - 1] = Wires[i - 1]->get_Name(); FWireData[j - 1] = Wires[i - 1]; - FX[j - 1] = Spc->Get_FX(i); - FY[j - 1] = Spc->Get_FY(i); - FUnits[j - 1] = Spc->get_FUnits(); + if (!Spc->get_FEquivalentSpacing()) { + FX[j - 1] = Spc->Get_FX(i); + FY[j - 1] = Spc->Get_FY(i); + FUnits[j - 1] = Spc->get_FUnits(); + } if (((Wires[i - 1]->NormAmps < NormAmps) || (NormAmps == 0.0)) && (j <= Fnphases)) { NormAmps = (Wires)[1 - 1]->NormAmps; @@ -1228,6 +1464,14 @@ void TLineGeometryObj::LoadSpacingAndWires(TLineSpacingObj* Spc, const pConducto } } + if (Spc->get_FEquivalentSpacing()) { + FEqDist[1 - 1] = Spc->get_FEqDistPhPh(); + FEqDist[2 - 1] = Spc->get_FEqDistPhN(); + FEqDist[3 - 1] = Spc->get_FAvgHeightPh(); + FEqDist[4 - 1] = Spc->get_FAvgHeightN(); + FLastUnit = Spc->get_FUnits(); + } + FEquivalentSpacing = Spc->get_FEquivalentSpacing(); DataChanged = true; // UpdateLineGeometryData will be called when we get the impedance matrix for the line. diff --git a/VersionC/General/LineGeometry.h b/VersionC/General/LineGeometry.h index 3cf21f7c0..7cd729d53 100644 --- a/VersionC/General/LineGeometry.h +++ b/VersionC/General/LineGeometry.h @@ -78,6 +78,9 @@ class TLineGeometryObj : public DSSObject::TDSSObject ConductorData::pConductorDataArray FWireData; std::vector FX; std::vector FY; + DoubleArray FEqDist; // This array always has four elements EqDistPhPh, EqDistPhN, AvgHeightPh, AvgHeightN + bool FEquivalentSpacing; // to tell the calcs when to use equivalent spacing info + String FCondsUser; // use this to preserve conductors array for dumping to avoid losing user-defined None positions. std::vector FUnits; int FLastUnit; bool DataChanged; @@ -93,8 +96,8 @@ class TLineGeometryObj : public DSSObject::TDSSObject Ucmatrix::TcMatrix* Get_Zmatrix(double f, double Lngth, int Units); double Get_RhoEarth(); void Set_RhoEarth(double Value); - double Get_EpsRMedium(); - void Set_EpsRMedium(double Value); + double Get_EpsRMedium(); + void Set_EpsRMedium(double Value); double Get_HeightOffset(); void Set_HeightOffset(double Value); int Get_HeightUnit(); @@ -102,7 +105,7 @@ class TLineGeometryObj : public DSSObject::TDSSObject int get_Nconds(); void UpdateLineGeometryData(double f); // call this before using the line data - // CIM Accessors + // CIM Accessors double Get_FX(int i); double Get_FY(int i); int Get_FUnits(int i); diff --git a/VersionC/General/LineSpacing.cpp b/VersionC/General/LineSpacing.cpp index bc33d5b4d..7a4abbe79 100644 --- a/VersionC/General/LineSpacing.cpp +++ b/VersionC/General/LineSpacing.cpp @@ -32,7 +32,7 @@ TLineSpacingObj::TLineSpacingObj() {} TLineSpacingObj* ActiveLineSpacingObj = nullptr; -const int NumPropsThisClass = 5; +const int NumPropsThisClass = 10; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Creates superstructure for all Line objects @@ -71,11 +71,21 @@ void TLineSpacing::DefineProperties() (PropertyName)[3 - 1] = "x"; (PropertyName)[4 - 1] = "h"; (PropertyName)[5 - 1] = "units"; + (PropertyName)[6 - 1] = "detailed"; + (PropertyName)[7 - 1] = "EqDistPhPh"; + (PropertyName)[8 - 1] = "EqDistPhN"; + (PropertyName)[9 - 1] = "AvgPhaseHeight"; + (PropertyName)[10 - 1] = "AvgNeutralHeight"; (PropertyHelp)[1 - 1] = "Number of wires in this geometry. Default is 3. Triggers memory allocations. Define first!"; (PropertyHelp)[2 - 1] = "Number of retained phase conductors. If less than the number of wires, list the retained phase coordinates first."; (PropertyHelp)[3 - 1] = "Array of wire X coordinates."; (PropertyHelp)[4 - 1] = "Array of wire Heights."; (PropertyHelp)[5 - 1] = "Units for x and h: {mi|kft|km|m|Ft|in|cm } Initial default is \"ft\", but defaults to last unit defined"; + (PropertyHelp)[6 - 1] = "{Yes/True | No/False} Default = Yes. Determines whether the spacing uses a detailed cross-section coordinates with x and h arrays (Yes/True), or uses equivalent spacing fields (No/False). The equivalent spacing fields are EqDistPhPh, EqDistPhN, AvgPhaseHeight and AvgNeutralHeight."; + (PropertyHelp)[7 - 1] = "Equivalent distance between phase conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates. "; + (PropertyHelp)[8 - 1] = "Equivalent distance between phase and neutral conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates."; + (PropertyHelp)[9 - 1] = "Average height of phase conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates."; + (PropertyHelp)[10 - 1] = "Average height of neutral conductors. Used for equivalent distance modeling (detailed=yes) as opposed to detailed cross-section coordinates."; ActiveProperty = NumPropsThisClass - 1; inherited::DefineProperties(); // Add defs of inherited properties to bottom of list } @@ -175,6 +185,21 @@ int TLineSpacing::Edit(int ActorID) case 5: with0->FUnits = GetUnitsCode(Param); break; + case 6: + with0->FEquivalentSpacing = not InterpretYesNo(Param); + break; + case 7: + with0->FEqDistPhPh = Parser[ActorID]->MakeDouble_(); + break; + case 8: + with0->FEqDistPhN = Parser[ActorID]->MakeDouble_(); + break; + case 9: + with0->FAvgHeightPh = Parser[ActorID]->MakeDouble_(); + break; + case 10: + with0->FAvgHeightN = Parser[ActorID]->MakeDouble_(); + break; // Inherited parameters default: ClassEdit(ActiveLineSpacingObj, ParamPointer - NumPropsThisClass); @@ -221,6 +246,11 @@ int TLineSpacing::MakeLike(const String LineName) { (with0->FY)[i - 1] = (OtherLineSpacing->FY)[i - 1]; } + with0->FEquivalentSpacing = OtherLineSpacing->FEquivalentSpacing; + with0->FEqDistPhPh = OtherLineSpacing->FEqDistPhPh; + with0->FEqDistPhN = OtherLineSpacing->FEqDistPhN; + with0->FAvgHeightPh = OtherLineSpacing->FAvgHeightPh; + with0->FAvgHeightN = OtherLineSpacing->FAvgHeightN; with0->FUnits = OtherLineSpacing->FUnits; with0->DataChanged = true; for(stop = with0->ParentClass->NumProperties, i = 1; i <= stop; i++) @@ -287,6 +317,11 @@ TLineSpacingObj::TLineSpacingObj(TDSSClass* ParClass, const String LineSpacingNa FUnits = UNITS_FT; set_Nwires(3); // Allocates terminals Fnphases = 3; + FEqDistPhPh = 0.0; + FEqDistPhN = 0.0; + FAvgHeightPh = 0.0; + FAvgHeightN = 0.0; + FEquivalentSpacing = false; InitPropertyValues(0); } @@ -308,8 +343,10 @@ void TLineSpacingObj::DumpProperties(System::TTextRec& f, bool Complete) { auto with0 = ParentClass; int stop = 0; - for(stop = 5, i = 1; i <= stop; i++) + for(stop = 10, i = 1; i <= stop; i++) { + // if (!FEquivalentSpacing && i > 5) {continue;} + // else if (FEquivalentSpacing && (i == 3 || i == 4)) {continue;} { Write(f, "~ "); Write(f, with0->PropertyName[i - 1]); Write(f, L'='); WriteLn(f, GetPropertyValue(i)); } } } @@ -399,6 +436,32 @@ int TLineSpacingObj::get_FUnits() //------------------------------------------------------------------------------------ +double TLineSpacingObj::get_FEqDistPhPh() +{ + return FEqDistPhPh; +} + +double TLineSpacingObj::get_FEqDistPhN() +{ + return FEqDistPhN; +} + +double TLineSpacingObj::get_FAvgHeightPh() +{ + return FAvgHeightPh; +} + +double TLineSpacingObj::get_FAvgHeightN() +{ + return FAvgHeightN; +} + +bool TLineSpacingObj::get_FEquivalentSpacing() +{ + return FEquivalentSpacing; +} +//------------------------------------------------------------------------------------ + void TLineSpacingObj::InitPropertyValues(int ArrayOffset) { Set_PropertyValue(1,"3"); @@ -406,6 +469,11 @@ void TLineSpacingObj::InitPropertyValues(int ArrayOffset) Set_PropertyValue(3,"0"); Set_PropertyValue(4,"32"); Set_PropertyValue(5,"ft"); + Set_PropertyValue(6,"Yes"); + Set_PropertyValue(7,"0"); + Set_PropertyValue(8,"0"); + Set_PropertyValue(9,"0"); + Set_PropertyValue(10,"0"); inherited::InitPropertyValues(NumPropsThisClass); } diff --git a/VersionC/General/LineSpacing.h b/VersionC/General/LineSpacing.h index f2ab42d47..ae7a2e729 100644 --- a/VersionC/General/LineSpacing.h +++ b/VersionC/General/LineSpacing.h @@ -54,6 +54,11 @@ class TLineSpacingObj : public DSSObject::TDSSObject Arraydef::pDoubleArray FX; Arraydef::pDoubleArray FY; int FUnits; + double FEqDistPhPh; + double FEqDistPhN; + double FAvgHeightPh; + double FAvgHeightN; + bool FEquivalentSpacing; bool DataChanged; void set_Nwires(int Value); @@ -70,6 +75,11 @@ class TLineSpacingObj : public DSSObject::TDSSObject int get_Fnconds(); int get_Fnphases(); int get_FUnits(); + double get_FEqDistPhPh(); + double get_FEqDistPhN(); + double get_FAvgHeightPh(); + double get_FAvgHeightN(); + bool get_FEquivalentSpacing(); // CIM XML accessors TLineSpacingObj(DSSClass::TDSSClass* ParClass);