All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.powsybl.matpower.model.MatpowerReader Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2020, RTE (http://www.rte-france.com)
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * SPDX-License-Identifier: MPL-2.0
 */
package com.powsybl.matpower.model;

import com.google.common.collect.Sets;
import us.hebi.matlab.mat.format.Mat5;
import us.hebi.matlab.mat.types.*;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * @author Christian Biasuzzi {@literal }
 */
public final class MatpowerReader {

    public static final String MATPOWER_STRUCT_NAME = "mpc";
    public static final String MATPOWER_SUPPORTED_VERSION = "2";
    public static final int MATPOWER_BUSES_COLUMNS = 13;
    public static final int MATPOWER_GENERATORS_COLUMNS = 21;
    public static final int MATPOWER_BRANCHES_COLUMNS = 13;
    public static final int MATPOWER_DCLINES_COLUMNS = 17;

    private MatpowerReader() {
    }

    public static MatpowerModel read(Path file, String caseName) throws IOException {
        try (InputStream stream = Files.newInputStream(file)) {
            return read(stream, caseName);
        }
    }

    public static MatpowerModel read(InputStream iStream, String caseName) throws IOException {
        Objects.requireNonNull(iStream);

        MatpowerModel model = null;
        try (MatFile mat = Mat5.newReader(Sources.wrapInputStream(iStream)).setEntryFilter(entry -> entry.getName().equals(MATPOWER_STRUCT_NAME)).readMat()) {
            if (mat.getNumEntries() == 0) {
                throw new IllegalStateException("no MATPOWER data: expected structure named '" + MATPOWER_STRUCT_NAME + "' not found.");
            }
            Struct mpcStruct = mat.getStruct(MATPOWER_STRUCT_NAME);
            Set mpcNames = Sets.newHashSet("version", "baseMVA", "bus", "gen", "branch");
            Set fieldNames = new HashSet<>(mpcStruct.getFieldNames());
            if (!fieldNames.containsAll(mpcNames)) {
                throw new IllegalStateException("expected MATPOWER variables not found: " + mpcNames);
            }
            String version = mpcStruct.get("version").toString().replace("'", "");
            if (!version.equals(MATPOWER_SUPPORTED_VERSION)) {
                throw new IllegalStateException("unsupported MATPOWER version: " + version);
            }

            double baseMVA = mpcStruct.getMatrix("baseMVA").getDouble(0);
            Matrix buses = mpcStruct.getMatrix("bus");
            Matrix generators = mpcStruct.getMatrix("gen");
            Matrix branches = mpcStruct.getMatrix("branch");
            Cell busesNames = null;
            if (fieldNames.contains("bus_name")) {
                busesNames = mpcStruct.getCell("bus_name");
            }
            Matrix dcLines = null;
            if (fieldNames.contains("dcline")) {
                dcLines = mpcStruct.getMatrix("dcline");
            }

            checkNumberOfColumns(buses, generators, branches, dcLines);

            model = new MatpowerModel(caseName);
            model.setVersion(version);
            model.setBaseMva(baseMVA);

            readBuses(buses, busesNames, model);
            readGenerators(generators, model);
            readBranches(branches, model);
            readDcLines(dcLines, model);
        }

        return model;
    }

    private static void checkNumberOfColumns(Matrix buses, Matrix generators, Matrix branches, Matrix dcLines) {
        if (buses.getDimensions()[1] < MATPOWER_BUSES_COLUMNS
                || generators.getDimensions()[1] < MATPOWER_GENERATORS_COLUMNS
                || branches.getDimensions()[1] < MATPOWER_BRANCHES_COLUMNS
                || dcLines != null && dcLines.getDimensions()[1] < MATPOWER_DCLINES_COLUMNS) {

            String exceptionMessage;
            if (dcLines == null) {
                exceptionMessage = String.format("Unexpected number of columns. Expected: Buses %d Generators %d Branches %d Received: Buses %d Generators %d Branches %d",
                        MATPOWER_BUSES_COLUMNS, MATPOWER_GENERATORS_COLUMNS, MATPOWER_BRANCHES_COLUMNS,
                        buses.getDimensions()[1], generators.getDimensions()[1], branches.getDimensions()[1]);
            } else {
                exceptionMessage = String.format("Unexpected number of columns. Expected: Buses %d Generators %d Branches %d DcLines %d Received: Buses %d Generators %d Branches %d DcLines %d",
                        MATPOWER_BUSES_COLUMNS, MATPOWER_GENERATORS_COLUMNS, MATPOWER_BRANCHES_COLUMNS, MATPOWER_DCLINES_COLUMNS,
                        buses.getDimensions()[1], generators.getDimensions()[1], branches.getDimensions()[1], dcLines.getDimensions()[1]);
            }
            throw new IllegalStateException(exceptionMessage);
        }
    }

    private static void readBuses(Matrix buses, Cell busesNames, MatpowerModel model) {
        for (int row = 0; row < buses.getDimensions()[0]; row++) {
            MBus bus = new MBus();
            bus.setNumber(buses.getInt(row, 0));
            if (busesNames != null) {
                String name = busesNames.getChar(row).getString();
                bus.setName(name);
            }
            bus.setType(MBus.Type.fromInt(buses.getInt(row, 1)));
            bus.setRealPowerDemand(buses.getDouble(row, 2));
            bus.setReactivePowerDemand(buses.getDouble(row, 3));
            bus.setShuntConductance(buses.getDouble(row, 4));
            bus.setShuntSusceptance(buses.getDouble(row, 5));
            bus.setAreaNumber(buses.getInt(row, 6));
            bus.setVoltageMagnitude(buses.getDouble(row, 7));
            bus.setVoltageAngle(buses.getDouble(row, 8));
            bus.setBaseVoltage(buses.getDouble(row, 9));
            bus.setLossZone(buses.getInt(row, 10));
            bus.setMaximumVoltageMagnitude(buses.getDouble(row, 11));
            bus.setMinimumVoltageMagnitude(buses.getDouble(row, 12));

            model.addBus(bus);
        }
    }

    private static void readGenerators(Matrix generators, MatpowerModel model) {
        for (int row = 0; row < generators.getDimensions()[0]; row++) {
            MGen gen = new MGen();
            gen.setNumber(generators.getInt(row, 0));
            gen.setRealPowerOutput(generators.getDouble(row, 1));
            gen.setReactivePowerOutput(generators.getDouble(row, 2));
            gen.setMaximumReactivePowerOutput(generators.getDouble(row, 3));
            gen.setMinimumReactivePowerOutput(generators.getDouble(row, 4));
            gen.setVoltageMagnitudeSetpoint(generators.getDouble(row, 5));
            gen.setTotalMbase(generators.getDouble(row, 6));
            gen.setStatus(generators.getInt(row, 7));
            gen.setMaximumRealPowerOutput(generators.getDouble(row, 8));
            gen.setMinimumRealPowerOutput(generators.getDouble(row, 9));
            gen.setPc1(generators.getDouble(row, 10));
            gen.setPc2(generators.getDouble(row, 11));
            gen.setQc1Min(generators.getDouble(row, 12));
            gen.setQc1Max(generators.getDouble(row, 13));
            gen.setQc2Min(generators.getDouble(row, 14));
            gen.setQc2Max(generators.getDouble(row, 15));
            gen.setRampAgc(generators.getDouble(row, 16));
            gen.setRampTenMinutes(generators.getDouble(row, 17));
            gen.setRampThirtyMinutes(generators.getDouble(row, 18));
            gen.setRampQ(generators.getDouble(row, 19));
            gen.setApf(generators.getDouble(row, 20));

            model.addGenerator(gen);
        }
    }

    private static void readBranches(Matrix branches, MatpowerModel model) {
        for (int row = 0; row < branches.getDimensions()[0]; row++) {
            MBranch branch = new MBranch();
            branch.setFrom(branches.getInt(row, 0));
            branch.setTo(branches.getInt(row, 1));
            branch.setR(branches.getDouble(row, 2));
            branch.setX(branches.getDouble(row, 3));
            branch.setB(branches.getDouble(row, 4));
            branch.setRateA(branches.getDouble(row, 5));
            branch.setRateB(branches.getDouble(row, 6));
            branch.setRateC(branches.getDouble(row, 7));
            branch.setRatio(branches.getDouble(row, 8));
            branch.setPhaseShiftAngle(branches.getDouble(row, 9));
            branch.setStatus(branches.getInt(row, 10));
            branch.setAngMin(branches.getDouble(row, 11));
            branch.setAngMax(branches.getDouble(row, 12));
            model.addBranch(branch);
        }
    }

    private static void readDcLines(Matrix dcLines, MatpowerModel model) {
        if (dcLines == null) {
            return;
        }
        for (int row = 0; row < dcLines.getDimensions()[0]; row++) {
            MDcLine dcLine = new MDcLine();

            dcLine.setFrom(dcLines.getInt(row, 0));
            dcLine.setTo(dcLines.getInt(row, 1));
            dcLine.setStatus(dcLines.getInt(row, 2));
            dcLine.setPf(dcLines.getDouble(row, 3));
            dcLine.setPt(dcLines.getDouble(row, 4));
            dcLine.setQf(dcLines.getDouble(row, 5));
            dcLine.setQt(dcLines.getDouble(row, 6));
            dcLine.setVf(dcLines.getDouble(row, 7));
            dcLine.setVt(dcLines.getDouble(row, 8));
            dcLine.setPmin(dcLines.getDouble(row, 9));
            dcLine.setPmax(dcLines.getDouble(row, 10));
            dcLine.setQminf(dcLines.getDouble(row, 11));
            dcLine.setQmaxf(dcLines.getDouble(row, 12));
            dcLine.setQmint(dcLines.getDouble(row, 13));
            dcLine.setQmaxt(dcLines.getDouble(row, 14));
            dcLine.setLoss0(dcLines.getDouble(row, 15));
            dcLine.setLoss1(dcLines.getDouble(row, 16));

            model.addDcLine(dcLine);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy