separate disjunct portions of circuit
This commit is contained in:
parent
4a335353b9
commit
a4d8f9cb2a
@ -10,8 +10,10 @@ import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.math3.linear.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
|
||||
@ -19,11 +21,15 @@ import static java.lang.Math.max;
|
||||
@Getter
|
||||
public class Calculation {
|
||||
|
||||
private static final double NO_RESISTANCE = 1e-12;
|
||||
public static final double NO_RESISTANCE = 1e-12;
|
||||
|
||||
private static final double FULL_ADMITTANCE = 1 / NO_RESISTANCE;
|
||||
|
||||
private final List<Junction> junctions;
|
||||
private final List<Junction> junctions = new ArrayList<>();
|
||||
|
||||
private final Set<Part> parts = new HashSet<>();
|
||||
|
||||
private final Set<Wire> wires = new HashSet<>();
|
||||
|
||||
private final RealMatrix matrix;
|
||||
|
||||
@ -31,29 +37,49 @@ public class Calculation {
|
||||
|
||||
private RealVector potentials = null;
|
||||
|
||||
public static List<Calculation> calculate(final Circuit circuit) {
|
||||
final List<Calculation> calculations = new ArrayList<>();
|
||||
final List<PartBattery> batteries = new ArrayList<>(circuit.streamParts().flatMap(PartBattery::filterCast).toList());
|
||||
while (!batteries.isEmpty()) {
|
||||
final PartBattery pivot = batteries.removeFirst();
|
||||
final Set<Junction> connectedJunctions = new HashSet<>();
|
||||
pivot.getPlus().collectConnectedJunctions(connectedJunctions);
|
||||
pivot.getMinus().collectConnectedJunctions(connectedJunctions);
|
||||
connectedJunctions.stream().map(Junction::getOwner).flatMap(PartBattery::filterCast).forEach(batteries::remove);
|
||||
calculations.add(new Calculation(connectedJunctions, pivot));
|
||||
}
|
||||
return calculations;
|
||||
}
|
||||
|
||||
public Calculation(final int numNodes) {
|
||||
junctions = Collections.emptyList();
|
||||
matrix = new Array2DRowRealMatrix(numNodes, numNodes);
|
||||
currents = new ArrayRealVector(numNodes);
|
||||
}
|
||||
|
||||
public Calculation(final Circuit circuit) {
|
||||
final PartBattery pivot = circuit.streamParts().flatMap(PartBattery::filterCast).findFirst().orElseThrow(RuntimeException::new);
|
||||
junctions = circuit.streamJunctions().filter(junction -> junction != pivot.getMinus()).toList(); // pivot.minus is GND and cannot be part of the matrix (linear dependency)
|
||||
matrix = new Array2DRowRealMatrix(junctions.size(), junctions.size());
|
||||
currents = new ArrayRealVector(junctions.size());
|
||||
fromSchematic(circuit);
|
||||
solve();
|
||||
toSchematic(circuit);
|
||||
private Calculation(final Set<Junction> connectedJunctions, final PartBattery pivot) {
|
||||
for (final Junction junction : connectedJunctions) {
|
||||
parts.add(junction.getOwner());
|
||||
if (!junctions.contains(junction) && junction != pivot.getMinus()) {
|
||||
// pivot.minus is GND and cannot be part of the matrix (linear dependency)
|
||||
this.junctions.add(junction);
|
||||
}
|
||||
wires.addAll(junction.getWires());
|
||||
}
|
||||
|
||||
private void fromSchematic(final Circuit circuit) {
|
||||
circuit.streamWires().forEach(
|
||||
matrix = new Array2DRowRealMatrix(this.junctions.size(), this.junctions.size());
|
||||
currents = new ArrayRealVector(this.junctions.size());
|
||||
fromSchematic();
|
||||
solve();
|
||||
toSchematic();
|
||||
}
|
||||
|
||||
private void fromSchematic() {
|
||||
wires.forEach(
|
||||
wire -> addResistor(wire.getA(), wire.getB(), NO_RESISTANCE)
|
||||
);
|
||||
circuit.streamParts().forEach(part -> {
|
||||
parts.forEach(part -> {
|
||||
for (final InnerConnection innerConnection : part.getInnerConnections()) {
|
||||
addResistor(innerConnection.a, innerConnection.b, NO_RESISTANCE);
|
||||
addResistor(innerConnection.a, innerConnection.b, innerConnection.resistance);
|
||||
}
|
||||
if (part instanceof final PartBattery battery) {
|
||||
addBattery(battery);
|
||||
@ -63,10 +89,12 @@ public class Calculation {
|
||||
});
|
||||
}
|
||||
|
||||
private void toSchematic(final Circuit circuit) {
|
||||
circuit.streamJunctions().forEach(junction -> junction.setVoltage(getPotential(junction)));
|
||||
circuit.streamWires().forEach(wire -> wire.setCurrent(getCurrent(wire)));
|
||||
circuit.streamParts().forEach(Part::postCalculate);
|
||||
private void toSchematic() {
|
||||
wires.forEach(wire -> wire.setCurrent(getCurrent(wire)));
|
||||
parts.forEach(part -> {
|
||||
part.getJunctions().forEach(junction -> junction.setVoltage(getPotential(junction)));
|
||||
part.postCalculate();
|
||||
});
|
||||
}
|
||||
|
||||
private double getPotential(final @NonNull Junction junction) {
|
||||
|
||||
@ -17,8 +17,6 @@ public class Circuit {
|
||||
|
||||
private final List<Part> parts = new ArrayList<>();
|
||||
|
||||
private final List<Junction> junctions = new ArrayList<>();
|
||||
|
||||
private final List<Wire> wires = new ArrayList<>();
|
||||
|
||||
public Circuit(final CircuitDto dto) {
|
||||
@ -42,7 +40,7 @@ public class Circuit {
|
||||
}
|
||||
|
||||
public void evaluateAndRender() {
|
||||
new Calculation(this);
|
||||
Calculation.calculate(this);
|
||||
parts.forEach(Part::render);
|
||||
}
|
||||
|
||||
@ -52,7 +50,6 @@ public class Circuit {
|
||||
}
|
||||
if (isFree(part.getPosition())) {
|
||||
parts.add(part);
|
||||
junctions.addAll(part.getJunctions());
|
||||
part.render();
|
||||
}
|
||||
return part;
|
||||
@ -75,10 +72,6 @@ public class Circuit {
|
||||
return parts.stream();
|
||||
}
|
||||
|
||||
public Stream<Junction> streamJunctions() {
|
||||
return junctions.stream();
|
||||
}
|
||||
|
||||
public Stream<Wire> streamWires() {
|
||||
return wires.stream();
|
||||
}
|
||||
|
||||
@ -17,19 +17,10 @@ public class CircuitPanel extends JPanel {
|
||||
|
||||
public CircuitPanel() {
|
||||
new CircuitPanelDropTarget(this, circuit);
|
||||
final PartBattery battery = circuit.addPart(new PartBattery(Position.ofRaster(1, 0)));
|
||||
|
||||
final PartLight light0 = circuit.addPart(new PartLight(Position.ofRaster(0, 2)));
|
||||
light0.clockwise();
|
||||
|
||||
final PartLight light1 = circuit.addPart(new PartLight(Position.ofRaster(1, 2)));
|
||||
light1.clockwise();
|
||||
light1.clockwise();
|
||||
light1.clockwise();
|
||||
|
||||
circuit.connect(battery.getMinus(), light0.getA());
|
||||
circuit.connect(light0.getB(), light1.getA());
|
||||
circuit.connect(light1.getB(), battery.getPlus());
|
||||
final PartBattery battery = circuit.addPart(new PartBattery(Position.ofRaster(0, 0)));
|
||||
final PartLight light = circuit.addPart(new PartLight(Position.ofRaster(0, 1)));
|
||||
circuit.connect(battery.getMinus(), light.getA());
|
||||
circuit.connect(light.getB(), battery.getPlus());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,14 +1,28 @@
|
||||
package de.ph87.electro.circuit.part;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class InnerConnection {
|
||||
|
||||
public final Junction a;
|
||||
|
||||
public final Junction b;
|
||||
|
||||
public InnerConnection(final Junction a, final Junction b) {
|
||||
public final double resistance;
|
||||
|
||||
public InnerConnection(final Junction a, final Junction b, final double resistance) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.resistance = resistance;
|
||||
}
|
||||
|
||||
public Stream<Junction> filter(final Junction junction) {
|
||||
if (a == junction) {
|
||||
return Stream.of(b);
|
||||
} else if (b == junction) {
|
||||
return Stream.of(a);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -74,4 +74,13 @@ public class Junction {
|
||||
return this.position.distance(position) <= JUNCTION_RADIUS_HOVER;
|
||||
}
|
||||
|
||||
public void collectConnectedJunctions(final Set<Junction> connected) {
|
||||
if (connected.contains(this)) {
|
||||
return;
|
||||
}
|
||||
connected.add(this);
|
||||
wires.forEach(wire -> wire.getOpposite(this).collectConnectedJunctions(connected));
|
||||
owner.getInnerConnections().stream().flatMap(innerConnection -> innerConnection.filter(this)).forEach(opposite -> opposite.collectConnectedJunctions(connected));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -110,6 +110,10 @@ public abstract class Part {
|
||||
// may be overwritten
|
||||
}
|
||||
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static Part of(final PartDto abstractDto) {
|
||||
return switch (abstractDto) {
|
||||
case final PartBatteryDto dto -> new PartBattery(dto);
|
||||
@ -124,8 +128,4 @@ public abstract class Part {
|
||||
};
|
||||
}
|
||||
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,8 +45,8 @@ public class PartBattery extends Part {
|
||||
|
||||
public PartBattery(final Position position) {
|
||||
super("Batterie", position);
|
||||
minus = newJunction(this, "PLUS", P10, P50);
|
||||
plus = newJunction(this, "MINUS", P90, P50);
|
||||
minus = newJunction(this, "MINUS", P10, P50);
|
||||
plus = newJunction(this, "PLUS", P90, P50);
|
||||
}
|
||||
|
||||
public PartBattery(final PartBatteryDto dto) {
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package de.ph87.electro.circuit.part.parts;
|
||||
|
||||
import de.ph87.electro.circuit.part.Junction;
|
||||
import de.ph87.electro.circuit.part.Orientation;
|
||||
import de.ph87.electro.circuit.part.PartOther;
|
||||
import de.ph87.electro.circuit.part.Position;
|
||||
import de.ph87.electro.circuit.part.*;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
import static java.lang.Math.abs;
|
||||
@ -115,4 +114,12 @@ public class PartLight extends PartOther {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
if (defect) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return List.of(new InnerConnection(a, b, resistance));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
import static de.ph87.electro.circuit.Calculation.NO_RESISTANCE;
|
||||
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@ -59,7 +60,7 @@ public class PartSwitch1x1 extends PartOther {
|
||||
@Override
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
if (state) {
|
||||
return List.of(new InnerConnection(common, output));
|
||||
return List.of(new InnerConnection(common, output, NO_RESISTANCE));
|
||||
}
|
||||
return super.getInnerConnections();
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import lombok.ToString;
|
||||
import java.util.List;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
import static de.ph87.electro.circuit.Calculation.NO_RESISTANCE;
|
||||
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@ -61,9 +62,9 @@ public class PartSwitch1x2 extends PartOther {
|
||||
@Override
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
if (state) {
|
||||
return List.of(new InnerConnection(common, output1));
|
||||
return List.of(new InnerConnection(common, output1, NO_RESISTANCE));
|
||||
}
|
||||
return List.of(new InnerConnection(common, output0));
|
||||
return List.of(new InnerConnection(common, output0, NO_RESISTANCE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import lombok.ToString;
|
||||
import java.util.List;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
import static de.ph87.electro.circuit.Calculation.NO_RESISTANCE;
|
||||
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@ -68,13 +69,13 @@ public class PartSwitchCross extends PartOther {
|
||||
public List<InnerConnection> getInnerConnections() {
|
||||
if (state) {
|
||||
return List.of(
|
||||
new InnerConnection(common0, output1),
|
||||
new InnerConnection(common1, output0)
|
||||
new InnerConnection(common0, output1, NO_RESISTANCE),
|
||||
new InnerConnection(common1, output0, NO_RESISTANCE)
|
||||
);
|
||||
}
|
||||
return List.of(
|
||||
new InnerConnection(common0, output0),
|
||||
new InnerConnection(common1, output1)
|
||||
new InnerConnection(common0, output0, NO_RESISTANCE),
|
||||
new InnerConnection(common1, output1, NO_RESISTANCE)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -20,8 +20,7 @@ class CalculationServiceTest {
|
||||
circuit.connect(battery.getMinus(), light.getA());
|
||||
circuit.connect(battery.getPlus(), light.getB());
|
||||
|
||||
final Calculation calculation = new Calculation(circuit);
|
||||
|
||||
for (final Calculation calculation : Calculation.calculate(circuit)) {
|
||||
calculation.toString().lines().forEach(log::info);
|
||||
circuit.streamParts().forEach(part -> {
|
||||
log.info("");
|
||||
@ -36,5 +35,6 @@ class CalculationServiceTest {
|
||||
});
|
||||
log.info("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user