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

com.powsybl.psse.model.pf.PsseFixes Maven / Gradle / Ivy

There is a newer version: 6.6.0
Show newest version
/**
 * Copyright (c) 2023, 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.psse.model.pf;

import com.powsybl.psse.model.PsseVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.function.Function;

/**
 * @author Luma Zamarreño {@literal }
 * @author José Antonio Marqués {@literal }
 */
public class PsseFixes {

    private static final Logger LOGGER = LoggerFactory.getLogger(PsseFixes.class);
    private final PssePowerFlowModel model;
    private final PsseVersion version;

    public PsseFixes(PssePowerFlowModel model, PsseVersion version) {
        this.model = Objects.requireNonNull(model);
        this.version = Objects.requireNonNull(version);
    }

    public void fix() {
        fixDuplicatedIds();
        fixTransformersWindingCod();
    }

    private void fixDuplicatedIds() {
        fixDuplicatedIds(model.getLoads(), l -> l.getI() + "-" + l.getId(), this::loadFixer);
        fixDuplicatedIds(model.getGenerators(), g -> g.getI() + "-" + g.getId(), this::generatorFixer);
        fixDuplicatedIds(model.getFixedShunts(), sh -> sh.getI() + "-" + sh.getId(), this::fixedShuntFixer);
        // For branches and transformers, we build the complete id using the sorted nodes plus the circuit id
        fixDuplicatedIds(model.getNonTransformerBranches(), b -> sortedBuses(b.getI(), b.getJ()) + b.getCkt(), this::nonTransformerBranchFixer);
        fixDuplicatedIds(model.getTransformers(), b -> sortedBuses(b.getI(), b.getJ(), b.getK()) + b.getCkt(), this::transformerFixer);
        if (version.getMajorNumber() >= 35) {
            fixDuplicatedIds(model.getSwitchedShunts(), sh -> sh.getI() + "-" + sh.getId(), this::switchedShuntFixer);
        }
    }

    private void fixTransformersWindingCod() {
        model.getTransformers().forEach(psseTransformer -> {
            if (psseTransformer.getK() == 0) { // TwoWindingsTransformers
                fixTransformerWindingCod(psseTransformer, psseTransformer.getWinding1(), "Winding1");
            } else {
                fixTransformerWindingCod(psseTransformer, psseTransformer.getWinding1(), "Winding1");
                fixTransformerWindingCod(psseTransformer, psseTransformer.getWinding2(), "Winding2");
                fixTransformerWindingCod(psseTransformer, psseTransformer.getWinding3(), "Winding3");
            }
        });
    }

    private String sortedBuses(int... buses) {
        Arrays.sort(buses);
        return Arrays.toString(buses);
    }

    private  void fixDuplicatedIds(List psseObjects, Function idBuilder, IdFixer idFixer) {
        Set foundIds = new HashSet<>();
        Map> duplicated = new HashMap<>();
        psseObjects.forEach(psseObject -> {
            String id = idBuilder.apply(psseObject);
            if (foundIds.contains(id)) {
                duplicated.computeIfAbsent(id, key -> new ArrayList<>()).add(psseObject);
            }
            foundIds.add(id);
        });
        duplicated.forEach((id, duplicatedIdObjects) -> {
            final Set usedIds = new HashSet<>();
            usedIds.add(id);
            duplicatedIdObjects.forEach(psseObject -> {
                String fixedId = idFixer.fix(psseObject, usedIds);
                usedIds.add(fixedId);
            });
        });
    }

    private String buildFixedId2(String id, Set usedIds) {
        // The id is only two characters long, and we try to preserve the first character
        // We avoid setting a 0 as first character because PSSE may interpret them as not valid
        String first = id.isEmpty() ? "1" : id.substring(0, 1);
        for (char second = '0'; second <= '9'; second++) {
            String candidate = first + second;
            if (usedIds.contains(candidate)) {
                continue;
            }
            return candidate;
        }
        // try with an uppercase letter, if all digits have been used
        for (char second = 'A'; second <= 'Z'; second++) {
            String candidate = first + second;
            if (usedIds.contains(candidate)) {
                continue;
            }
            return candidate;
        }
        // we run out of candidates, return the same id
        return id;
    }

