Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.powsybl.cgmes.model.CgmesTerminal;
import com.powsybl.iidm.network.*;
import com.powsybl.math.graph.TraverseResult;
import com.powsybl.triplestore.api.PropertyBag;

import java.util.*;
import java.util.function.Function;
Expand Down Expand Up @@ -42,9 +43,11 @@ public static Optional<Terminal> mapForVoltageControl(String cgmesTerminalId, Co
.or(() -> new EquivalentTerminalFinderVoltageControl(cgmesTerminalId, context).find())
// As a last resource, rely on the "find" method of terminal mapping:
// Bus/branch models may define remote voltage controls that point to busbar sections
// Busbar sections are not mapped to IIDM
// Since busbar sections are not mapped to IIDM, we look for an equivalent IIDM terminal
// is connected to the busbar section via switches
.or(() -> Optional.ofNullable(context.terminalMapping()
.findFromTopologicalNode(context.terminalMapping().getTopologicalNode(cgmesTerminalId))));
.findFromTopologicalNode(context.terminalMapping().getTopologicalNode(cgmesTerminalId)))
.or(() -> findEquivalentTerminalForVoltageRegulatingTerminalDefinedAtBusbarSection(cgmesTerminalId, context)));
}

public static Optional<TerminalAndSign> mapForFlowControl(String cgmesTerminalId, Context context) {
Expand Down Expand Up @@ -399,6 +402,30 @@ private Optional<Terminal> findBusBranch() {
}
}

static Optional<Terminal> findEquivalentTerminalForVoltageRegulatingTerminalDefinedAtBusbarSection(String cgmesTerminalId, Context context) {
CgmesTerminal busbarSectionCgmesTerminal = context.cgmes().terminal(cgmesTerminalId);
String switchCgmesTerminalId = busbarSectionCgmesTerminal != null
? findSwitchCgmesTerminalIdForConnectivityNode(busbarSectionCgmesTerminal.connectivityNode(), context).orElse(null)
: null;
return switchCgmesTerminalId != null ? new EquivalentTerminalFinderVoltageControl(switchCgmesTerminalId, context).find() : Optional.empty();
}

private static Optional<String> findSwitchCgmesTerminalIdForConnectivityNode(String connectivityNode, Context context) {
return context.cgmes().switches().stream()
.map(swPropertyBag -> getSwitchCgmesTerminalId(swPropertyBag, connectivityNode, context))
.filter(Objects::nonNull)
.findFirst();
}

private static String getSwitchCgmesTerminalId(PropertyBag swPropertyBag, String connectivityNode, Context context) {
return Stream.of(CgmesNames.TERMINAL1, CgmesNames.TERMINAL2)
.map(swPropertyBag::getId)
.filter(Objects::nonNull)
.filter(id -> connectivityNode.equals(context.cgmes().terminal(id).connectivityNode()))
.findFirst()
.orElse(null);
}

