Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to new report API #139

Closed
wants to merge 11 commits into from
33 changes: 29 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,51 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- name: print environment
run: env

- name: Checkout sources
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
path: main

- name: Checkout powsybl-core branch
uses: actions/checkout@v4
with:
repository: powsybl/powsybl-core
ref: refs/heads/main
path: powsybl-core

- name: Checkout powsybl-open-loadflow branch
uses: actions/checkout@v4
with:
repository: powsybl/powsybl-open-loadflow
ref: refs/heads/main
path: powsybl-open-loadflow

- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17

- name: Build and install powsybl-core with Maven
run: mvn --batch-mode -DskipTests=true --file ./powsybl-core/pom.xml install

- name: Build and install powsybl-open-loadflow with Maven
run: mvn --batch-mode -DskipTests=true --file ./powsybl-open-loadflow/pom.xml install

- name: Build with Maven
if: matrix.os == 'ubuntu-latest'
run: mvn --batch-mode -Pjacoco install
run: mvn --batch-mode -Pjacoco --file ./main/pom.xml install

- name: Build with Maven
if: matrix.os != 'ubuntu-latest'
run: mvn --batch-mode install
run: mvn --batch-mode --file ./main/pom.xml install

- name: Run SonarCloud analysis
if: matrix.os == 'ubuntu-latest'
run: >
mvn --batch-mode -DskipTests sonar:sonar
mvn --batch-mode -DskipTests --file ./main/pom.xml sonar:sonar
-Dsonar.host.url=https://sonarcloud.io
-Dsonar.organization=powsybl-ci-github
-Dsonar.projectKey=com.powsybl:powsybl-entsoe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
package com.powsybl.balances_adjustment.balance_computation;

import com.powsybl.commons.reporter.Reporter;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.iidm.network.Network;

import java.util.concurrent.CompletableFuture;
Expand All @@ -22,6 +22,6 @@ public interface BalanceComputation {

CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters);

CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters, Reporter reporter);
CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters, ReportNode reportNode);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import com.powsybl.balances_adjustment.util.NetworkArea;
import com.powsybl.balances_adjustment.util.Reports;
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.commons.reporter.TypedValue;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;
import com.powsybl.computation.ComputationManager;
import com.powsybl.iidm.modification.scalable.Scalable;
import com.powsybl.iidm.network.ComponentConstants;
Expand Down Expand Up @@ -64,20 +64,20 @@ public BalanceComputationImpl(List<BalanceComputationArea> areas, ComputationMan
*/
@Override
public CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters) {
return this.run(network, workingStateId, parameters, Reporter.NO_OP);
return this.run(network, workingStateId, parameters, ReportNode.NO_OP);
}

