WCASecurityRulesWriter implements WCAConstants { public void write() { try (Writer writer = new OutputStreamWriter(dataSource.newOutputStream(SECURITY_RULES_FILE_SUFFIX, TXT_EXT, false), StandardCharsets.UTF_8); TableFormatter formatter = new AmplDatTableFormatter( writer, "Security rules", AmplConstants.INVALID_FLOAT_VALUE, true, AmplConstants.LOCALE, new Column("inequality num"), new Column("convex num"), new Column("var type (1: P, 2: Q, 3: V)"), new Column("entity type (1: branch, 2: load, 3: generator, 4: compensator shunt, 5: substation)"), new Column("entity num"), new Column("branch side (1 or 2, 0 if NA)"), new Column("inequality coeff."), new Column("constant value"), new Column("contingency num"), new Column("security index type"), new Column("attribute set (0: active only, 1: active/reactive)"))) { class Context { int inegNum; int convexNum; Context(int inegNum, int convexNum) { this.inegNum = inegNum; this.convexNum = convexNum; } } Context context = new Context(1, 1); for (SecurityRuleExpression rule : rules) { RuleId ruleId = rule.getRuleId(); SecurityIndexType securityIndexType = ruleId.getSecurityIndexId().getSecurityIndexType(); RuleAttributeSet attributeSet = ruleId.getAttributeSet(); final int indexTypeNum = securityIndexType.ordinal(); final int attributeSetNum = attributeSet.ordinal(); if (rule.getStatus() == SecurityRuleStatus.ALWAYS_UNSECURE) { if (activateFiltering) { throw new RuntimeException("Always unsecure rule " + ruleId); } else { continue; } } if (rule.getStatus() == SecurityRuleStatus.ALWAYS_SECURE) { continue; } ExpressionNode expr = rule.getCondition(); if (expr != null) { if (debug) { System.out.println(ExpressionTreePrinter.toString(expr)); } formatter.writeComment(ExpressionFlatPrinter.toString(expr)); expr.accept(new ExpressionVisitor<Void, Context>() { @Override public Void visit(Attribute attr, Context context) { throw new AssertionError(); } @Override public Void visit(Litteral value, Context context) { throw new AssertionError(); } @Override public Void visit(ComparisonOperator comp, Context context) { try { HistoDbNetworkAttributeId attrId = (HistoDbNetworkAttributeId) comp.getNode1().getId(); WCAEntity entity = toEntity(attrId, network, mapper); if (entity == null) { LOGGER.warn("Equipment '" + attrId.getEquipmentId() + "' not found"); return null; } double threshold = comp.getNode2().getValue(); int varType; switch (attrId.getAttributeType()) { case P: varType = 1; break; case Q: varType = 2; break; case V: varType = 3; break; default: throw new RuntimeException("Unsupported attribute type '" + attrId.getAttributeType()); } formatter.writeCell(context.inegNum++) .writeCell(context.convexNum) .writeCell(varType); formatter.writeCell(entity.type) .writeCell(entity.num) .writeCell(entity.sideNum); double thresholdPu; if (attrId.getAttributeType() == HistoDbAttr.V) { thresholdPu = threshold / entity.nomV; } else { thresholdPu = threshold; } switch (comp.getType()) { case LESS: formatter.writeCell(1f); formatter.writeCell(thresholdPu); break; case GREATER_EQUAL: formatter.writeCell(-1f); formatter.writeCell(-thresholdPu); break; default: throw new InternalError(); } formatter.writeCell(mapper.getInt(AmplSubset.FAULT, ruleId.getSecurityIndexId().getContingencyId())) .writeCell(indexTypeNum) .writeCell(attributeSetNum); } catch (IOException e) { throw new RuntimeException(e); } return null; } @Override public Void visit(AndOperator and, Context context) { and.getNode1().accept(this, context); and.getNode2().accept(this, context); return null; } @Override public Void visit(OrOperator or, Context context) { context.convexNum++; or.getNode1().accept(this, context); context.convexNum++; or.getNode2().accept(this, context); return null; } }, context); context.convexNum++; } } } catch (IOException e) { throw new RuntimeException(e); } } WCASecurityRulesWriter(Network network, List<SecurityRuleExpression> rules, DataSource dataSource,
                                  StringToIntMapper<AmplSubset> mapper, boolean debug, boolean activateFiltering); void write();  }
@Test public void testWrite() { ContingencyElement contingencyElement = new BranchContingency("line"); Contingency contingency = new Contingency("contigency_1", contingencyElement); Network network = NetworkTest1Factory.create(); List<SecurityRuleExpression> rules = new ArrayList<>(); SecurityIndexType securityIndexType = SecurityIndexType.TSO_OVERLOAD; SecurityIndexId securityIndexId = new SecurityIndexId(contingency.getId(), securityIndexType); RuleAttributeSet ruleAttributeSet = RuleAttributeSet.WORST_CASE; RuleId ruleId = new RuleId(ruleAttributeSet, securityIndexId); ComparisonOperator condition1 = new ComparisonOperator( new Attribute(new HistoDbNetworkAttributeId(network.getLoads().iterator().next().getId(), HistoDbAttr.P)), new Litteral(10d), ComparisonOperator.Type.GREATER_EQUAL); ComparisonOperator condition2 = new ComparisonOperator( new Attribute(new HistoDbNetworkAttributeId(network.getGenerators().iterator().next().getId(), HistoDbAttr.Q)), new Litteral(5d), ComparisonOperator.Type.LESS); ExpressionNode condition = new AndOperator(condition1, condition2); rules.add(new SecurityRuleExpression(ruleId, SecurityRuleStatus.SECURE_IF, condition)); MemDataSource dataSource = new MemDataSource(); StringToIntMapper<AmplSubset> mapper = new StringToIntMapper<>(AmplSubset.class); AmplUtil.fillMapper(mapper, network); mapper.newInt(AmplSubset.FAULT, contingency.getId()); new WCASecurityRulesWriter(network, rules, dataSource, mapper, false, false).write(); String fileContent = String.join(System.lineSeparator(), "#(("+ network.getLoads().iterator().next().getId() + "_P >= 10.0) AND ("+ network.getGenerators().iterator().next().getId() + "_Q < 5.0))", "#Security rules", "#\"inequality num\" \"convex num\" \"var type (1: P, 2: Q, 3: V)\" \"entity type (1: branch, 2: load, 3: generator, 4: compensator shunt, 5: substation)\" \"entity num\" \"branch side (1 or 2, 0 if NA)\" \"inequality coeff.\" \"constant value\" \"contingency num\" \"security index type\" \"attribute set (0: active only, 1: active/reactive)\"", "1 1 1 2 1 0 -1.00000 -10.0000 1 4 0", "2 1 2 3 1 0 1.00000 5.00000 1 4 0"); assertEquals(fileContent, new String(dataSource.getData(WCAConstants.SECURITY_RULES_FILE_SUFFIX, WCAConstants.TXT_EXT), StandardCharsets.UTF_8).trim()); }