private static Bus getTerminalBus(Terminal terminal) {
return terminal.getBusBreakerView().getBus() != null ? terminal.getBusBreakerView().getBus()
: terminal.getBusBreakerView().getConnectableBus();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@

import com.powsybl.cgmes.conformity.Cgmes3ModifiedCatalog;
import com.powsybl.cgmes.conformity.CgmesConformity1ModifiedCatalog;
import com.powsybl.cgmes.conversion.CgmesImport;
import com.powsybl.cgmes.conversion.Conversion;
import com.powsybl.cgmes.model.GridModelReference;
import com.powsybl.iidm.network.*;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.Properties;

import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources;
import static org.junit.jupiter.api.Assertions.*;

/**
* @author Luma Zamarreño {@literal <zamarrenolm at aia.es>}
Expand Down Expand Up @@ -86,6 +89,39 @@ void microGridBaseBECaseRegulatingTerminalsDefinedOnSwitches() {
assertEquals(21.987, regulationValue, 0.0);
}

@Test
void voltageRegulatingTerminalAtBusbarSectionNodeBreakerTest() {
Network network = readCgmesResources("/issues/voltage-regulating-terminal-at-busbar-section",
"issue_3560_CGMES_EQ.xml",
"issue_3560_CGMES_SSH.xml",
"issue_3560_CGMES_SV.xml",
"issue_3560_CGMES_TP.xml");

Generator generator = network.getGenerator("GEN");
assertNotNull(generator);
assertEquals("VL2_400_BBS1", generator.getRegulatingTerminal().getConnectable().getId());
System.err.printf("Type %s %n", generator.getRegulatingTerminal().getConnectable().getType());
assertSame(IdentifiableType.BUSBAR_SECTION, generator.getRegulatingTerminal().getConnectable().getType());
}

@Test
void voltageRegulatingTerminalAtBusbarSectionBusBreakerTest() {
Properties importParams = new Properties();
importParams.put(CgmesImport.IMPORT_NODE_BREAKER_AS_BUS_BREAKER, "true");

Network network = readCgmesResources(importParams,
"/issues/voltage-regulating-terminal-at-busbar-section",
"issue_3560_CGMES_EQ.xml",
"issue_3560_CGMES_SSH.xml",
"issue_3560_CGMES_SV.xml",
"issue_3560_CGMES_TP.xml");

Generator generator = network.getGenerator("GEN");
assertNotNull(generator);
assertEquals("LOAD", generator.getRegulatingTerminal().getConnectable().getId());
assertSame(IdentifiableType.LOAD, generator.getRegulatingTerminal().getConnectable().getType());
}

private Network networkModel(GridModelReference testGridModel, Conversion.Config config) {
config.setConvertSvInjections(true);
return ConversionUtil.networkModel(testGridModel, config);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:entsoe="http://entsoe.eu/CIM/SchemaExtension/3/1#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cim="http://iec.ch/TC57/2013/CIM-schema-cim16#" xmlns:md="http://iec.ch/TC57/61970-552/ModelDescription/1#">
<md:FullModel rdf:about="urn:uuid:test_N_EQUIPMENT_2025-11-15T13:55:26Z_1_1D__FM">
<md:Model.scenarioTime>2025-11-15T13:55:26Z</md:Model.scenarioTime>
<md:Model.created>2025-11-15T13:55:26Z</md:Model.created>
<md:Model.description>EQ Model</md:Model.description>
<md:Model.version>1</md:Model.version>
<md:Model.profile>http://entsoe.eu/CIM/EquipmentCore/3/1</md:Model.profile>
<md:Model.profile>http://entsoe.eu/CIM/EquipmentOperation/3/1</md:Model.profile>
<md:Model.modelingAuthoritySet>powsybl.org</md:Model.modelingAuthoritySet>
</md:FullModel>
<cim:ConnectivityNode rdf:ID="_VL1_400_VL_0_CN">
<cim:IdentifiedObject.name>0</cim:IdentifiedObject.name>
<cim:ConnectivityNode.ConnectivityNodeContainer rdf:resource="#_VL1_400"/>
</cim:ConnectivityNode>
<cim:ConnectivityNode rdf:ID="_VL1_15_VL_0_CN">
<cim:IdentifiedObject.name>0</cim:IdentifiedObject.name>
<cim:ConnectivityNode.ConnectivityNodeContainer rdf:resource="#_VL1_15"/>
</cim:ConnectivityNode>
<cim:ConnectivityNode rdf:ID="_VL2_400_VL_0_CN">
<cim:IdentifiedObject.name>0</cim:IdentifiedObject.name>
<cim:ConnectivityNode.ConnectivityNodeContainer rdf:resource="#_VL2_400"/>
</cim:ConnectivityNode>
<cim:ConnectivityNode rdf:ID="_VL2_400_VL_1_CN">
<cim:IdentifiedObject.name>1</cim:IdentifiedObject.name>
<cim:ConnectivityNode.ConnectivityNodeContainer rdf:resource="#_VL2_400"/>
</cim:ConnectivityNode>
<cim:Terminal rdf:ID="_VL1_400_BBS_BS_T_1">
<cim:IdentifiedObject.name>VL1_400_BBS</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL1_400_BBS"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_400_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_LOAD_EC_T_1">
<cim:IdentifiedObject.name>LOAD</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_LOAD"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_1_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_line_ACLS_T_1">
<cim:IdentifiedObject.name>line</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_line"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_400_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_line_ACLS_T_2">
<cim:IdentifiedObject.name>line</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_line"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_1_CN"/>
<cim:ACDCTerminal.sequenceNumber>2</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_VL1_15_BBS_BS_T_1">
<cim:IdentifiedObject.name>VL1_15_BBS</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL1_15_BBS"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_15_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_2WT_PT_T_1">
<cim:IdentifiedObject.name>2WT</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_2WT"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_15_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_2WT_PT_T_2">
<cim:IdentifiedObject.name>2WT</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_2WT"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_400_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>2</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_GEN_SM_T_1">
<cim:IdentifiedObject.name>GEN</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_GEN"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL1_15_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_VL2_400_BBS1_BS_T_1">
<cim:IdentifiedObject.name>VL2_400_BBS1</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL2_400_BBS1"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_VL2_400_BBS2_BS_T_1">
<cim:IdentifiedObject.name>VL2_400_BBS2</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL2_400_BBS2"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_1_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_VL2_400_COUPLER_SW_T_1">
<cim:IdentifiedObject.name>VL2_400_COUPLER</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL2_400_COUPLER"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_0_CN"/>
<cim:ACDCTerminal.sequenceNumber>1</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Terminal rdf:ID="_VL2_400_COUPLER_SW_T_2">
<cim:IdentifiedObject.name>VL2_400_COUPLER</cim:IdentifiedObject.name>
<cim:Terminal.ConductingEquipment rdf:resource="#_VL2_400_COUPLER"/>
<cim:Terminal.ConnectivityNode rdf:resource="#_VL2_400_VL_1_CN"/>
<cim:ACDCTerminal.sequenceNumber>2</cim:ACDCTerminal.sequenceNumber>
</cim:Terminal>
<cim:Breaker rdf:ID="_VL2_400_COUPLER">
<cim:IdentifiedObject.name>VL2_400_COUPLER</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL2_400"/>
<cim:Switch.normalOpen>false</cim:Switch.normalOpen>
<cim:Switch.retained>true</cim:Switch.retained>
</cim:Breaker>
<cim:GeographicalRegion rdf:ID="_default+region_GR">
<cim:IdentifiedObject.name>default region</cim:IdentifiedObject.name>
</cim:GeographicalRegion>
<cim:SubGeographicalRegion rdf:ID="_default+region_SGR">
<cim:IdentifiedObject.name>default region</cim:IdentifiedObject.name>
<cim:SubGeographicalRegion.Region rdf:resource="#_default+region_GR"/>
</cim:SubGeographicalRegion>
<cim:Substation rdf:ID="_S1">
<cim:IdentifiedObject.name>S1</cim:IdentifiedObject.name>
<cim:Substation.Region rdf:resource="#_default+region_SGR"/>
</cim:Substation>
<cim:Substation rdf:ID="_S2">
<cim:IdentifiedObject.name>S2</cim:IdentifiedObject.name>
<cim:Substation.Region rdf:resource="#_default+region_SGR"/>
</cim:Substation>
<cim:BaseVoltage rdf:ID="_400_BV">
<cim:IdentifiedObject.name>400</cim:IdentifiedObject.name>
<cim:BaseVoltage.nominalVoltage>400</cim:BaseVoltage.nominalVoltage>
</cim:BaseVoltage>
<cim:VoltageLevel rdf:ID="_VL1_400">
<cim:IdentifiedObject.name>VL1_400</cim:IdentifiedObject.name>
<cim:VoltageLevel.Substation rdf:resource="#_S1"/>
<cim:VoltageLevel.BaseVoltage rdf:resource="#_400_BV"/>
</cim:VoltageLevel>
<cim:BaseVoltage rdf:ID="_15_BV">
<cim:IdentifiedObject.name>15</cim:IdentifiedObject.name>
<cim:BaseVoltage.nominalVoltage>15</cim:BaseVoltage.nominalVoltage>
</cim:BaseVoltage>
<cim:VoltageLevel rdf:ID="_VL1_15">
<cim:IdentifiedObject.name>VL1_15</cim:IdentifiedObject.name>
<cim:VoltageLevel.Substation rdf:resource="#_S1"/>
<cim:VoltageLevel.BaseVoltage rdf:resource="#_15_BV"/>
</cim:VoltageLevel>
<cim:VoltageLevel rdf:ID="_VL2_400">
<cim:IdentifiedObject.name>VL2_400</cim:IdentifiedObject.name>
<cim:VoltageLevel.Substation rdf:resource="#_S2"/>
<cim:VoltageLevel.BaseVoltage rdf:resource="#_400_BV"/>
</cim:VoltageLevel>
<cim:BusbarSection rdf:ID="_VL1_400_BBS">
<cim:IdentifiedObject.name>VL1_400_BBS</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL1_400"/>
<cim:ConductingEquipment.BaseVoltage rdf:resource="#_400_BV"/>
</cim:BusbarSection>
<cim:BusbarSection rdf:ID="_VL1_15_BBS">
<cim:IdentifiedObject.name>VL1_15_BBS</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL1_15"/>
<cim:ConductingEquipment.BaseVoltage rdf:resource="#_15_BV"/>
</cim:BusbarSection>
<cim:BusbarSection rdf:ID="_VL2_400_BBS1">
<cim:IdentifiedObject.name>VL2_400_BBS1</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL2_400"/>
<cim:ConductingEquipment.BaseVoltage rdf:resource="#_400_BV"/>
</cim:BusbarSection>
<cim:BusbarSection rdf:ID="_VL2_400_BBS2">
<cim:IdentifiedObject.name>VL2_400_BBS2</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL2_400"/>
<cim:ConductingEquipment.BaseVoltage rdf:resource="#_400_BV"/>
</cim:BusbarSection>
<cim:EnergyConsumer rdf:ID="_LOAD">
<cim:IdentifiedObject.name>LOAD</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL2_400"/>
</cim:EnergyConsumer>
<cim:LoadArea rdf:ID="_test_N_LA">
<cim:IdentifiedObject.name>test Load Area</cim:IdentifiedObject.name>
</cim:LoadArea>
<cim:SubLoadArea rdf:ID="_test_N_SLA">
<cim:IdentifiedObject.name>test SubLoad Area</cim:IdentifiedObject.name>
<cim:SubLoadArea.LoadArea rdf:resource="#_test_N_LA"/>
</cim:SubLoadArea>
<cim:RegulatingControl rdf:ID="_GEN_RC">
<cim:IdentifiedObject.name>RC_GEN</cim:IdentifiedObject.name>
<cim:RegulatingControl.Terminal rdf:resource="#_VL2_400_BBS1_BS_T_1"/>
<cim:RegulatingControl.mode rdf:resource="http://iec.ch/TC57/2013/CIM-schema-cim16#RegulatingControlModeKind.voltage"/>
</cim:RegulatingControl>
<cim:SynchronousMachine rdf:ID="_GEN">
<cim:IdentifiedObject.name>GEN</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_VL1_15"/>
<cim:RotatingMachine.GeneratingUnit rdf:resource="#_GEN_GU"/>
<cim:RegulatingCondEq.RegulatingControl rdf:resource="#_GEN_RC"/>
<cim:SynchronousMachine.minQ>-3.402823E38</cim:SynchronousMachine.minQ>
<cim:SynchronousMachine.maxQ>3.402823E38</cim:SynchronousMachine.maxQ>
<cim:RotatingMachine.ratedS>179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</cim:RotatingMachine.ratedS>
<cim:SynchronousMachine.type rdf:resource="http://iec.ch/TC57/2013/CIM-schema-cim16#SynchronousMachineKind.generatorOrCondenser"/>
</cim:SynchronousMachine>
<cim:GeneratingUnit rdf:ID="_GEN_GU">
<cim:IdentifiedObject.name>GU_GEN</cim:IdentifiedObject.name>
<cim:GeneratingUnit.minOperatingP>0</cim:GeneratingUnit.minOperatingP>
<cim:GeneratingUnit.maxOperatingP>500</cim:GeneratingUnit.maxOperatingP>
<cim:GeneratingUnit.initialP>100</cim:GeneratingUnit.initialP>
<cim:Equipment.EquipmentContainer rdf:resource="#_S1"/>
</cim:GeneratingUnit>
<cim:ACLineSegment rdf:ID="_line">
<cim:IdentifiedObject.name>line</cim:IdentifiedObject.name>
<cim:ACLineSegment.r>0.1</cim:ACLineSegment.r>
<cim:ACLineSegment.x>1</cim:ACLineSegment.x>
<cim:ACLineSegment.bch>0.000002</cim:ACLineSegment.bch>
<cim:ConductingEquipment.BaseVoltage rdf:resource="#_400_BV"/>
</cim:ACLineSegment>
<cim:PowerTransformer rdf:ID="_2WT">
<cim:IdentifiedObject.name>2WT</cim:IdentifiedObject.name>
<cim:Equipment.EquipmentContainer rdf:resource="#_S1"/>
</cim:PowerTransformer>
<cim:PowerTransformerEnd rdf:ID="_2WT_TW1">
<cim:IdentifiedObject.name>2WT_1</cim:IdentifiedObject.name>
<cim:TransformerEnd.endNumber>1</cim:TransformerEnd.endNumber>
<cim:PowerTransformerEnd.r>0.00140625</cim:PowerTransformerEnd.r>
<cim:PowerTransformerEnd.x>0.028125</cim:PowerTransformerEnd.x>
<cim:PowerTransformerEnd.g>0.00071111111111</cim:PowerTransformerEnd.g>
<cim:PowerTransformerEnd.b>0.00071111111111</cim:PowerTransformerEnd.b>
<cim:PowerTransformerEnd.ratedS>100</cim:PowerTransformerEnd.ratedS>
<cim:PowerTransformerEnd.ratedU>15</cim:PowerTransformerEnd.ratedU>
<cim:PowerTransformerEnd.PowerTransformer rdf:resource="#_2WT"/>
<cim:TransformerEnd.Terminal rdf:resource="#_2WT_PT_T_1"/>
<cim:TransformerEnd.BaseVoltage rdf:resource="#_15_BV"/>
</cim:PowerTransformerEnd>
<cim:PowerTransformerEnd rdf:ID="_2WT_TW2">
<cim:IdentifiedObject.name>2WT_2</cim:IdentifiedObject.name>
<cim:TransformerEnd.endNumber>2</cim:TransformerEnd.endNumber>
<cim:PowerTransformerEnd.r>0</cim:PowerTransformerEnd.r>
<cim:PowerTransformerEnd.x>0</cim:PowerTransformerEnd.x>
<cim:PowerTransformerEnd.g>0</cim:PowerTransformerEnd.g>
<cim:PowerTransformerEnd.b>0</cim:PowerTransformerEnd.b>
<cim:PowerTransformerEnd.ratedS>100</cim:PowerTransformerEnd.ratedS>
<cim:PowerTransformerEnd.ratedU>400</cim:PowerTransformerEnd.ratedU>
<cim:PowerTransformerEnd.PowerTransformer rdf:resource="#_2WT"/>
<cim:TransformerEnd.Terminal rdf:resource="#_2WT_PT_T_2"/>
<cim:TransformerEnd.BaseVoltage rdf:resource="#_400_BV"/>
</cim:PowerTransformerEnd>
</rdf:RDF>
Loading