/**
* Run balances adjustment computation in several iterations
*/
@Override
public CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters, Reporter reporter) {
public CompletableFuture<BalanceComputationResult> run(Network network, String workingStateId, BalanceComputationParameters parameters, ReportNode reportNode) {
Objects.requireNonNull(network);
Objects.requireNonNull(workingStateId);
Objects.requireNonNull(parameters);
Objects.requireNonNull(reporter);
Objects.requireNonNull(reportNode);

BalanceComputationRunningContext context = new BalanceComputationRunningContext(areas, network, parameters, reporter);
BalanceComputationRunningContext context = new BalanceComputationRunningContext(areas, network, parameters, reportNode);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering why we give two reportNodes to the context even though it's useless 🤨 Not the purpose of this PR anyway!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, it is not clear that the two report nodes are needed. I just kept the same behaviours, just upgrading to the new report API.

Copy link
Member

@jeandemanged jeandemanged Mar 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zamarrenolm you may clarify via comments that (please adjust with new reporting api terminology, unsure of correct new terms ...):

  • reportNode is the root reporter / provided when calling run
  • iterationReportNode is subreporter for the current balancing iteration

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with comments. Also used the method to obtain the root report node from the context, to make explicit that the balance adjustment different steps have it available through the context as eventually the complexity of the current calculation could be split in many lower level methods.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Luma for clarifying with comments. Nonetheless I think it would be clearer to remove the two ReportNodes from the context, as hiding them in this object does not help understanding the reports split... but again it's not the purpose of current PR!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flo-dup I don't understand previous comments '... it's useless ...', 'it would be clearer to remove the two ReportNodes', '... hiding ...'

The two report nodes are different, they are both useful, and should not be removed.
They are not hidden in the context, it is the opposite, they are made available via the context, so they can actually be used.

BalanceComputationResult result;

String initialVariantId = network.getVariantManager().getWorkingVariantId();
Expand All @@ -86,33 +86,33 @@ public CompletableFuture<BalanceComputationResult> run(Network network, String w
network.getVariantManager().setWorkingVariant(workingVariantCopyId);

do {
Reporter iterationReporter = Reports.createBalanceComputationIterationReporter(reporter, context.getIterationNum());
context.setIterationReporter(iterationReporter);
ReportNode iterationReportNode = Reports.createBalanceComputationIterationReportNode(context.getReportNode(), context.getIterationNum());
context.setIterationReportNode(iterationReportNode);
// Step 1: Perform the scaling
Reporter scalingReporter = iterationReporter.createSubReporter("scaling", "Scaling");
ReportNode scalingReportNode = iterationReportNode.newReportNode().withMessageTemplate("scaling", "Scaling").add();
context.getBalanceOffsets().forEach((area, offset) -> {
Scalable scalable = area.getScalable();
double done = scalable.scale(network, offset, parameters.getScalingParameters());
Reports.reportScaling(scalingReporter, area.getName(), offset, done);
Reports.reportScaling(scalingReportNode, area.getName(), offset, done);
LOGGER.info("Iteration={}, Scaling for area {}: offset={}, done={}", context.getIterationNum(), area.getName(), offset, done);
});

// Step 2: compute Load Flow
LoadFlowResult loadFlowResult = loadFlowRunner.run(network, workingVariantCopyId, computationManager, parameters.getLoadFlowParameters(), iterationReporter);
LoadFlowResult loadFlowResult = loadFlowRunner.run(network, workingVariantCopyId, computationManager, parameters.getLoadFlowParameters(), iterationReportNode);
if (!isLoadFlowResultOk(context, loadFlowResult)) {
LOGGER.error("Iteration={}, LoadFlow on network {} does not converge", context.getIterationNum(), network.getId());
result = new BalanceComputationResult(BalanceComputationResult.Status.FAILED, context.getIterationNum());
return CompletableFuture.completedFuture(result);
}

// Step 3: Compute balance and mismatch for each area
Reporter mismatchReporter = iterationReporter.createSubReporter("mismatch", "Mismatch");
ReportNode mismatchReportNode = iterationReportNode.newReportNode().withMessageTemplate("mismatch", "Mismatch").add();
for (BalanceComputationArea area : areas) {
NetworkArea na = context.getNetworkArea(area);
double target = area.getTargetNetPosition();
double balance = na.getNetPosition();
double mismatch = target - balance;
Reports.reportAreaMismatch(mismatchReporter, area.getName(), mismatch, target, balance);
Reports.reportAreaMismatch(mismatchReportNode, area.getName(), mismatch, target, balance);
LOGGER.info("Iteration={}, Mismatch for area {}: {} (target={}, balance={})", context.getIterationNum(), area.getName(), mismatch, target, balance);
context.updateAreaOffsetAndMismatch(area, mismatch);
}
Expand All @@ -128,16 +128,16 @@ public CompletableFuture<BalanceComputationResult> run(Network network, String w
}
} while (context.getIterationNum() < parameters.getMaxNumberIterations() && result.getStatus() != BalanceComputationResult.Status.SUCCESS);

Reporter statusReporter = reporter.createSubReporter("status", "Status");
ReportNode statusReportNode = context.getReportNode().newReportNode().withMessageTemplate("status", "Status").add();
if (result.getStatus() == BalanceComputationResult.Status.SUCCESS) {
List<String> networkAreasName = areas.stream()
.map(BalanceComputationArea::getName).collect(Collectors.toList());
Reports.reportBalancedAreas(statusReporter, networkAreasName, result.getIterationCount());
.map(BalanceComputationArea::getName).toList();
Reports.reportBalancedAreas(statusReportNode, networkAreasName, result.getIterationCount());
LOGGER.info("Areas {} are balanced after {} iterations", networkAreasName, result.getIterationCount());

} else {
BigDecimal totalMismatch = BigDecimal.valueOf(computeTotalMismatch(context)).setScale(2, RoundingMode.UP);
Reports.reportUnbalancedAreas(statusReporter, context.getIterationNum(), totalMismatch);
Reports.reportUnbalancedAreas(statusReportNode, context.getIterationNum(), totalMismatch);
LOGGER.error("Areas are unbalanced after {} iterations, total mismatch is {}", context.getIterationNum(), totalMismatch);
}

Expand Down Expand Up @@ -182,9 +182,9 @@ protected boolean isLoadFlowResultOk(BalanceComputationRunningContext context, f
return false;
}
final var cr = list.get(0);
Reporter lfStatusReporter = context.getIterationReporter().createSubReporter("loadFlowStatus", "Checking load flow status");
ReportNode lfStatusReportNode = context.getIterationReportNode().newReportNode().withMessageTemplate("loadFlowStatus", "Checking load flow status").add();
final var severity = cr.getStatus() == LoadFlowResult.ComponentResult.Status.CONVERGED ? TypedValue.INFO_SEVERITY : TypedValue.ERROR_SEVERITY;
Reports.reportLfStatus(lfStatusReporter, cr.getConnectedComponentNum(), cr.getSynchronousComponentNum(), cr.getStatus().name(), severity);
Reports.reportLfStatus(lfStatusReportNode, cr.getConnectedComponentNum(), cr.getSynchronousComponentNum(), cr.getStatus().name(), severity);
return cr.getStatus() == LoadFlowResult.ComponentResult.Status.CONVERGED;
})
);
Expand All @@ -197,19 +197,25 @@ protected static class BalanceComputationRunningContext {
private final Map<BalanceComputationArea, NetworkArea> networkAreas;
private final Map<BalanceComputationArea, Double> balanceOffsets = new LinkedHashMap<>();
private final Map<BalanceComputationArea, Double> balanceMismatches = new HashMap<>();
private final Reporter reporter;
private Reporter iterationReporter;
/**
* The root node of the report for balance adjustment
*/
private final ReportNode reportNode;
/**
* The node where information about the current iteration of balance adjustment is reported
*/
private ReportNode iterationReportNode;

public BalanceComputationRunningContext(List<BalanceComputationArea> areas, Network network, BalanceComputationParameters parameters) {
this(areas, network, parameters, Reporter.NO_OP);
this(areas, network, parameters, ReportNode.NO_OP);
}

public BalanceComputationRunningContext(List<BalanceComputationArea> areas, Network network, BalanceComputationParameters parameters, Reporter reporter) {
public BalanceComputationRunningContext(List<BalanceComputationArea> areas, Network network, BalanceComputationParameters parameters, ReportNode reportNode) {
this.iterationNum = 0;
this.network = network;
this.parameters = parameters;
this.reporter = reporter;
this.iterationReporter = Reporter.NO_OP;
this.reportNode = reportNode;
this.iterationReportNode = ReportNode.NO_OP;
networkAreas = areas.stream().collect(Collectors.toMap(Function.identity(), ba -> ba.getNetworkAreaFactory().create(network), (v1, v2) -> v1, LinkedHashMap::new));
balanceOffsets.clear();
balanceMismatches.clear();
Expand Down Expand Up @@ -249,16 +255,16 @@ public void updateAreaOffsetAndMismatch(BalanceComputationArea area, double mism
balanceMismatches.put(area, mismatch);
}

public Reporter getReporter() {
return reporter;
public ReportNode getReportNode() {
return reportNode;
}

public Reporter getIterationReporter() {
return iterationReporter;
public ReportNode getIterationReportNode() {
return iterationReportNode;
}

public BalanceComputationRunningContext setIterationReporter(Reporter iterationReporter) {
this.iterationReporter = iterationReporter;
public BalanceComputationRunningContext setIterationReportNode(ReportNode iterationReportNode) {
this.iterationReportNode = iterationReportNode;
return this;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
*/
package com.powsybl.balances_adjustment.util;

import com.powsybl.commons.reporter.Report;
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.commons.reporter.TypedValue;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
* @author George Budau {@literal <george.budau at artelys.com>}
Expand All @@ -25,62 +23,58 @@ public final class Reports {
private Reports() {
}

public static void reportScaling(Reporter reporter, String areaName, double offset, double done) {
reporter.report(Report.builder()
.withKey("areaScaling")
.withDefaultMessage("Scaling for area ${areaName}: offset=${offset}, done=${done}")
.withValue(AREA_NAME, areaName)
.withValue("offset", offset)
.withValue("done", done)
public static void reportScaling(ReportNode reportNode, String areaName, double offset, double done) {
reportNode.newReportNode().withMessageTemplate("areaScaling",
"Scaling for area ${areaName}: offset=${offset}, done=${done}")
.withUntypedValue(AREA_NAME, areaName)
.withUntypedValue("offset", offset)
.withUntypedValue("done", done)
.withSeverity(TypedValue.INFO_SEVERITY)
.build());
.add();
}

public static void reportLfStatus(Reporter reporter, int networkNumCc, int networkNumSc, String status, TypedValue severity) {
reporter.report(Report.builder()
.withKey("lfStatus")
.withDefaultMessage("Network CC${networkNumCc} SC${networkNumSc} Load flow complete with status '${status}'")
.withValue("networkNumCc", networkNumCc)
.withValue("networkNumSc", networkNumSc)
.withValue("status", status)
public static void reportLfStatus(ReportNode reportNode, int networkNumCc, int networkNumSc, String status, TypedValue severity) {
reportNode.newReportNode().withMessageTemplate("lfStatus",
"Network CC${networkNumCc} SC${networkNumSc} Load flow complete with status '${status}'")
.withUntypedValue("networkNumCc", networkNumCc)
.withUntypedValue("networkNumSc", networkNumSc)
.withUntypedValue("status", status)
.withSeverity(severity)
.build());
.add();
}

public static void reportAreaMismatch(Reporter reporter, String areaName, double mismatch, double target, double balance) {
reporter.report(Report.builder()
.withKey("areaMismatch")
.withDefaultMessage("Mismatch for area ${areaName}: ${mismatch} (target=${target}, balance=${balance})")
.withValue(AREA_NAME, areaName)
.withValue("mismatch", mismatch)
.withValue("target", target)
.withValue("balance", balance)
public static void reportAreaMismatch(ReportNode reportNode, String areaName, double mismatch, double target, double balance) {
reportNode.newReportNode().withMessageTemplate("areaMismatch",
"Mismatch for area ${areaName}: ${mismatch} (target=${target}, balance=${balance})")
.withUntypedValue(AREA_NAME, areaName)
.withUntypedValue("mismatch", mismatch)
.withUntypedValue("target", target)
.withUntypedValue("balance", balance)
.withSeverity(TypedValue.INFO_SEVERITY)
.build());
.add();
}

public static void reportBalancedAreas(Reporter reporter, List<String> networkAreasName, int iterationCount) {
reporter.report(Report.builder()
.withKey("balancedAreas")
.withDefaultMessage("Areas ${networkAreasName} are balanced after ${iterationCount} iterations")
.withValue("networkAreasName", networkAreasName.toString())
.withValue("iterationCount", iterationCount)
public static void reportBalancedAreas(ReportNode reportNode, List<String> networkAreasName, int iterationCount) {
reportNode.newReportNode().withMessageTemplate("balancedAreas",
"Areas ${networkAreasName} are balanced after ${iterationCount} iterations")
.withUntypedValue("networkAreasName", networkAreasName.toString())
.withUntypedValue("iterationCount", iterationCount)
.withSeverity(TypedValue.INFO_SEVERITY)
.build());
.add();
}

public static void reportUnbalancedAreas(Reporter reporter, int iteration, BigDecimal totalMismatch) {
reporter.report(Report.builder()
.withKey("unbalancedAreas")
.withDefaultMessage("Areas are unbalanced after ${iteration} iterations, total mismatch is ${totalMismatch}")
.withValue(ITERATION, iteration)
.withValue("totalMismatch", totalMismatch.toString())
public static void reportUnbalancedAreas(ReportNode reportNode, int iteration, BigDecimal totalMismatch) {
reportNode.newReportNode().withMessageTemplate("unbalancedAreas",
"Areas are unbalanced after ${iteration} iterations, total mismatch is ${totalMismatch}")
.withUntypedValue(ITERATION, iteration)
.withUntypedValue("totalMismatch", totalMismatch.toString())
.withSeverity(TypedValue.ERROR_SEVERITY)
.build());
.add();
}

public static Reporter createBalanceComputationIterationReporter(Reporter reporter, int iteration) {
return reporter.createSubReporter("balanceComputation", "Balance Computation iteration '${iteration}'",
Map.of(ITERATION, new TypedValue(iteration, TypedValue.UNTYPED)));
public static ReportNode createBalanceComputationIterationReportNode(ReportNode reportNode, int iteration) {
return reportNode.newReportNode().withMessageTemplate("balanceComputation", "Balance Computation iteration '${iteration}'")
.withUntypedValue(ITERATION, iteration)
.add();
}
}
Loading
Loading