    private String loadFixer(PsseLoad load, Set usedIds) {
        String id = load.getId();
        String fixedId = buildFixedId2(id, usedIds);
        load.setId(fixedId);
        warn("Load", load.getI(), id, fixedId);
        return fixedId;
    }

    private String generatorFixer(PsseGenerator generator, Set usedIds) {
        String id = generator.getId();
        String fixedId = buildFixedId2(id, usedIds);
        generator.setId(fixedId);
        warn("Generator", generator.getI(), id, fixedId);
        return fixedId;
    }

    private String fixedShuntFixer(PsseFixedShunt fixedShunt, Set usedIds) {
        String id = fixedShunt.getId();
        String fixedId = buildFixedId2(id, usedIds);
        fixedShunt.setId(fixedId);
        warn("FixedShunt", fixedShunt.getI(), id, fixedId);
        return fixedId;
    }

    private String switchedShuntFixer(PsseSwitchedShunt switchedShunt, Set usedIds) {
        String id = switchedShunt.getId();
        String fixedId = buildFixedId2(id, usedIds);
        switchedShunt.setId(fixedId);
        warn("SwitchedShunt", switchedShunt.getI(), id, fixedId);
        return fixedId;
    }

    private String nonTransformerBranchFixer(PsseNonTransformerBranch branch, Set usedIds) {
        String id = branch.getCkt();
        String fixedId = buildFixedId2(id, usedIds);
        branch.setCkt(fixedId);
        warn(branch, id, fixedId);
        return fixedId;
    }

    private String transformerFixer(PsseTransformer transformer, Set usedIds) {
        String id = transformer.getCkt();
        String fixedId = buildFixedId2(id, usedIds);
        transformer.setCkt(fixedId);
        warn(transformer, id, fixedId);
        return fixedId;
    }

    private void fixTransformerWindingCod(PsseTransformer transformer, PsseTransformerWinding winding, String windingTag) {
        if (Math.abs(winding.getCod()) == 1 && winding.getCont() == 0) {
            warn(transformer, windingTag, winding.getCod(), 0);
            winding.setCod(0);
        }
    }

    private void warn(String type, int i, String id, String fixedId) {
        if (LOGGER.isWarnEnabled()) {
            if (id.equals(fixedId)) {
                LOGGER.warn("Unable to fix {} Id: I {} ID '{}'", type, i, id);
            } else {
                LOGGER.warn("{} Id fixed: I {} ID '{}'. Fixed ID '{}'", type, i, id, fixedId);
            }
        }
    }

    private void warn(PsseNonTransformerBranch branch, String id, String fixedId) {
        if (LOGGER.isWarnEnabled()) {
            if (id.equals(fixedId)) {
                LOGGER.warn("Unable to fix NonTransformerBranch Id: I {} J {} CKT '{}'", branch.getI(), branch.getJ(), id);
            } else {
                LOGGER.warn("NonTransformerBranch Id fixed: I {} J {} CKT '{}'. Fixed CKT '{}'", branch.getI(), branch.getJ(), id, fixedId);
            }
        }
    }

    private void warn(PsseTransformer transformer, String id, String fixedId) {
        if (LOGGER.isWarnEnabled()) {
            if (id.equals(fixedId)) {
                LOGGER.warn("Unable to fix Transformer Id: I {} J {} K {} CKT '{}'", transformer.getI(), transformer.getJ(), transformer.getK(), id);
            } else {
                LOGGER.warn("Transformer Id fixed: I {} J {} K {} CKT '{}'. Fixed CKT '{}'", transformer.getI(), transformer.getJ(), transformer.getK(), id, fixedId);
            }
        }
    }

    private void warn(PsseTransformer transformer, String windingTag, int cod, int fixedCod) {
        if (LOGGER.isWarnEnabled()) {
            LOGGER.warn("Transformer {} Cod fixed: I {} J {} K {} CKT {}. Cod '{}' Fixed Cod '{}'. Controlled bus is not defined (cont == 0).", windingTag, transformer.getI(), transformer.getJ(), transformer.getK(), transformer.getCkt(), cod, fixedCod);
        }
    }

    @FunctionalInterface
    public interface IdFixer {
        String fix(T t, Set usedIds);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy