Adding initial Project to git
This commit is contained in:
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
# user spesific files
|
||||||
|
.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
.vscode/*
|
||||||
57
BWR.ConsoleApp/Program.cs
Normal file
57
BWR.ConsoleApp/Program.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// MyBWRSimulator.ConsoleApp/Program.cs
|
||||||
|
namespace MyBWRSimulator.ConsoleApp
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Simulation;
|
||||||
|
using MyBWRSimulator.Core.Components.Concrete; // Needed for specific component instantiation if not using config
|
||||||
|
using MyBWRSimulator.Core.Ports; // Needed for specific port instantiation if not using config
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Starting BWR Simulator Console Application...");
|
||||||
|
|
||||||
|
var simulator = new Simulator();
|
||||||
|
|
||||||
|
// Define the path to your configuration file
|
||||||
|
// Adjust this path as needed for your project structure
|
||||||
|
string configFilePath = Path.Combine(Directory.GetCurrentDirectory(), "config", "PlantConfig.json");
|
||||||
|
|
||||||
|
// Option 1: Load configuration from JSON file
|
||||||
|
//simulator.LoadPlantConfiguration(configFilePath);
|
||||||
|
|
||||||
|
// Option 2 (Alternative for testing without config file): Manually create components and connect them
|
||||||
|
|
||||||
|
var reactor = new ReactorCore("RC001", "Main Reactor Core", 4);
|
||||||
|
var pump = new Pump("PMP001", "Recirculation Pump", 100.0, 50000.0); // maxFlow, maxHeadPressure
|
||||||
|
var pipe = new Pipe("PIP001", "Hot Leg Pipe", 20.0, 0.5); // length, diameter
|
||||||
|
var tank = new FluidTank("TK001", "Condensate Tank", 500.0, 1, 1, 250.0); // maxVol, numInlets, numOutlets, initialVol
|
||||||
|
|
||||||
|
simulator.AddComponent(reactor);
|
||||||
|
simulator.AddComponent(pump);
|
||||||
|
simulator.AddComponent(pipe);
|
||||||
|
simulator.AddComponent(tank);
|
||||||
|
|
||||||
|
// Establish connections manually (example)
|
||||||
|
// Note: You'd need to access the specific ports of each component.
|
||||||
|
// This is simplified and assumes direct port access for brevity.
|
||||||
|
// In a real scenario, you'd use GetFluidPorts() etc.
|
||||||
|
// For example: pump.GetThermalPorts().First(p => p.ID.Contains("PowerIn")).Connect(powerSource.GetThermalPorts().First(p => p.ID.Contains("PowerOut")));
|
||||||
|
|
||||||
|
// Example of manual connection (requires casting and knowing port IDs)
|
||||||
|
// This is simplified and might break if port IDs change.
|
||||||
|
// The ConfigurationLoader handles this more robustly.
|
||||||
|
reactor.GetFluidPortById("FeedwaterInlet").Connect(pipe.GetFluidPortById("Inlet"));
|
||||||
|
pipe.GetFluidPortById("Outlet").Connect(pump.GetFluidPortById("Inlet"));
|
||||||
|
pump.GetFluidPortById("Outlet").Connect(tank.GetFluidPortById("Outlet")); // Tank has Inlet1, Inlet2 etc.
|
||||||
|
|
||||||
|
// Run the simulation for 60 seconds with 1-second time steps
|
||||||
|
simulator.RunSimulation(60.0, 1.0);
|
||||||
|
|
||||||
|
Console.WriteLine("\nSimulation application finished. Press any key to exit.");
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
154
BWR.core/Components/Abstract/Component.cs
Normal file
154
BWR.core/Components/Abstract/Component.cs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
namespace MyBWRSimulator.Core.Components.Abstract
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Interfaces;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq; // Needed for .ToList()
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract base class for all simulated physical components.
|
||||||
|
/// Implements ISimulatable, IFluidConnectable, and IThermalConnectable.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Component : ISimulatable, IFluidConnectable, IThermalConnectable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the component.
|
||||||
|
/// </summary>
|
||||||
|
public string ID { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Human-readable name of the component.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detailed description of the component.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An integer value indicating the order in which components should be updated.
|
||||||
|
/// Lower numbers mean higher priority (updated first).
|
||||||
|
/// </summary>
|
||||||
|
public int UpdatePriority { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the component is receiving sufficient Thermal power.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPowered { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection of fluid ports belonging to this component, accessible by their ID.
|
||||||
|
/// </summary>
|
||||||
|
protected Dictionary<string, FluidPort> FluidPorts { get; set; } = new Dictionary<string, FluidPort>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection of Thermal ports belonging to this component, accessible by their ID.
|
||||||
|
/// </summary>
|
||||||
|
protected Dictionary<string, ThermalPort> ThermalPorts { get; set; } = new Dictionary<string, ThermalPort>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for the Component base class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Unique identifier.</param>
|
||||||
|
/// <param name="name">Human-readable name.</param>
|
||||||
|
/// <param name="description">Description of the component.</param>
|
||||||
|
/// <param name="updatePriority">Priority for simulation updates.</param>
|
||||||
|
protected Component(string id, string name, string description, int updatePriority)
|
||||||
|
{
|
||||||
|
ID = id;
|
||||||
|
Name = name;
|
||||||
|
Description = description;
|
||||||
|
UpdatePriority = updatePriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the component. Called once when the simulation starts or component is added.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Initialize()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Initializing {Name} ({ID})...");
|
||||||
|
// Placeholder for component-specific initialization logic
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the component. Called once when the simulation ends or component is removed.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Shutdown()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Shutting down {Name} ({ID})...");
|
||||||
|
// Placeholder for component-specific cleanup logic
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract method to update the component's state over a time step.
|
||||||
|
/// Must be implemented by concrete component classes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime">The time elapsed.</param>
|
||||||
|
public abstract void Update(double deltaTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all fluid ports for this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of FluidPort objects.</returns>
|
||||||
|
public List<FluidPort> GetFluidPorts() => FluidPorts.Values.ToList();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a fluid port by its unique ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of the fluid port.</param>
|
||||||
|
/// <returns>The FluidPort object if found, otherwise null.</returns>
|
||||||
|
public FluidPort GetFluidPortById(string id)
|
||||||
|
{
|
||||||
|
FluidPorts.TryGetValue(id, out FluidPort port);
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all Thermal ports for this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of Thermal objects.</returns>
|
||||||
|
public List<ThermalPort> GetThermalPorts() => ThermalPorts.Values.ToList();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an Thermal port by its unique ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of the Thermal port.</param>
|
||||||
|
/// <returns>The ThermalPort object if found, otherwise null.</returns>
|
||||||
|
public ThermalPort GetThermalPortById(string id)
|
||||||
|
{
|
||||||
|
ThermalPorts.TryGetValue(id, out ThermalPort port);
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to add a fluid port to this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="port">The FluidPort to add.</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if a port with the same ID already exists.</exception>
|
||||||
|
protected void AddFluidPort(FluidPort port)
|
||||||
|
{
|
||||||
|
if (FluidPorts.ContainsKey(port.ID))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"A fluid port with ID '{port.ID}' already exists on component '{Name}' ({ID}).");
|
||||||
|
}
|
||||||
|
port.ParentComponent = this;
|
||||||
|
FluidPorts.Add(port.ID, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to add an Thermal port to this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="port">The ThermalPort to add.</param>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if an Thermal port with the same ID already exists.</exception>
|
||||||
|
protected void AddThermalPort(ThermalPort port)
|
||||||
|
{
|
||||||
|
if (ThermalPorts.ContainsKey(port.ID))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"An Thermal port with ID '{port.ID}' already exists on component '{Name}' ({ID}).");
|
||||||
|
}
|
||||||
|
port.ParentComponent = this;
|
||||||
|
ThermalPorts.Add(port.ID, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
BWR.core/Components/Abstract/Port.cs
Normal file
77
BWR.core/Components/Abstract/Port.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Abstract/Port.cs
|
||||||
|
namespace MyBWRSimulator.Core.Components.Abstract
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract base class for all types of connection points on components.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Port
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique ID for the port (e.g., "Inlet1", "OutletA").
|
||||||
|
/// </summary>
|
||||||
|
public string ID { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the Port it's connected to. Null if not connected.
|
||||||
|
/// </summary>
|
||||||
|
public Port ConnectedPort { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference back to the component this port belongs to.
|
||||||
|
/// </summary>
|
||||||
|
public Component ParentComponent { get; internal set; } // Internal set by AddPort methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for the Port base class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Unique identifier for the port.</param>
|
||||||
|
protected Port(string id)
|
||||||
|
{
|
||||||
|
ID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Establishes a connection between this port and another port.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="otherPort">The port to connect to.</param>
|
||||||
|
public virtual void Connect(Port otherPort)
|
||||||
|
{
|
||||||
|
if (otherPort == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: Cannot connect {ID} to null port.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ConnectedPort != null && ConnectedPort != otherPort)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Warning: {ID} is already connected to {ConnectedPort.ID}. Disconnecting first.");
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectedPort = otherPort;
|
||||||
|
// For bidirectional connection, the other port should also connect to this one
|
||||||
|
if (otherPort.ConnectedPort != this)
|
||||||
|
{
|
||||||
|
otherPort.Connect(this);
|
||||||
|
}
|
||||||
|
Console.WriteLine($"Port {ID} connected to {otherPort.ID}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Breaks the connection of this port.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Disconnect()
|
||||||
|
{
|
||||||
|
if (ConnectedPort != null)
|
||||||
|
{
|
||||||
|
Port oldConnectedPort = ConnectedPort;
|
||||||
|
ConnectedPort = null;
|
||||||
|
// Ensure the other port also disconnects from this one
|
||||||
|
if (oldConnectedPort.ConnectedPort == this)
|
||||||
|
{
|
||||||
|
oldConnectedPort.Disconnect();
|
||||||
|
}
|
||||||
|
Console.WriteLine($"Port {ID} disconnected from {oldConnectedPort.ID}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
BWR.core/Components/Concrete/FluidTank.cs
Normal file
67
BWR.core/Components/Concrete/FluidTank.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Concrete/FluidTank.cs
|
||||||
|
namespace MyBWRSimulator.Core.Components.Concrete
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
//using MyBWRSimulator.Core.Components.Enums;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a Fluid Tank component in the BWR simulation.
|
||||||
|
/// </summary>
|
||||||
|
public class FluidTank : Component
|
||||||
|
{
|
||||||
|
public double MaxVolume { get; private set; } // Maximum capacity of the tank (m^3)
|
||||||
|
public double CurrentVolume { get; private set; } // Current fluid volume in the tank (m^3)
|
||||||
|
public double CurrentLevel => CurrentVolume / MaxVolume; // 0.0 to 1.0 (0% to 100%)
|
||||||
|
public double ContentsTemperature { get; private set; } // Average temperature of fluid in tank
|
||||||
|
|
||||||
|
public FluidPort Inlet => GetFluidPortById("Inlet");
|
||||||
|
public FluidPort Outlet => GetFluidPortById("Outlet");
|
||||||
|
|
||||||
|
public FluidTank(string id, string name, double maxVolume, int numInlets, int numOutlets, double initialVolume = 0.0, double initialTemp = 293.15)
|
||||||
|
: base(id, name, $"A fluid tank with max volume {maxVolume} m^3.", 5) // Priority 5 (updates last)
|
||||||
|
{
|
||||||
|
MaxVolume = maxVolume;
|
||||||
|
CurrentVolume = Math.Clamp(initialVolume, 0.0, MaxVolume);
|
||||||
|
ContentsTemperature = initialTemp;
|
||||||
|
|
||||||
|
|
||||||
|
AddFluidPort(new FluidPort("Inlet"));
|
||||||
|
AddFluidPort(new FluidPort("Outlet"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
double FlowVolume = 0.0;
|
||||||
|
double InletEnergy = 0.0; // For temperature calculation
|
||||||
|
|
||||||
|
FlowVolume += Inlet.FlowRate * deltaTime; // FlowRate is volume/time, so FlowRate * deltaTime = volume
|
||||||
|
InletEnergy += Inlet.FlowRate * Inlet.Temperature * deltaTime; // Simple energy balance
|
||||||
|
|
||||||
|
// Sum outgoing flow (assuming outlets draw based on their connected components)
|
||||||
|
// For a tank, outlets typically "demand" flow, and the tank supplies it if available.
|
||||||
|
// For simplicity here, we'll assume outlets simply remove fluid.
|
||||||
|
// In a real system, outlet flow depends on downstream pressure and tank level.
|
||||||
|
FlowVolume -= Outlet.FlowRate * deltaTime;
|
||||||
|
|
||||||
|
|
||||||
|
// Update volume
|
||||||
|
double newVolume = CurrentVolume + FlowVolume;
|
||||||
|
CurrentVolume = Math.Clamp(newVolume, 0.0, MaxVolume);
|
||||||
|
|
||||||
|
// Update outlet port properties (e.g., pressure based on level)
|
||||||
|
// This is a simplification; in reality, outlet pressure also depends on downstream pressure
|
||||||
|
double pressureFromLevel = CurrentLevel * 100000; // Example: 100kPa at full level
|
||||||
|
|
||||||
|
Outlet.Pressure = pressureFromLevel; // Or a more complex calculation
|
||||||
|
Outlet.Temperature = ContentsTemperature;
|
||||||
|
// Mirror values to connected ports
|
||||||
|
Outlet.MirrorToConnectedPort();
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine($"{Name} ({ID}) - Volume: {CurrentVolume:F2} m^3 ({CurrentLevel * 100:F1}%), Temp: {ContentsTemperature:F1} K");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
BWR.core/Components/Concrete/PressureVessel.cs
Normal file
0
BWR.core/Components/Concrete/PressureVessel.cs
Normal file
74
BWR.core/Components/Concrete/Pump.cs
Normal file
74
BWR.core/Components/Concrete/Pump.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Concrete/Pump.cs
|
||||||
|
namespace MyBWRSimulator.Core.Components.Concrete
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a Pump component in the BWR simulation.
|
||||||
|
/// </summary>
|
||||||
|
public class Pump : Component
|
||||||
|
{
|
||||||
|
public double PumpSpeed { get; set; } // 0.0 to 1.0 (0% to 100%)
|
||||||
|
public double MaxFlowRate { get; private set; } // Max flow at 100% speed
|
||||||
|
public double MaxHeadPressure { get; private set; } // Max pressure at 100% speed
|
||||||
|
|
||||||
|
// Publicly expose ports for easier named access if needed, but GetFluidPortById is preferred
|
||||||
|
public FluidPort Inlet => GetFluidPortById("Inlet");
|
||||||
|
public FluidPort Outlet => GetFluidPortById("Outlet");
|
||||||
|
|
||||||
|
|
||||||
|
public Pump(string id, string name, double maxFlowRate, double maxHeadPressure)
|
||||||
|
: base(id, name, $"A pump component with max flow {maxFlowRate} and max head {maxHeadPressure}.", 1) // Priority 1
|
||||||
|
{
|
||||||
|
MaxFlowRate = maxFlowRate;
|
||||||
|
MaxHeadPressure = maxHeadPressure;
|
||||||
|
PumpSpeed = 0.0; // Initially off
|
||||||
|
|
||||||
|
// Use descriptive IDs for ports
|
||||||
|
AddFluidPort(new FluidPort("Inlet"));
|
||||||
|
AddFluidPort(new FluidPort("Outlet"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
if (PumpSpeed > 0)
|
||||||
|
{
|
||||||
|
// Simple pump model: Flow proportional to speed, pressure based on head
|
||||||
|
double actualFlowRate = PumpSpeed * MaxFlowRate;
|
||||||
|
double actualPressureIncrease = PumpSpeed * MaxHeadPressure;
|
||||||
|
|
||||||
|
// Read from inlet
|
||||||
|
double inletPressure = Inlet.Pressure;
|
||||||
|
double inletTemperature = Inlet.Temperature;
|
||||||
|
|
||||||
|
// Calculate outlet properties
|
||||||
|
Outlet.FlowRate = actualFlowRate;
|
||||||
|
Outlet.Pressure = inletPressure + actualPressureIncrease;
|
||||||
|
Outlet.Temperature = inletTemperature; // Assuming no temperature change by pump
|
||||||
|
|
||||||
|
// Mirror values to connected ports
|
||||||
|
Outlet.MirrorToConnectedPort();
|
||||||
|
|
||||||
|
Console.WriteLine($"{Name} ({ID}) - Flow: {actualFlowRate:F2} kg/s, Outlet P: {Outlet.Pressure:F2} Pa");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If not powered or off, no flow
|
||||||
|
Outlet.FlowRate = 0.0;
|
||||||
|
Outlet.Pressure = Inlet.Pressure; // Outlet pressure equals inlet if no pumping
|
||||||
|
Outlet.Temperature = Inlet.Temperature;
|
||||||
|
Outlet.MirrorToConnectedPort();
|
||||||
|
Console.WriteLine($"{Name} ({ID}) - Off/No Power.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPumpSpeed(double speed)
|
||||||
|
{
|
||||||
|
PumpSpeed = Math.Clamp(speed, 0.0, 1.0);
|
||||||
|
Console.WriteLine($"{Name} ({ID}) - Pump speed set to {PumpSpeed * 100:F0}%.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
BWR.core/Components/Concrete/ReactorCore.cs
Normal file
25
BWR.core/Components/Concrete/ReactorCore.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Concrete/Pump.cs
|
||||||
|
namespace MyBWRSimulator.Core.Components.Concrete
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
//using MyBWRSimulator.Core.Components.Enums;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a Pump component in the BWR simulation.
|
||||||
|
/// </summary>
|
||||||
|
public class ReactorCore : Component
|
||||||
|
{
|
||||||
|
public ReactorCore(string id, string name, int priority)
|
||||||
|
: base(id, name, "Simulates all fuel rods and control rods", priority)
|
||||||
|
{
|
||||||
|
AddFluidPort(new FluidPort("FeedwaterInlet"));
|
||||||
|
}
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
BWR.core/Components/Concrete/pipe.cs
Normal file
63
BWR.core/Components/Concrete/pipe.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Concrete/Pipe.cs
|
||||||
|
namespace MyBWRSimulator.Core.Components.Concrete
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a Pipe component in the BWR simulation.
|
||||||
|
/// </summary>
|
||||||
|
public class Pipe : Component
|
||||||
|
{
|
||||||
|
public double Length { get; private set; } // Length of the pipe (m)
|
||||||
|
public double Diameter { get; private set; } // Inner diameter of the pipe (m)
|
||||||
|
public double Roughness { get; private set; } = 0.000045; // Example roughness for steel (m)
|
||||||
|
|
||||||
|
// Publicly expose ports for easier named access if needed
|
||||||
|
public FluidPort Inlet => GetFluidPortById("Inlet");
|
||||||
|
public FluidPort Outlet => GetFluidPortById("Outlet");
|
||||||
|
|
||||||
|
public Pipe(string id, string name, double length, double diameter)
|
||||||
|
: base(id, name, $"A pipe of length {length}m and diameter {diameter}m.", 4) // Priority 4
|
||||||
|
{
|
||||||
|
Length = length;
|
||||||
|
Diameter = diameter;
|
||||||
|
|
||||||
|
// Use descriptive IDs for ports
|
||||||
|
AddFluidPort(new FluidPort("Inlet"));
|
||||||
|
AddFluidPort(new FluidPort("Outlet"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
// Read properties from the inlet port (which should have been updated by upstream component)
|
||||||
|
double inletFlowRate = Inlet.FlowRate;
|
||||||
|
double inletPressure = Inlet.Pressure;
|
||||||
|
double inletTemperature = Inlet.Temperature;
|
||||||
|
|
||||||
|
// Simple pressure drop calculation (e.g., Darcy-Weisbach or simpler linear drop)
|
||||||
|
// This is very simplified. For high fidelity, you'd need fluid properties (density, viscosity).
|
||||||
|
double pressureDrop = 0.0;
|
||||||
|
if (inletFlowRate > 0)
|
||||||
|
{
|
||||||
|
// A very basic linear pressure drop for demonstration
|
||||||
|
pressureDrop = (inletFlowRate * Length * 10.0) / (Diameter * Diameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple heat loss/gain (e.g., based on ambient temperature, not modeled here)
|
||||||
|
double outletTemperature = inletTemperature; // Assuming no heat loss for now
|
||||||
|
|
||||||
|
// Update outlet port properties
|
||||||
|
Outlet.FlowRate = inletFlowRate;
|
||||||
|
Outlet.Pressure = inletPressure - pressureDrop;
|
||||||
|
Outlet.Temperature = outletTemperature;
|
||||||
|
|
||||||
|
// Mirror values to connected ports
|
||||||
|
Outlet.MirrorToConnectedPort();
|
||||||
|
|
||||||
|
Console.WriteLine($"{Name} ({ID}) - Flow: {inletFlowRate:F2} kg/s, Pressure Drop: {pressureDrop:F2} Pa");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
BWR.core/Components/Enums/FluidPortType.cs
Normal file
14
BWR.core/Components/Enums/FluidPortType.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// MyBWRSimulator.Core/Components/Enums/FluidPortType.cs
|
||||||
|
/*
|
||||||
|
namespace MyBWRSimulator.Core.Components.Enums
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the type of a fluid port (e.g., inlet or outlet).
|
||||||
|
/// </summary>
|
||||||
|
public enum FluidPortType
|
||||||
|
{
|
||||||
|
Inlet,
|
||||||
|
Outlet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
167
BWR.core/Data/ConfigurationLoader.cs
Normal file
167
BWR.core/Data/ConfigurationLoader.cs
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
// MyBWRSimulator.Core/Data/ConfigurationLoader.cs
|
||||||
|
namespace MyBWRSimulator.Core.Data
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
using MyBWRSimulator.Core.Components.Concrete;
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for deserializing component and connection configurations.
|
||||||
|
/// </summary>
|
||||||
|
public class ComponentConfig
|
||||||
|
{
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string ID { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int UpdatePriority { get; set; }
|
||||||
|
public JsonElement InitialState { get; set; } // Use JsonElement to handle dynamic properties
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for deserializing connection configurations.
|
||||||
|
/// </summary>
|
||||||
|
public class PortReference
|
||||||
|
{
|
||||||
|
public string ComponentID { get; set; }
|
||||||
|
public string PortID { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overall configuration structure.
|
||||||
|
/// </summary>
|
||||||
|
public class PlantConfiguration
|
||||||
|
{
|
||||||
|
public List<ComponentConfig> Components { get; set; }
|
||||||
|
public List<ConnectionConfig> Connections { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for deserializing connection configurations.
|
||||||
|
/// </summary>
|
||||||
|
public class ConnectionConfig
|
||||||
|
{
|
||||||
|
public PortReference PortA { get; set; }
|
||||||
|
public PortReference PortB { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles loading simulation configuration from a JSON file.
|
||||||
|
/// </summary>
|
||||||
|
public class ConfigurationLoader
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Loads components and establishes connections from a JSON configuration file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">The path to the JSON configuration file.</param>
|
||||||
|
/// <param name="components">An output list to populate with instantiated components.</param>
|
||||||
|
public static void LoadConfiguration(string filePath, out List<Component> components)
|
||||||
|
{
|
||||||
|
components = new List<Component>();
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: Configuration file not found at {filePath}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string jsonString = File.ReadAllText(filePath);
|
||||||
|
var config = JsonSerializer.Deserialize<PlantConfiguration>(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||||
|
|
||||||
|
if (config?.Components == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: No components found in configuration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Instantiate Components
|
||||||
|
foreach (var compConfig in config.Components)
|
||||||
|
{
|
||||||
|
Component newComponent = null;
|
||||||
|
switch (compConfig.Type)
|
||||||
|
{
|
||||||
|
case "Pump":
|
||||||
|
// Example: Deserialize specific properties for Pump
|
||||||
|
var pumpProps = compConfig.InitialState.Deserialize<Dictionary<string, double>>();
|
||||||
|
newComponent = new Pump(compConfig.ID, compConfig.Name, pumpProps["MaxFlowRate"], pumpProps["MaxHeadPressure"]);
|
||||||
|
if (pumpProps.TryGetValue("PumpSpeed", out double pumpSpeed))
|
||||||
|
{
|
||||||
|
((Pump)newComponent).SetPumpSpeed(pumpSpeed);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "FluidTank":
|
||||||
|
// Example: Deserialize specific properties for FluidTank
|
||||||
|
var tankProps = compConfig.InitialState.Deserialize<Dictionary<string, double>>();
|
||||||
|
newComponent = new FluidTank(compConfig.ID, compConfig.Name, tankProps["MaxVolume"], (int)tankProps["NumInlets"], (int)tankProps["NumOutlets"], tankProps["InitialVolume"]);
|
||||||
|
break;
|
||||||
|
case "Pipe":
|
||||||
|
var pipeProps = compConfig.InitialState.Deserialize<Dictionary<string, double>>();
|
||||||
|
newComponent = new Pipe(compConfig.ID, compConfig.Name, pipeProps["Length"], pipeProps["Diameter"]);
|
||||||
|
break;
|
||||||
|
case "ReactorCore":
|
||||||
|
newComponent = new ReactorCore(compConfig.ID, compConfig.Name, compConfig.UpdatePriority);
|
||||||
|
// ReactorCore might have no specific initial state beyond base properties
|
||||||
|
break;
|
||||||
|
// Add more component types here
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"Warning: Unknown component type '{compConfig.Type}' for ID '{compConfig.ID}'. Skipping.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newComponent != null)
|
||||||
|
{
|
||||||
|
components.Add(newComponent);
|
||||||
|
newComponent.Initialize(); // Initialize after creation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Establish Connections
|
||||||
|
if (config.Connections != null)
|
||||||
|
{
|
||||||
|
foreach (var connConfig in config.Connections)
|
||||||
|
{
|
||||||
|
var compA = components.FirstOrDefault(c => c.ID == connConfig.PortA.ComponentID);
|
||||||
|
var compB = components.FirstOrDefault(c => c.ID == connConfig.PortB.ComponentID);
|
||||||
|
|
||||||
|
if (compA == null || compB == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Warning: Could not find one or both components for connection: {connConfig.PortA.ComponentID}.{connConfig.PortA.PortID} <-> {connConfig.PortB.ComponentID}.{connConfig.PortB.PortID}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the new GetPortById methods for more robust lookup
|
||||||
|
Port portA = compA.GetFluidPortById(connConfig.PortA.PortID) as Port ??
|
||||||
|
compA.GetThermalPortById(connConfig.PortA.PortID) as Port;
|
||||||
|
|
||||||
|
Port portB = compB.GetFluidPortById(connConfig.PortB.PortID) as Port ??
|
||||||
|
compB.GetThermalPortById(connConfig.PortB.PortID) as Port;
|
||||||
|
|
||||||
|
if (portA != null && portB != null)
|
||||||
|
{
|
||||||
|
portA.Connect(portB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Warning: Could not find one or both ports for connection: {connConfig.PortA.ComponentID}.{connConfig.PortA.PortID} <-> {connConfig.PortB.ComponentID}.{connConfig.PortB.PortID}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error parsing JSON configuration: {ex.Message}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"An unexpected error occurred during configuration loading: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
BWR.core/Interfaces/IFluidConnectable.cs
Normal file
18
BWR.core/Interfaces/IFluidConnectable.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// MyBWRSimulator.Core/Interfaces/IFluidConnectable.cs
|
||||||
|
namespace MyBWRSimulator.Core.Interfaces
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for components that have fluid connections.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFluidConnectable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of fluid ports associated with this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of FluidPort objects.</returns>
|
||||||
|
List<FluidPort> GetFluidPorts();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
BWR.core/Interfaces/ISimulatable.cs
Normal file
15
BWR.core/Interfaces/ISimulatable.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// MyBWRSimulator.Core/Interfaces/ISimulatable.cs
|
||||||
|
namespace MyBWRSimulator.Core.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for any object that can participate in the simulation's time-stepping.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISimulatable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the state of the object over a given time step.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime">The time elapsed since the last update.</param>
|
||||||
|
void Update(double deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
BWR.core/Interfaces/IThermalConnectable.cs
Normal file
18
BWR.core/Interfaces/IThermalConnectable.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// MyBWRSimulator.Core/Interfaces/IThermalConnectable.cs
|
||||||
|
namespace MyBWRSimulator.Core.Interfaces
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Ports;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for components that have Thermal connections.
|
||||||
|
/// </summary>
|
||||||
|
public interface IThermalConnectable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of Thermal ports associated with this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of ThermalPort objects.</returns>
|
||||||
|
List<ThermalPort> GetThermalPorts();
|
||||||
|
}
|
||||||
|
}
|
||||||
71
BWR.core/Ports/FluidPort.cs
Normal file
71
BWR.core/Ports/FluidPort.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// MyBWRSimulator.Core/Ports/FluidPort.cs
|
||||||
|
namespace MyBWRSimulator.Core.Ports
|
||||||
|
{
|
||||||
|
//using MyBWRSimulator.Core.Components.Enums;
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a fluid connection point on a component.
|
||||||
|
/// </summary>
|
||||||
|
public class FluidPort : Port
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current fluid flow rate through this port (e.g., kg/s).
|
||||||
|
/// </summary>
|
||||||
|
public double FlowRate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current fluid pressure at this port (e.g., Pa).
|
||||||
|
/// </summary>
|
||||||
|
public double Pressure { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current fluid temperature at this port (e.g., K or C).
|
||||||
|
/// </summary>
|
||||||
|
public double Temperature { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current volume of fluid within the port itself (optional, for more detailed modeling).
|
||||||
|
/// </summary>
|
||||||
|
public double CurrentVolume { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for a FluidPort.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Unique identifier for the port.</param>
|
||||||
|
/// <param name="type">The type of fluid port (Inlet or Outlet).</param>
|
||||||
|
public FluidPort(string id) : base(id)
|
||||||
|
{
|
||||||
|
FlowRate = 0.0;
|
||||||
|
Pressure = 0.0;
|
||||||
|
Temperature = 0.0;
|
||||||
|
CurrentVolume = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connects this fluid port to another fluid port.
|
||||||
|
/// Includes basic type checking.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="otherPort">The port to connect to.</param>
|
||||||
|
public override void Connect(Port otherPort)
|
||||||
|
{
|
||||||
|
base.Connect(otherPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors fluid properties from this port to its connected port.
|
||||||
|
/// This is for the direct property assignment data flow model.
|
||||||
|
/// </summary>
|
||||||
|
public void MirrorToConnectedPort()
|
||||||
|
{
|
||||||
|
if (ConnectedPort is FluidPort connectedFluidPort)
|
||||||
|
{
|
||||||
|
connectedFluidPort.FlowRate = this.FlowRate;
|
||||||
|
connectedFluidPort.Pressure = this.Pressure;
|
||||||
|
connectedFluidPort.Temperature = this.Temperature;
|
||||||
|
// Optionally, mirror CurrentVolume if applicable
|
||||||
|
// connectedFluidPort.CurrentVolume = this.CurrentVolume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
BWR.core/Ports/ThermalPort.cs
Normal file
68
BWR.core/Ports/ThermalPort.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// MyBWRSimulator.Core/Ports/ThermalPort.cs
|
||||||
|
namespace MyBWRSimulator.Core.Ports
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an Thermal connection point on a component.
|
||||||
|
/// </summary>
|
||||||
|
public class ThermalPort : Port
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current voltage at this port (e.g., Volts).
|
||||||
|
/// </summary>
|
||||||
|
public double Voltage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current amperage at this port (e.g., Amperes).
|
||||||
|
/// </summary>
|
||||||
|
public double Amperage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if this port is actively supplying power.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSupplyingPower { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for an ThermalPort.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Unique identifier for the port.</param>
|
||||||
|
public ThermalPort(string id) : base(id)
|
||||||
|
{
|
||||||
|
Voltage = 0.0;
|
||||||
|
Amperage = 0.0;
|
||||||
|
IsSupplyingPower = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connects this Thermal port to another Thermal port.
|
||||||
|
/// Includes basic type checking.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="otherPort">The port to connect to.</param>
|
||||||
|
public override void Connect(Port otherPort)
|
||||||
|
{
|
||||||
|
if (otherPort is ThermalPort)
|
||||||
|
{
|
||||||
|
base.Connect(otherPort);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: Cannot connect ThermalPort {ID} to non-ThermalPort {otherPort.ID}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors Thermal properties from this port to its connected port.
|
||||||
|
/// This is for the direct property assignment data flow model.
|
||||||
|
/// </summary>
|
||||||
|
public void MirrorToConnectedPort()
|
||||||
|
{
|
||||||
|
if (ConnectedPort is ThermalPort connectedThermalPort)
|
||||||
|
{
|
||||||
|
connectedThermalPort.Voltage = this.Voltage;
|
||||||
|
connectedThermalPort.Amperage = this.Amperage;
|
||||||
|
connectedThermalPort.IsSupplyingPower = this.IsSupplyingPower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
141
BWR.core/Simulator.cs
Normal file
141
BWR.core/Simulator.cs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
// MyBWRSimulator.Core/Simulation/Simulator.cs
|
||||||
|
namespace MyBWRSimulator.Core.Simulation
|
||||||
|
{
|
||||||
|
using MyBWRSimulator.Core.Components.Abstract;
|
||||||
|
using MyBWRSimulator.Core.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The orchestrator of the simulation. Manages components, runs the simulation loop, and provides data.
|
||||||
|
/// </summary>
|
||||||
|
public class Simulator
|
||||||
|
{
|
||||||
|
private List<Component> _components;
|
||||||
|
private double _simulationTime;
|
||||||
|
private bool _isPaused;
|
||||||
|
|
||||||
|
public Simulator()
|
||||||
|
{
|
||||||
|
_components = new List<Component>();
|
||||||
|
_simulationTime = 0.0;
|
||||||
|
_isPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a component to the simulation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="component">The component to add.</param>
|
||||||
|
public void AddComponent(Component component)
|
||||||
|
{
|
||||||
|
if (component != null && !_components.Contains(component))
|
||||||
|
{
|
||||||
|
_components.Add(component);
|
||||||
|
_components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Re-sort after adding
|
||||||
|
component.Initialize();
|
||||||
|
Console.WriteLine($"Component '{component.Name}' ({component.ID}) added.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a component from the simulation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="component">The component to remove.</param>
|
||||||
|
public void RemoveComponent(Component component)
|
||||||
|
{
|
||||||
|
if (component != null && _components.Remove(component))
|
||||||
|
{
|
||||||
|
_components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Re-sort after removing
|
||||||
|
component.Shutdown();
|
||||||
|
Console.WriteLine($"Component '{component.Name}' ({component.ID}) removed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads components and connections from a configuration file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">The path to the configuration JSON file.</param>
|
||||||
|
public void LoadPlantConfiguration(string filePath)
|
||||||
|
{
|
||||||
|
ConfigurationLoader.LoadConfiguration(filePath, out _components);
|
||||||
|
_components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Ensure sorted after load
|
||||||
|
Console.WriteLine($"Loaded { _components.Count} components from configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the simulation for a specified duration with a given time step.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="duration">Total simulation duration (e.g., in seconds).</param>
|
||||||
|
/// <param name="timeStep">Time step for each update iteration (e.g., in seconds).</param>
|
||||||
|
public void RunSimulation(double duration, double timeStep)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Starting simulation for {duration} seconds with a time step of {timeStep} seconds...");
|
||||||
|
_isPaused = false;
|
||||||
|
|
||||||
|
while (_simulationTime < duration && !_isPaused)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n--- Simulation Time: {_simulationTime:F2} s ---");
|
||||||
|
foreach (var component in _components)
|
||||||
|
{
|
||||||
|
component.Update(timeStep);
|
||||||
|
}
|
||||||
|
_simulationTime += timeStep;
|
||||||
|
|
||||||
|
// For console output, add a small delay to see updates
|
||||||
|
System.Threading.Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_simulationTime >= duration)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nSimulation finished.");
|
||||||
|
}
|
||||||
|
else if (_isPaused)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nSimulation paused.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call shutdown for all components at the end of the simulation
|
||||||
|
foreach (var component in _components)
|
||||||
|
{
|
||||||
|
component.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pauses the simulation.
|
||||||
|
/// </summary>
|
||||||
|
public void PauseSimulation()
|
||||||
|
{
|
||||||
|
_isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resumes the simulation.
|
||||||
|
/// </summary>
|
||||||
|
public void ResumeSimulation()
|
||||||
|
{
|
||||||
|
_isPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets current simulation data from all components.
|
||||||
|
/// (Placeholder - you'll define the structure of this data more concretely later)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A dictionary containing simulation data.</returns>
|
||||||
|
public Dictionary<string, object> GetSimulationData()
|
||||||
|
{
|
||||||
|
var data = new Dictionary<string, object>();
|
||||||
|
data["SimulationTime"] = _simulationTime;
|
||||||
|
data["ComponentStates"] = _components.Select(c => new
|
||||||
|
{
|
||||||
|
c.ID,
|
||||||
|
c.Name
|
||||||
|
// Add specific properties for each component type here
|
||||||
|
// Example for Pump: (c as Pump)?.PumpSpeed
|
||||||
|
// Example for FluidTank: (c as FluidTank)?.CurrentVolume
|
||||||
|
}).ToList();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
BWR.core/Utilities/Constants.cs
Normal file
0
BWR.core/Utilities/Constants.cs
Normal file
9
BWR_rewrite.csproj
Normal file
9
BWR_rewrite.csproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
24
BWR_rewrite.sln
Normal file
24
BWR_rewrite.sln
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BWR_rewrite", "BWR_rewrite.csproj", "{06A4A2A6-D413-5904-24B0-D5788442CB13}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{06A4A2A6-D413-5904-24B0-D5788442CB13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{06A4A2A6-D413-5904-24B0-D5788442CB13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{06A4A2A6-D413-5904-24B0-D5788442CB13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{06A4A2A6-D413-5904-24B0-D5788442CB13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {504A20E3-1BAE-41B3-AC23-5F6EC8680BB7}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
27
Other.cs
Normal file
27
Other.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BWR_simulator
|
||||||
|
{
|
||||||
|
class PlantMngr
|
||||||
|
{
|
||||||
|
// simulation step all plant components
|
||||||
|
public void StepAll()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayStats()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Constants
|
||||||
|
{
|
||||||
|
public const double WATER_MOLAR_MASS = 0.018015; // kg/mol
|
||||||
|
public const double IDEAL_GAS_CONSTANT = 9425;
|
||||||
|
public const double WATER_LATENT_HEAT = 406500; // j*kg/k
|
||||||
|
public const double WATER_BOILING_POINT_NORM = 373; // temp in K the fluid boils at, under 1 atm
|
||||||
|
public const double WATER_HEAT_CAPACITY = 4182; // J/kg*K
|
||||||
|
}
|
||||||
|
}
|
||||||
97
PressureVessel.cs
Normal file
97
PressureVessel.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BWR_simulator
|
||||||
|
{
|
||||||
|
public class PressureVessel
|
||||||
|
{
|
||||||
|
public readonly double TOTAL_VOLUME; // Liters
|
||||||
|
private const double VESSEL_COOLING_COEFF = 1000;
|
||||||
|
private const double ROD_HEATING_COEFF = 2000;
|
||||||
|
|
||||||
|
// fluid density coeffcients to calculate fluid density at different pressures and temps
|
||||||
|
private readonly double[] FDC =
|
||||||
|
[
|
||||||
|
999.83311,
|
||||||
|
0.0752,
|
||||||
|
0.0089,
|
||||||
|
7.36413e-5,
|
||||||
|
4.74639e-7,
|
||||||
|
1.34888e-9,
|
||||||
|
1.36e-11
|
||||||
|
];
|
||||||
|
public double HotwellTemp { get; private set; }
|
||||||
|
|
||||||
|
public double GasMass { get; private set; }
|
||||||
|
public double GasVolume { get; private set; }
|
||||||
|
public double GasDensity { get; private set; }
|
||||||
|
public double Pressure { get; private set; }
|
||||||
|
|
||||||
|
public double FluidMass { get; private set; }
|
||||||
|
public double FluidDensity { get; private set; }
|
||||||
|
public double FluidVolume { get; private set; }
|
||||||
|
public double FluidTemp { get; private set; }
|
||||||
|
public double FluidBoilingPoint { get; private set; }
|
||||||
|
|
||||||
|
public double FeedwaterFlow { get; private set; }
|
||||||
|
public double ReliefValvePos { get; private set; }
|
||||||
|
public double InputEnergy { get; private set; }
|
||||||
|
|
||||||
|
public PressureVessel(double totalVolume = 9500,
|
||||||
|
double fluidTemp = 300,
|
||||||
|
double fluidMass = 6200,
|
||||||
|
double gasMass = 0)
|
||||||
|
{
|
||||||
|
TOTAL_VOLUME = totalVolume;
|
||||||
|
FluidTemp = fluidTemp;
|
||||||
|
FluidMass = fluidMass;
|
||||||
|
GasMass = gasMass;
|
||||||
|
|
||||||
|
InputEnergy = 0;
|
||||||
|
ReliefValvePos = 0;
|
||||||
|
FeedwaterFlow = 0;
|
||||||
|
Pressure = 1; // calcualte initial pressure
|
||||||
|
FluidBoilingPoint = Constants.WATER_BOILING_POINT_NORM; // calculate boiling point givien initial pressure
|
||||||
|
FluidDensity = 1;
|
||||||
|
|
||||||
|
HotwellTemp = 300;
|
||||||
|
CalculateDensity();
|
||||||
|
|
||||||
|
}
|
||||||
|
private void CalculateDensity()
|
||||||
|
{
|
||||||
|
FluidVolume = FluidMass / FluidDensity;
|
||||||
|
GasVolume = TOTAL_VOLUME - FluidVolume;
|
||||||
|
GasDensity = GasMass / GasVolume;
|
||||||
|
}
|
||||||
|
private void CalculateEnergyInput(double dt)
|
||||||
|
{
|
||||||
|
InputEnergy -= VESSEL_COOLING_COEFF * (HotwellTemp - FluidTemp) * dt;
|
||||||
|
InputEnergy += ROD_HEATING_COEFF * (600 - FluidTemp) * dt;
|
||||||
|
InputEnergy /= 1e6;
|
||||||
|
}
|
||||||
|
public void Step(double dt)
|
||||||
|
{
|
||||||
|
CalculateEnergyInput(dt);
|
||||||
|
FluidVolume += FeedwaterFlow * dt;
|
||||||
|
FluidBoilingPoint = Math.Pow((1/Constants.WATER_BOILING_POINT_NORM - (8.314 * Math.Log(Pressure))/40700), -1);
|
||||||
|
|
||||||
|
FluidTemp += (InputEnergy * 1e6) / (FluidMass * Constants.WATER_HEAT_CAPACITY);
|
||||||
|
if (FluidTemp > FluidBoilingPoint)
|
||||||
|
{
|
||||||
|
InputEnergy = FluidMass * Constants.WATER_HEAT_CAPACITY * FluidTemp - FluidBoilingPoint;
|
||||||
|
FluidTemp = FluidBoilingPoint;
|
||||||
|
double d_vapour = InputEnergy / Constants.WATER_LATENT_HEAT;
|
||||||
|
FluidMass -= d_vapour;
|
||||||
|
GasMass += d_vapour;
|
||||||
|
|
||||||
|
CalculateDensity();
|
||||||
|
}
|
||||||
|
|
||||||
|
Pressure = 1 + ((GasMass/Constants.WATER_MOLAR_MASS) * (Constants.IDEAL_GAS_CONSTANT * FluidTemp / TOTAL_VOLUME - FluidVolume));
|
||||||
|
if (Pressure < 1) {Pressure = 1;}
|
||||||
|
|
||||||
|
GasMass -= (Pressure - 1) * ReliefValvePos * dt;
|
||||||
|
if (GasMass < 0) {GasMass = 0;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Program.cs
Normal file
22
Program.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BWR_simulator;
|
||||||
|
|
||||||
|
namespace BWR_siumulator
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
PressureVessel p1 = new();
|
||||||
|
|
||||||
|
for(int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Fluid Temp: {Math.Round(p1.FluidTemp - 273, 1)}");
|
||||||
|
p1.Step(0.01);
|
||||||
|
System.Threading.Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
162
Reactor.cs
Normal file
162
Reactor.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
namespace BWR_siumulator
|
||||||
|
{
|
||||||
|
public class ThermalPort
|
||||||
|
{
|
||||||
|
public double Measurement { get; set; }
|
||||||
|
public double ValueToAffect { get; set; }
|
||||||
|
|
||||||
|
public ThermalPort(double measurement, double valueToAffect)
|
||||||
|
{
|
||||||
|
Measurement = measurement;
|
||||||
|
ValueToAffect = valueToAffect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Reactor
|
||||||
|
{
|
||||||
|
// --- Core Physics and Material Constants ---
|
||||||
|
public const double CONTROL_ROD_SPEED = 1.0;
|
||||||
|
public const double DECAY_HEAT_FRACTION = 0.065;
|
||||||
|
public const double DECAY_HEAT_LAMBDA = 0.0077;
|
||||||
|
public const double BETA = 0.0067;
|
||||||
|
public const double LAMBDA_DECAY = 0.078;
|
||||||
|
public const double L_PROMPT_NEUTRON = 0.00002;
|
||||||
|
public const double FUEL_HEAT_CAPACITY = 2.8;
|
||||||
|
public const double HEAT_TRANSFER_COEFF = 0.5;
|
||||||
|
public const double ALPHA_SQRT_T_FUEL = -0.008;
|
||||||
|
public const double CONTROL_ROD_WORTH = -0.05;
|
||||||
|
public const double INTRINSIC_SOURCE = 0.25;
|
||||||
|
public const double COOLANT_TEMP = 300; // K
|
||||||
|
public const double STABLE_TEMP = 547; // K [The temperature at which the doppler effect has no effect on reactivity]
|
||||||
|
|
||||||
|
// --- State Variables ---
|
||||||
|
public double Power { get; private set; } // MW
|
||||||
|
|
||||||
|
// --- Inspect Variables ---
|
||||||
|
public double ReactivityDoppler { get; private set; }
|
||||||
|
public double ReactivityRod { get; private set; }
|
||||||
|
|
||||||
|
public double FuelTemp { get; private set; } // K
|
||||||
|
public double HeatGenerated { get; private set; }
|
||||||
|
|
||||||
|
public double Precursors { get; private set; }
|
||||||
|
public double DecayHeatPrecursors { get; private set; }
|
||||||
|
|
||||||
|
public double ReactivityTotal { get; private set; }
|
||||||
|
public double ControlRodCurrentPosition { get; private set; }
|
||||||
|
public double ControlRodTargetPosition { get; set; } // Can be set externally
|
||||||
|
public double ReactorPeriod { get; private set; }
|
||||||
|
|
||||||
|
public ThermalPort ThermalPort { get; private set; }
|
||||||
|
|
||||||
|
public Reactor(double initialPower = 1.0, double fuelTemp = 300)
|
||||||
|
{
|
||||||
|
Power = initialPower;
|
||||||
|
FuelTemp = fuelTemp;
|
||||||
|
|
||||||
|
// Initialize precursors and decay heat to be in equilibrium
|
||||||
|
Precursors = Power * BETA / (LAMBDA_DECAY * L_PROMPT_NEUTRON);
|
||||||
|
DecayHeatPrecursors = Power * DECAY_HEAT_FRACTION / DECAY_HEAT_LAMBDA;
|
||||||
|
|
||||||
|
ReactivityTotal = 0.0;
|
||||||
|
ControlRodCurrentPosition = 100;
|
||||||
|
ControlRodTargetPosition = 100;
|
||||||
|
ReactorPeriod = double.PositiveInfinity;
|
||||||
|
|
||||||
|
ThermalPort = new ThermalPort(FuelTemp, HeatGenerated);
|
||||||
|
}
|
||||||
|
private double GetReactivityFromRodPosition()
|
||||||
|
{
|
||||||
|
double positionRad = (ControlRodCurrentPosition / 100.0) * Math.PI;
|
||||||
|
double effectiveness = (1 - Math.Cos(positionRad)) / 2.0;
|
||||||
|
return CONTROL_ROD_WORTH * effectiveness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates reactivity from the fuel temperature.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The reactivity due to fuel temperature (Doppler effect).</returns>
|
||||||
|
private double CalculateDopplerReactivity()
|
||||||
|
{
|
||||||
|
return ALPHA_SQRT_T_FUEL * (Math.Sqrt(FuelTemp) - Math.Sqrt(STABLE_TEMP));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Advances the simulation by one time step, dt.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dt">The time step in seconds.</param>
|
||||||
|
public void Step(double dt)
|
||||||
|
{
|
||||||
|
// --- UPDATE CONTROL ROD POSITION ---
|
||||||
|
if (ControlRodCurrentPosition != ControlRodTargetPosition)
|
||||||
|
{
|
||||||
|
double difference = ControlRodTargetPosition - ControlRodCurrentPosition;
|
||||||
|
double maxMove = CONTROL_ROD_SPEED * dt;
|
||||||
|
if (Math.Abs(difference) < maxMove)
|
||||||
|
{
|
||||||
|
ControlRodCurrentPosition = ControlRodTargetPosition;
|
||||||
|
}
|
||||||
|
else if (difference > 0)
|
||||||
|
{
|
||||||
|
ControlRodCurrentPosition += maxMove;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ControlRodCurrentPosition -= maxMove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- PHYSICS CALCULATION ---
|
||||||
|
// 1. Calculate Total Reactivity
|
||||||
|
ReactivityDoppler = CalculateDopplerReactivity();
|
||||||
|
ReactivityRod = GetReactivityFromRodPosition();
|
||||||
|
ReactivityTotal = ReactivityDoppler + ReactivityRod;
|
||||||
|
|
||||||
|
// 2. Solve Point Kinetics
|
||||||
|
double powerOld = Power;
|
||||||
|
double dtLambda = dt * LAMBDA_DECAY;
|
||||||
|
double dtOverL = dt / L_PROMPT_NEUTRON;
|
||||||
|
double numerator = Power + Precursors * dtLambda / (1 + dtLambda) + dt * INTRINSIC_SOURCE;
|
||||||
|
double denominator = 1 - dtOverL * (ReactivityTotal - BETA) -
|
||||||
|
(dtOverL * BETA * dtLambda) / (1 + dtLambda);
|
||||||
|
Power = numerator / denominator;
|
||||||
|
|
||||||
|
Precursors = (Precursors + dt * Power * BETA / L_PROMPT_NEUTRON) / (1 + dtLambda);
|
||||||
|
|
||||||
|
// 3. Calculate Reactor Period
|
||||||
|
double powerChange = Power - powerOld;
|
||||||
|
if (Math.Abs(powerChange) > 1e-9 && Power > 1e-7)
|
||||||
|
{
|
||||||
|
ReactorPeriod = (Power * dt) / powerChange;
|
||||||
|
if (ReactorPeriod < -1500 || ReactorPeriod > 1500)
|
||||||
|
{
|
||||||
|
ReactorPeriod = double.PositiveInfinity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReactorPeriod = double.PositiveInfinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Solve for Decay Heat
|
||||||
|
DecayHeatPrecursors = (DecayHeatPrecursors + dt * Power * DECAY_HEAT_FRACTION) / (1 + dt * DECAY_HEAT_LAMBDA);
|
||||||
|
|
||||||
|
// 5. Solve Thermal-Hydraulics
|
||||||
|
double promptHeat = Power * (1 - DECAY_HEAT_FRACTION);
|
||||||
|
HeatGenerated = promptHeat + DecayHeatPrecursors;
|
||||||
|
//double heatRemoved = HEAT_TRANSFER_COEFF * (FuelTemp - COOLANT_TEMP);
|
||||||
|
//double dFuelTemp = (HeatGenerated - heatRemoved) / FUEL_HEAT_CAPACITY;
|
||||||
|
double dFuelTemp = HeatGenerated / FUEL_HEAT_CAPACITY;
|
||||||
|
FuelTemp += dFuelTemp * dt;
|
||||||
|
|
||||||
|
// --- CLAMPING ---
|
||||||
|
if (Power < 0) Power = 0;
|
||||||
|
if (Precursors < 0) Precursors = 0;
|
||||||
|
if (DecayHeatPrecursors < 0) DecayHeatPrecursors = 0;
|
||||||
|
|
||||||
|
// Update ThermalPort
|
||||||
|
ThermalPort.Measurement = FuelTemp;
|
||||||
|
ThermalPort.ValueToAffect = HeatGenerated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user