Skip to content

Commit

Permalink
Merge pull request #2 from mancioshell/main
Browse files Browse the repository at this point in the history
Update to new zip and nalgebra crate, with real pandapower json support
  • Loading branch information
chengts95 authored Jul 12, 2024
2 parents 6b5be0c + 265cfab commit fc24111
Show file tree
Hide file tree
Showing 5 changed files with 1,924 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ num-derive = ">=0.3"
num-complex = ">=0.4"
rsparse = "1.0"
csv = "1.3.0"
zip = "1.3.1"
zip = "2.1.3"
[dependencies.klu-rs]
path = "./klu_rs"
optional = true
1,805 changes: 1,805 additions & 0 deletions cases/networks.json

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions src/basic/newtonpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::basic::sparse::{
stack::{csc_hstack, csc_vstack},
};
use num_traits::Zero;

use nalgebra::*;
use nalgebra_sparse::*;
use num_complex::Complex64;
Expand Down Expand Up @@ -163,7 +162,7 @@ trait Slice {
fn columns(&self, start_col: usize, end_col: usize) -> Self::Mat;
}

impl<T: Clone + Zero + Scalar + ClosedAdd> Slice for CscMatrix<T> {
impl<T: Clone + Zero + Scalar + ClosedAddAssign> Slice for CscMatrix<T> {
type Mat = CscMatrix<T>;

#[inline(always)]
Expand All @@ -188,7 +187,7 @@ trait SliceTo {
fn columns_to(&self, start_col: usize, end_col: usize, mat: &mut Self::Mat);
}

impl<T: Copy + Clone + Zero + Scalar + ClosedAdd> SliceTo for CscMatrix<T> {
impl<T: Copy + Clone + Zero + Scalar + ClosedAddAssign> SliceTo for CscMatrix<T> {
type Mat = CscMatrix<T>;

#[inline(always)]
Expand Down
6 changes: 3 additions & 3 deletions src/basic/sparse/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pub fn slice_csc_matrix_to<T: Clone>(
///
/// A new CSC matrix containing the sliced block.
#[inline(always)]
pub fn slice_csc_matrix_block<T: Clone + Scalar + ClosedAdd + num_traits::Zero>(
pub fn slice_csc_matrix_block<T: Clone + Scalar + ClosedAddAssign + num_traits::Zero>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
Expand Down Expand Up @@ -128,7 +128,7 @@ pub fn slice_csc_matrix_block<T: Clone + Scalar + ClosedAdd + num_traits::Zero>(
/// * `shape` - The shape (rows, cols) of the block.
/// * `dest` - A mutable reference to the destination CSC matrix.
#[inline(always)]
pub fn slice_csc_matrix_block_to<T: Copy + Clone + Scalar + ClosedAdd + num_traits::Zero>(
pub fn slice_csc_matrix_block_to<T: Copy + Clone + Scalar + ClosedAddAssign + num_traits::Zero>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
Expand Down Expand Up @@ -166,7 +166,7 @@ pub fn slice_csc_matrix_block_to<T: Copy + Clone + Scalar + ClosedAdd + num_trai
///
/// A vector containing the indices of non-zero elements in the block.
#[inline(always)]
pub fn csc_matrix_block_nnz_indices<T: Copy + Clone + Scalar + ClosedAdd + num_traits::Zero>(
pub fn csc_matrix_block_nnz_indices<T: Copy + Clone + Scalar + ClosedAddAssign + num_traits::Zero>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
Expand Down
130 changes: 113 additions & 17 deletions src/io/pandapower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ use nalgebra::{vector, Complex};
use serde::Deserializer;
use serde::{Deserialize, Serialize};
use std::f64::consts::PI;
use std::fs::File;
use std::{fs::File, fs};
use std::{io::Read, option::Option};

use crate::basic::system::*;
use crate::prelude::admittance::*;

use serde_json;
use serde_json::{Map, Value};

/// This module is used to parse pandapower network parameters
/// Deserializes a number from JSON format.
fn from_number<'de, D>(deserializer: D) -> Result<i64, D::Error>
fn from_number<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
where
D: Deserializer<'de>,
{
let val: serde_json::Value = Deserialize::deserialize(deserializer)?;
if let serde_json::Value::Number(n) = val {
let res = n.as_f64().unwrap();
return Ok(res as i64);
return Ok(Some(res as i64));
}
Err(serde::de::Error::custom("invalid number format"))
Ok(None)
}

/// Deserializes a string from JSON format.
Expand All @@ -44,22 +47,22 @@ where
pub struct Bus {
pub index: i64,
pub in_service: bool,
pub max_vm_pu: f64,
pub min_vm_pu: f64,
pub max_vm_pu: Option<f64>,
pub min_vm_pu: Option<f64>,
#[serde(deserialize_with = "from_str")]
pub name: Option<String>,
#[serde(rename = "type")]
pub type_: Option<String>, // Added underscore to avoid conflict with Rust keyword
pub vn_kv: f64,
#[serde(deserialize_with = "from_number")]
pub zone: i64,
pub zone: Option<i64>,
}

/// Represents a generator in the network.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Gen {
pub bus: i64,
pub controllable: bool,
pub controllable: Option<bool>,
pub in_service: bool,
pub name: Option<String>,
pub p_mw: f64,
Expand All @@ -82,7 +85,7 @@ pub struct Load {
pub bus: i64,
pub const_i_percent: f64,
pub const_z_percent: f64,
pub controllable: bool,
pub controllable: Option<bool>,
pub in_service: bool,
pub name: Option<String>,
pub p_mw: f64,
Expand All @@ -104,11 +107,11 @@ pub struct Line {
pub in_service: bool,
pub length_km: f64,
pub max_i_ka: f64,
pub max_loading_percent: f64,
pub max_loading_percent: Option<f64>,
pub parallel: i32,
pub r_ohm_per_km: f64,
#[serde(rename = "type")]
pub type_: String,
pub type_: Option<String>,
pub x_ohm_per_km: f64,
pub name: Option<String>,
pub std_type: Option<String>,
Expand All @@ -122,7 +125,7 @@ pub struct Transformer {
pub i0_percent: f64,
pub in_service: bool,
pub lv_bus: i32,
pub max_loading_percent: f64,
pub max_loading_percent: Option<f64>,
pub parallel: i32,
pub pfe_kw: f64,
pub shift_degree: f64,
Expand Down Expand Up @@ -150,10 +153,10 @@ pub struct ExtGrid {
pub in_service: bool,
pub va_degree: f64,
pub vm_pu: f64,
pub max_p_mw: f64,
pub min_p_mw: f64,
pub max_q_mvar: f64,
pub min_q_mvar: f64,
pub max_p_mw: Option<f64>,
pub min_p_mw: Option<f64>,
pub max_q_mvar: Option<f64>,
pub min_q_mvar: Option<f64>,
pub slack_weight: f64,
pub name: Option<String>,
}
Expand All @@ -171,7 +174,7 @@ pub struct SGen {
#[serde(rename = "type")]
pub type_: Option<String>,
pub current_source: bool,
pub controllable: bool,
pub controllable: Option<bool>,
}

/// Represents a shunt in the network.
Expand Down Expand Up @@ -469,6 +472,88 @@ pub fn load_csv_zip(name: String) -> Result<Network, std::io::Error> {
Ok(net)
}


fn load_json_from_str(file_content: String) -> Result<Map<String, Value>, std::io::Error> {
let parsed: Value = serde_json::from_str(&file_content)?;
let obj: Map<String, Value> = parsed.as_object().unwrap().clone();
Ok(obj)
}

fn load_json(file_path: String) -> Result<Map<String, Value>, std::io::Error> {
let file_content =
fs::read_to_string(file_path).expect(format!("Error reading file network file").as_str());
let obj = load_json_from_str(file_content);
obj
}

fn load_pandapower_element_json<T: serde::de::DeserializeOwned>(
object: &Map<String, Value>,
key: String,
) -> Vec<T> {
let element = object
.get(&key)
.and_then(|v| v.as_object())
.unwrap()
.get("_object")
.and_then(|v| v.as_str())
.unwrap();

let mut elements = Vec::new();

let map = load_json_from_str(element.to_string()).unwrap();

let headers = map
.get("columns")
.and_then(|v| v.as_array())
.unwrap()
.to_owned();

let rows = map.get("data").and_then(|v| v.as_array()).unwrap();

for (index, row) in rows.iter().enumerate() {
let obj: Map<String, Value> = Map::new();
let mut obj: Map<String, Value> =
headers
.iter()
.zip(row.as_array().unwrap().iter())
.fold(obj, |mut acc, (k, v)| {
let key = k.as_str().unwrap();
let value = v.to_owned();
acc.insert(key.to_string(), value);
acc
});

obj.insert(
"index".to_string(),
Value::Number(serde_json::Number::from(index as i64)),
);

println!("key: {} Obj: {:?}", key, obj);

let elem: T = serde_json::from_value(obj.clone().into()).unwrap();
elements.push(elem);
}

return elements;
}

pub fn load_pandapower_json(file_path: String) -> Network {
let map: Map<String, Value> = load_json(file_path).unwrap();
let object: &Map<String, Value> = map.get("_object").and_then(|v| v.as_object()).unwrap();

let mut net = Network::default();
net.bus = load_pandapower_element_json(object, "bus".to_string());
net.gen = Some(load_pandapower_element_json(object, "gen".to_string()));
net.line = Some(load_pandapower_element_json(object, "line".to_string()));
net.shunt = Some(load_pandapower_element_json(object, "shunt".to_string()));
net.trafo = Some(load_pandapower_element_json(object, "trafo".to_string()));
net.ext_grid = Some(load_pandapower_element_json(object, "ext_grid".to_string()));
net.load = Some(load_pandapower_element_json(object, "load".to_string()));
net.sgen = Some(load_pandapower_element_json(object, "sgen".to_string()));

return net;
}

impl From<Network> for PFNetwork {
fn from(value: Network) -> Self {
let v_base = value.bus[value.ext_grid.as_ref().unwrap()[0].bus as usize].vn_kv;
Expand Down Expand Up @@ -513,6 +598,17 @@ impl From<Network> for PFNetwork {
mod tests {
use super::*;
use std::env;


#[test]
fn test_load_json() -> () {
let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let folder = format!("{}/cases", dir);
let filepath: String = folder.to_owned() + "/networks.json";
let net = load_pandapower_json(filepath);
println!("{:?}", net);
}

#[test]
fn test_load_csv() -> () {
let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
Expand Down

0 comments on commit fc24111

Please sign in to comment.