I am having trouble locating the source of an additional unknown in a modelling project I am working on. I am getting an error saying I have 34 unknowns and 33 equations. I decided to look at the flattened code in Dymola, and while I can count the correct number of variables, I cannot find a way to reach the 33 equations. Below is the flattened code:
model HeatStorage
parameter Modelica.SIunits.Diameter D = 18.667 "Diameter";
parameter Modelica.SIunits.Height H = 20 "Height";
parameter Boolean enable_losses = false "= true enable thermal losses with environment";
parameter Modelica.SIunits.CoefficientOfHeatTransfer alpha = 1
"Constant heat transfer coefficient with the ambient";
parameter Real L_start = 0 "Start value of level in %";
parameter Modelica.SIunits.Temperature T_start = Modelica.SIunits.Conversions.from_degC
(300) "Start value of temperature";
parameter Modelica.SIunits.Temperature T_max = Modelica.SIunits.Conversions.from_degC
(550) "Maximum tank temperature";
parameter Modelica.SIunits.Temperature T_set = Modelica.SIunits.Conversions.from_degC
(300) "Tank Heater Temperature Set-Point";
parameter Modelica.SIunits.Power W_max = 3000000000.0 "Hot Tank Heater Capacity";
parameter Modelica.SIunits.Efficiency e_ht = 0.99 "Tank Heater Efficiency";
parameter Boolean medium.preferredMediumStates = false "= true if StateSelect.prefer shall be used for the independent property variables of the medium";
parameter Boolean medium.standardOrderComponents = true "If true, and reducedX = true, the last element of X will be computed from the other ones";
input Modelica.Blocks.Interfaces.RealInput Q_heater;
parameter Modelica.SIunits.Volume V_t = H*3.141592653589793*D^2/4;
Modelica.Media.Interfaces.PartialMedium.MassFlowRate fluid_a.m_flow
"Mass flow rate from the connection point into the component";
Modelica.Media.Interfaces.Types.AbsolutePressure fluid_a.p "Thermodynamic pressure in the connection point";
Modelica.Media.Interfaces.Types.SpecificEnthalpy fluid_a.h_outflow
"Specific thermodynamic enthalpy close to the connection point if m_flow < 0";
Modelica.Media.Interfaces.Types.MassFraction fluid_a.Xi_outflow[0]
"Independent mixture mass fractions m_i/m close to the connection point if m_flow < 0";
Modelica.Media.Interfaces.Types.ExtraProperty fluid_a.C_outflow[0](start =
fill(1.0, size(fluid_a.C_outflow, 1))) "Properties c_i/m close to the connection point if m_flow < 0";
Modelica.Media.Interfaces.PartialMedium.MassFlowRate fluid_b.m_flow
"Mass flow rate from the connection point into the component";
Modelica.Media.Interfaces.Types.AbsolutePressure fluid_b.p "Thermodynamic pressure in the connection point";
Modelica.Media.Interfaces.Types.SpecificEnthalpy fluid_b.h_outflow
"Specific thermodynamic enthalpy close to the connection point if m_flow < 0";
Modelica.Media.Interfaces.Types.MassFraction fluid_b.Xi_outflow[0]
"Independent mixture mass fractions m_i/m close to the connection point if m_flow < 0";
Modelica.Media.Interfaces.Types.ExtraProperty fluid_b.C_outflow[0](start =
fill(1.0, size(fluid_b.C_outflow, 1))) "Properties c_i/m close to the connection point if m_flow < 0";
Modelica.SIunits.Temperature heat_PB.T "Port temperature";
Modelica.SIunits.HeatFlowRate heat_PB.Q_flow "Heat flow rate (positive if flowing from outside into the component)";
Modelica.SIunits.Temperature heat_DS.T "Port temperature";
Modelica.SIunits.HeatFlowRate heat_DS.Q_flow "Heat flow rate (positive if flowing from outside into the component)";
Modelica.SIunits.Volume V;
Modelica.SIunits.Mass m;
Modelica.Media.Interfaces.PartialMedium.BaseProperties_D1.InputAbsolutePressure
medium.p(nominal = 100000.0, unit = "Pa", displayUnit = "bar", min = 0.0)
"Absolute pressure of medium";
Modelica.Media.Interfaces.PartialMedium.BaseProperties_D1.InputMassFraction
medium.Xi[0](start = {}, unit = "1", min = 0.0, max = 1.0) "Structurally independent mass fractions";
Modelica.Media.Interfaces.PartialMedium.BaseProperties_D1.InputSpecificEnthalpy
medium.h(unit = "J/kg") "Specific enthalpy of medium";
Modelica.Media.Interfaces.Types.Density medium.d "Density of medium";
Modelica.Media.Interfaces.Types.Temperature medium.T(start = 800, min = 573.15,
max = 873.15) "Temperature of medium";
Modelica.Media.Interfaces.Types.MassFraction medium.X[2](start = {0.5, 0.5})
"Mass fractions (= (component mass)/total mass m_i/m)";
Modelica.Media.Interfaces.Types.SpecificInternalEnergy medium.u
"Specific internal energy of medium";
Modelica.Media.Interfaces.Types.SpecificHeatCapacity medium.R "Gas constant (of mixture if applicable)";
Modelica.Media.Interfaces.Types.MolarMass medium.MM "Molar mass (of mixture or single fluid)";
Modelica.Media.Interfaces.Types.AbsolutePressure medium.state.p
"Absolute pressure of medium";
Modelica.Media.Interfaces.Types.SpecificEnthalpy medium.state.h
"Specific enthalpy";
Modelica.SIunits.Conversions.NonSIunits.Temperature_degC medium.T_degC =
Modelica.SIunits.Conversions.to_degC(medium.T) "Temperature of medium in [degC]";
Modelica.SIunits.Conversions.NonSIunits.Pressure_bar medium.p_bar =
Modelica.SIunits.Conversions.to_bar(medium.p) "Absolute pressure of medium in [bar]";
Modelica.SIunits.Area A;
Modelica.SIunits.HeatFlowRate Q_losses;
Modelica.Media.Interfaces.Types.AbsolutePressure state_i.p "Absolute pressure of medium";
Modelica.Media.Interfaces.Types.SpecificEnthalpy state_i.h "Specific enthalpy";
Modelica.SIunits.Power W_net;
Modelica.SIunits.Power W_loss;
output Modelica.Blocks.Interfaces.RealOutput L "Tank level in %";
Modelica.SIunits.HeatFlowRate Q_PB "Heat Flow to PowerBlock";
Modelica.SIunits.HeatFlowRate Q_desal "Heat Flow to Desalination";
// Equations and algorithms
// Component medium
// class SolarTherm.Media.MoltenSalt.MoltenSalt_base.BaseProperties
// extends Modelica.Media.Interfaces.PartialMedium.BaseProperties_D1
equation
if (medium.standardOrderComponents) then
medium.Xi = medium.X[1:0];
medium.X = {0.5, 0.5};
for i in (1:2) loop
assert(medium.X[i] >= -1E-005 and medium.X[i] <= 1.00001,
"Mass fraction X["+ String(i, true, 0)+"] = "+ String(
medium.X[i], true, 0)+"of substance "+{"NaNO3", "KNO3"}[i]+
"\nof medium "+"MoltenSalt"+" is not in the range 0..1");
end for;
end if;
assert(medium.p >= 0.0, "Pressure (= "+ String(medium.p, true, 0)+
" Pa) of medium \""+"MoltenSalt"+"\" is negative\n(Temperature = "+
String(medium.T, true, 0)+" K)");
// end of extends
equation
medium.d = SolarTherm.Media.MoltenSalt.MoltenSalt_Utilities.rho_T(medium.T);
medium.h = medium.state.h;
medium.u = medium.h-medium.p/medium.d;
medium.MM = 0.091438;
medium.R = 8.3144/medium.MM;
medium.state.p = medium.p;
medium.T = SolarTherm.Media.MoltenSalt.MoltenSalt_Utilities.T_h(medium.h);
// This model
// class PentakomoPlant.Storage.HeatStorage
equation
Q_losses = -0.939*exp(Modelica.SIunits.Conversions.to_degC(medium.T)*
0.005111)*1000*5/7;
fluid_a.p = medium.p;
fluid_b.p = medium.p;
fluid_a.h_outflow = medium.h;
fluid_b.h_outflow = medium.h;
der(m) = fluid_a.m_flow+fluid_b.m_flow;
m*der(medium.h)+der(m)*medium.h = Q_losses+Q_PB+Q_desal+W_net+fluid_a.m_flow
*inStream(fluid_a.h_outflow)+fluid_b.m_flow*medium.h;
V = m/medium.d;
L = 100*(max(medium.T, T_set)-T_set)/(T_max-T_set);
A = 6.283185307179586*(D/2)*H;
W_net = Q_heater;
W_loss = W_net/e_ht;
heat_PB.Q_flow = Q_PB;
heat_DS.Q_flow = Q_desal;
heat_PB.T = medium.T;
heat_DS.T = medium.T;
// Initial equations and algorithms
// This model
// class PentakomoPlant.Storage.HeatStorage
initial equation
medium.h = specificEnthalpy_Unique3(
state_i);
m = density_Unique4(
state_i)*V_t;
end HeatStorage;
If someone could shed some light on exactly how the equations are counted from the flat code so as to help me locate my missing variable, I would be most appreciative!!
Unfortunately the flattened code does not contain all the necessary information.
However, it is a good start and contains 27 equations:
2 binding equations
2 scalar equations in the extends Modelica.Media.Interfaces.PartialMedium.BaseProperties_D1
7 equations in SolarTherm.Media.MoltenSalt.MoltenSalt_base.BaseProperties outside the base-class
16 equations in PentakomoPlant.Storage.HeatStorage.
But in addition there can at least be:
Bindings of records (none in this case)
Flow-variables in top-level public connectors; in this case I would assume it 2+2+1+1 (fluid_a, fluid_b, heat_PB, heat_DS).
The top-level public input Q_heater can be handled in two ways, and as I recall Dymola has used both variants: either it does neither contribute to unknowns nor to equations (seen as a known variable), or it adds one to both.
Related
I'm currently studying chemical engineering and for my Bachelor thesis, I'm supposed to model a heated pipe that can be used in a superheater by connecting two pipes via a heatport together. Even though I made a big effort on understanding how I code correctly in Modelica, my code is still not working and I'm getting pretty desperate.
So the model basically has to be applicable for both fluid water and overheated steam, so just one-phase flow in instationary conditions. Heat transfer is supposed to happen convectively. Also, I neglect pressure losses due to friction in this model.
Here´s my idea of how the model is supposed to work:
I'm pretty much trying to build a model like the one in the MSL, "Dynamic Pipe", just way more easier so that students who work on the same topic are able to understand my code quickly. So I splitted the pipe into a number of nodes n, the first volume being a inlet state, so basically that state does not really belong to the pipe. After that, the balance equations apply. I´m not quite sure about the momentum equations, so any help on them is highly appreciated. Convective heat transfer is defined by the Model "Convection" from the MSL, Thermal.HeatTransfer.Components.
When testing the model with a flow source, a boundary with fixed pressure and a fixed temperature at the wall, I also get the error "Failed to reduce the DAE index" and I have absolutely no idea what that means.
Also, here is my code:
model Pipe_base3
//Import
import Modelica.SIunits.*;
import Modelica.Constants.pi;
replaceable package Medium =
Modelica.Media.Interfaces.PartialTwoPhaseMedium annotation (choicesAllMatching = true);
parameter Integer n=2;
parameter Integer np=1;
// Geometry==================================================================//
parameter Diameter d_pipe = 0.05 "Inner diameter of pipe"
annotation (Dialog(tab="Geometry"));
parameter Length L = 1 "Length of unit"
annotation (Dialog(tab="Geometry"));
parameter Area A_hex = pi * d_pipe * L
"Shell surface of pipe for heat exchange" annotation (Dialog(tab="Geometry"));
parameter Area A_q = (pi/4)*d_pipe^2
annotation (Dialog(tab="Geometry"));
//Initialisation=============================================================//
parameter Medium.Temperature T_start = 403.15 annotation (Dialog(tab="Initialization"));
parameter Medium.SpecificEnthalpy h_start = Medium.specificEnthalpy_pT(p_start, T_start) annotation (Dialog(tab="Initialization"));
parameter AbsolutePressure p_start = Medium.saturationPressure(T_start) annotation (Dialog(tab="Initialization"));
parameter Medium.MassFlowRate m_flow_start = 0.5 annotation (Dialog(tab="Initialization"));
//Temperature, pressure, energy==============================================//
Medium.Temperature T[n+1]( each start=T_start, fixed=false);
Medium.SpecificEnthalpy h[n+1]( each start=h_start, fixed=false);
Medium.AbsolutePressure p[n+1](each start=p_start, fixed=false);
HeatFlowRate Q_flow[n](fixed = false);
Energy U[n](min=0);
Energy KE[n]; //Kinetic Energy
Medium.ThermodynamicState state[n+1];
// Nondimensional Variables + HeatTransfer===================================//
Medium.PrandtlNumber Pr[n](fixed=false);
ReynoldsNumber Re[n](fixed=false);
Real Xi[n];
NusseltNumber Nu[n];
CoefficientOfHeatTransfer alpha[n];
// Thermodynamic properties==================================================//
Medium.SpecificInternalEnergy u[n](fixed=false);
Medium.DynamicViscosity eta[n];
Density rho[n+1];
Medium.SpecificHeatCapacity cp[n];
Medium.ThermalConductivity lambda_fluid[n];
//Segmental properties
Mass ms[n]; //Mass per Segment
MassFlowRate m_flow[n+1]( each start=m_flow_start/np, fixed=false);
Velocity w[n+1](fixed=false);
// Momentum
Force F_p[n];
Momentum I[n];
Force Ib_flow[n];
parameter Boolean init = false;
Modelica.Fluid.Interfaces.FluidPort_a fluidin( redeclare package Medium = Medium, m_flow(start = m_flow_start, min = 0), p(start = p_start))
annotation (Placement(transformation(extent={{-90,-100},{-70,-80}}),
iconTransformation(extent={{-90,-100},{-70,-80}})));
Modelica.Fluid.Interfaces.FluidPort_b fluidout( redeclare package Medium = Medium, m_flow(start = -m_flow_start, max = 0), p(start = p_start), h_outflow(start=h_start))
annotation (Placement(transformation(extent={{70,-100},{90,-80}}),
iconTransformation(extent={{70,-100},{90,-80}})));
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a[n] heatport
annotation (Placement(transformation(extent={{-10,60},{10,80}}),
iconTransformation(extent={{-10,60},{10,80}})));
Modelica.Blocks.Interfaces.RealOutput[n] alpha_output annotation (Placement(
transformation(extent={{-100,38},{-140,78}}), iconTransformation(extent={{-100,
38},{-140,78}})));
protected
parameter Volume vn = (A_q * L) / n; //Volume per segment
parameter Real x[n] = linspace((L/n), L, n);
parameter Length length = L/n;
initial equation
for i in 1:(n+1) loop
//h[i] = Medium.specificEnthalpy_pTX(p_start, T_start, {1});
p[i] = p_start;
end for;
equation
//Port equations=============================================================//
fluidout.p = p[n];
//fluidin.p-fluidout.p=p[1]-p[n+1];
fluidout.h_outflow = h[n];
fluidout.m_flow = -m_flow[n+1];
//===========================================================================//
h[1]=inStream(fluidin.h_outflow);
p[1]=fluidin.p;
state[1]=Medium.setState_ph(p[1],h[1]);
T[1]=Medium.temperature(state[1]);
rho[1]=Medium.density(state[1]);
m_flow[1]=fluidin.m_flow/np;
m_flow[1]=A_q*rho[1]*w[1];
for i in 1:(n) loop
// Heatport equations======================================================//
T[i] = heatport[i].T;
Q_flow[i] = heatport[i].Q_flow;
// Momentum Balance =======================================================//
der(I[i]) = Ib_flow[i] - F_p[i];
I[i]=m_flow[i]*length;
Ib_flow[i] = (p[i+1]*w[i+1]*w[i+1] - p[i]*w[i]*w[i])*A_q*np;
F_p[i] = (A_q*p[i+1]-A_q*p[i]);
// Energy Balance=========================================================//
U[i] = ms[i] * u[i];
KE[i] = 0.5*ms[i]*w[i+1]*w[i+1];
der(U[i]+KE[i])=m_flow[i]*(h[i]+0.5*w[i]) - m_flow[i+1]*(h[i+1]+0.5*w[i+1]) + Q_flow[i];
der(rho[i+1])= -((rho[i+1]-rho[i])*w[i+1] + (w[i+1]-w[i])*rho[i+1]); //Konti
ms[i]=vn*rho[i+1];
T[i+1]=Medium.temperature(state[i+1]);
state[i+1] = Medium.setState_ph(p[i+1], h[i+1], 1); //Sets thermodynamic state from which other properties can be determined
u[i] = Medium.specificInternalEnergy(state[i+1]);
cp[i] = Medium.specificHeatCapacityCp(state[i+1]);
rho[i+1] = Medium.density(state[i+1]);
eta[i] = Medium.dynamicViscosity(state[i+1]);
lambda_fluid[i] = Medium.thermalConductivity(state[i+1]);
Re[i] * eta[i] = (rho[i+1] * abs(w[i+1]) * d_pipe);
Pr[i] *lambda_fluid[i] = (eta[i] * cp[i]);
Xi[i] = (1.8 * log10(abs(Re[i])+1) - 1.5)^(-2);
Nu[i] = ((Xi[i]/8)*Re[i]*Pr[i])/(1+12.7*sqrt(Xi[i]/8)*((Pr[i])^(2/3)-1))*(1+(1/3)*(d_pipe/x[i])^(2/3));
Nu[i] = Modelica.Fluid.Pipes.BaseClasses.CharacteristicNumbers.NusseltNumber(alpha[i], d_pipe, lambda_fluid[i]);
alpha_output[i] = alpha[i] * (A_hex/n);
m_flow[i+1] = A_q * w[i+1] * rho[i+1];
// der(p[i]) = - w[i]*der(w[i]) * rho[i];
// 0 = m_flow[i-1] - m_flow[i];
// der(rho[i]) = -((rho[i]-rho[i-1])*w[i] + (v[i]-v[i-1])*rho[i]);
//m_flow[i] = A_q * w[i] * rho[i]; //Calculation of flow velocity
//ms[i] = vn * rho[i]; //Mass per segment
//Calculation of thermodynamic properties for each segment=================//
//Heat Transfer============================================================//
end for;
fluidin.h_outflow = h[1]; //
annotation (Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},
{100,100}}), graphics={Line(
points={{-80,-80},{-80,94},{-80,100},{0,20},{80,100},{80,-80}},
color={0,0,255},
smooth=Smooth.None), Line(
points={{-60,-60},{-60,-48},{-60,0},{60,0},{60,-60},{48,-40},{72,-40},
{60,-60}},
color={0,0,255},
smooth=Smooth.None)}), __Dymola_selections);
end Pipe_base3;
Thank you so much in advance!
I was in the same situation when I started using Modelica: I wanted the features of Modelica.Fluid.Pipes.DynamicPipe but with less complexity (I wanted the code to be more readable and less hierarchical). So, like you, I started building my own pipe model from scratch. However, because I wanted to be able to replace the pressure drop and heat transfer correlations and have great flexibility I ended up with a model of nearly the same complexity as Modelica.Fluid.Pipes.DynamicPipe.
My recommendation to you is to
build your own simple dynamic pipe model without any complex
features. This will only be usable for educational purposes (e.g.
letting other students understand your coding principles)
learn how to use Modelica.Fluid.Pipes.DynamicPipe for problems where you need vary model complexity (number of segment, replaceable pressure drop and heat transfer methods etc.). Modelica.Fluid.Examples.HeatExchanger is an example of how you can use Modelica.Fluid.Pipes.DynamicPipe to model a heat exchanger like the one you request.
Here I've shared an example of a very simple dynamic pipe that can be used as a heat exchanger. The pipe is made from n pipe segments and takes advantage of the fact that you can instantiate an array of components and connect the elements in a for loop.
As for the momentum balance, the correct/complete way is to account for the change in momentum by summing all the forces acting on each control volume (Newton's Second law). However, in most lumped models a steady-state momentum balance is adequate which reduces the equation to a linear or quadratic relation between mass flow rate and pressure drop. Modelica.Fluid.Pipes.DynamicPipe has a number of different presssure/flow correlations to choose from.
Best regards,
Rene Just Nielsen
I have built a small example/test that uses your model. It should be a very simple application of your model. Unfortunately I get the same error message:
Cannot find differentiation function:
Modelica.Media.Water.IF97_Utilities.waterBaseProp_ph(boundary1.p, pipe_base3_1.h[2], 0, 1)
with respect to time
Index reduction basically means that the model contains equations that have no unknown. This is solved by differentiation of these equations with respect to time (which can happen multiple times). For more information you can check
https://www.inf.ethz.ch/personal/cellier/Lect/NSDS/Ppt/nsds_ppt_engl.html
especially lecture 16 and probably the ones before it :)
Therefore the Modelica tool will have to know how to do this differentiation. For equations this is usually done automatically, but for functions it has to be specified by the developer. It seems this is not done for Modelica.Media.Water.IF97_Utilities.waterBaseProp_ph()
which is why you get the error message.
There are basically two possibilities to solve this problem:
You change your model to get rid of or revise the constraint equation (the one which has no unknown). It should be the one shown in the error message: der(pipe_base3_1.rho[2]) = ...
You add the function for differentiation to the medium (I'm not much into the Fluid/Media so I have no idea how complicated that is, so I would try to go with 1. first). How this can be done is shown in https://modelica.org/documents/ModelicaSpec33Revision1.pdf section 12.7
Here is the code of the example:
model PipeTest
Pipe_base3 pipe_base3_1(redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
Modelica.Fluid.Sources.FixedBoundary boundary(
nPorts=1,
p=100000,
redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
annotation (Placement(transformation(extent={{-60,-40},{-40,-20}})));
Modelica.Fluid.Sources.FixedBoundary boundary1(
nPorts=1,
p=100000,
redeclare package Medium = Modelica.Media.Water.WaterIF97_R1pT)
annotation (Placement(transformation(extent={{60,-40},{40,-20}})));
Modelica.Thermal.HeatTransfer.Sources.FixedHeatFlow fixedHeatFlow[2](Q_flow={0,0})
annotation (Placement(transformation(extent={{-40,20},{-20,40}})));
equation
connect(boundary.ports[1], pipe_base3_1.fluidin) annotation (Line(points={{-40,-30},{-8,-30},{-8,-9}}, color={0,127,255}));
connect(boundary1.ports[1], pipe_base3_1.fluidout) annotation (Line(points={{40,-30},{8,-30},{8,-9}}, color={0,127,255}));
connect(fixedHeatFlow.port, pipe_base3_1.heatport) annotation (Line(points={{-20,30},{0,30},{0,7}}, color={191,0,0}));
annotation (
Icon(coordinateSystem(preserveAspectRatio=false)),
Diagram(coordinateSystem(preserveAspectRatio=false)),
uses(Modelica(version="3.2.2")));
end PipeTest;
Hope this helps...
To be precise, the loss function that I'm looking for is the squared error when the absolute error is lesser than 0.5, and it is the absolute error itself, when the absolute error is greater than 0.5. In this way, the gradient from the error function doesn't exceed 1 because once the gradient of the squared error function reaches 1, the absolute error function kicks in, and the gradient remains constant at 1. I've included my current implementation below. For some reason, it's giving me worse performance than just the squared error.
fn_choice_maker1 = (tf.to_int32(tf.sign(y - y_ + 0.5)) + 1)/2
fn_choice_maker2 = (tf.to_int32(tf.sign(y_ - y + 0.5)) + 1)/2
choice_maker_sqr = tf.to_float(tf.mul(fn_choice_maker1, fn_choice_maker2))
sqr_contrib = tf.mul(choice_maker_sqr, tf.square(y - y_))
abs_contrib = tf.abs(y - y_)-0.25 - tf.mul(choice_maker_sqr, tf.abs(y - y_)-0.25)
loss = tf.reduce_mean(sqr_contrib + abs_contrib)
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
choice_maker_sqr is a column tensor that is one whenever the error is between 0.5 and -0.5. The names are pretty self explanatory.
Here is my implementation of the Huber loss function in python tensorflow:
def huber_loss(y_true, y_pred, max_grad=1.):
"""Calculates the huber loss.
Parameters
----------
y_true: np.array, tf.Tensor
Target value.
y_pred: np.array, tf.Tensor
Predicted value.
max_grad: float, optional
Positive floating point value. Represents the maximum possible
gradient magnitude.
Returns
-------
tf.Tensor
The huber loss.
"""
err = tf.abs(y_true - y_pred, name='abs')
mg = tf.constant(max_grad, name='max_grad')
lin = mg*(err-.5*mg)
quad=.5*err*err
return tf.where(err < mg, quad, lin)
You can use tf.select to implement it in a single call:
err = y - y_
huber_loss = tf.select(tf.abs(err) < 1.0,
0.5 * tf.square(err),
tf.abs(err) - 0.5) # if, then, else
err = tf.subtract(x,y)
huber_loss = tf.where(tf.less(x,y),
tf.sqrt(tf.square(err)),
tf.abs(err))
with tf.Session() as sess:
print(sess.run(tf.reduce_mean(huber_loss)))
Not sure if this is still relevant, but I would like to point it out to those seeking this in the future. The tensorflow research losses script has an implementation of the Huber loss for Object detection (like its implemented in the FasterRCNN paper)
Here's the link to the method
GOAL:
In this project, we calculate the gravitational forces exerted by each body in a solar system on the other bodies in the system. Based upon those forces and initial position/velocities of the bodies, one can predict their motion using Newton’s second law. We assume that the following information is given:
The masses of all bodies involved in a solar system.
The positions and velocities of all planets at a given time.
Then we can calculate the gravitational forces using Newton’s law of universal gravitation. Each body is acted upon by gravitational forces from all the other bodies, and therefore the total force on the body is the sum of the forces induced by all the other bodies. Once the force on a body is known, the acceleration of each body can be determined using Newton’s second law of motion. Based upon this acceleration at any time t, we can calculate the new velocity and position of the bodies at time t + ∆t. We start with known positions and velocities at time t = 0, then calculate those at ∆t, then at 2∆t and so on.
ASSIGNMENT:
Write a MATLAB function that takes as input a struct array (where each element represents one body in your solar system), a time step ∆t and a final time T. Each struct in the struct array should have the following fields:
name: A string that holds the name of the planet.
x: The x-coordinate of the initial position of the planet.
y: The y-coordinate of the initial position of the planet.
z: The z-coordinate of the initial position of the planet.
vx: The x-component of the initial velocity of the planet.
vy: The y-component of the initial velocity of the planet.
vz: The z-component of the initial velocity of the planet.
Then your function should use the model of a gravitational system described above to compute the positions and velocities of all planets at all times. Your function should return these values in an appropriate way and also produce a plot of the positions of all planets in a 3D plot. The plot should at least contain a title and a legend. The legend should use the field name in order to name each planet. Further, each planet should be shown in a different color where the color is determined randomly. A sample plot is given in Figure 1.
MY ERROR
There is an error in my last loop with time in it, has n=1:T/t; regarding matrix dimensions. I'm trying to calculate new forces using the updated positions from each iteration, however I am getting and error, and my plot shows a bunch of straight lines, and not a solar system orbit.**
function [x, y, z, vx, vy, vz] = solarsystemsim(F,t,T)
m = size(F,2);
G = 6.67384e-11;
j=1;
x = 1:10;
% r = zeros(m-1,1);
% gF = zeros(m-1,1);
for(i=1:m)
for(j=1:m)
r(i,j) = distform2(F(i).x,F(j).x,F(i).y,F(j).y,F(i).z,F(j).z);
gF(i,j) = (G*(F(i).mass)*(F(j).mass))/((r(i,j))^2);
gFx(i,j) = -((gF(i,j))*(F(i).x-F(j).x))/(r(i,j));
gFy(i,j) = -((gF(i,j))*(F(i).y-F(j).y))/(r(i,j));
gFz(i,j) = -((gF(i,j))*(F(i).z-F(j).z))/(r(i,j));
if(i==j)
gF(i,j) = 0;
gFx(i,j) = 0;
gFy(i,j) = 0;
gFz(i,j) = 0;
end
end
end
for(i=1:m)
gFxT(i) = sum(gFx(i,:));
gFyT(i) = sum(gFy(i,:));
gFzT(i) = sum(gFz(i,:));
end
tn = 0;
n = 1;
x = zeros(T/t,m);
y = zeros(T/t,m);
z = zeros(T/t,m);
vx = zeros(T/t,m);
vy = zeros(T/t,m);
vz = zeros(T/t,m);
for(i=1:m)
vx(1,i) = F(i).vx;
vy(1,i) = F(i).vy;
vz(1,i) = F(i).vz;
x(1,i) = F(i).x;
y(1,i) = F(i).y;
z(1,i) = F(i).z;
end
for(n=1:T/t)
for(i=1:m)
for(j=1:m)
r(i+1,j+1) = distform2(x(i,j),x(i,j),y(i,j),y(i,j),z(i,j),z(i,j));
gF(i+1,j+1) = (G*(F(i).mass)*(F(j).mass))/((r(i,j))^2);
gFx(i+1,j+1) = -((gF(i,j))*(x(i,j)-x(i,j+1)))/(r(i,j));
gFy(i+1,j+1) = -((gF(i,j))*(y(i,j)-y(i,j+1)))/(r(i,j));
gFz(i+1,j+1) = -((gF(i,j))*(z(i,j)-z(i,j+1)))/(r(i,j));
if(i==j)
gF(i,j) = 0;
gFx(i,j) = 0;
gFy(i,j) = 0;
gFz(i,j) = 0;
end
end
end
gFxT(i) = sum(gFx(i,:));
gFyT(i) = sum(gFy(i,:));
gFzT(i) = sum(gFz(i,:));
for(i=1:T/t)
for(j=1:m)
vx(i,j) = vx(i,j) + t*(gFxT(j))/(F(j).mass);
vy(i,j) = vy(i,j) + t*(gFyT(j))/(F(j).mass);
vz(i,j) = vz(i,j) + t*(gFzT(j))/(F(j).mass);
x(i,j) = x(i,j) + t*(vx(j));
y(i,j) = y(i,j) + t*(vy(j));
z(i,j) = z(i,j) + t*(vz(j));
end
end
plot3(x,y,z);
end
F is not a matrix and so you can't index it using parentheses. It's a cell array and must be indexed using braces {}
EDITED to correct struct to cell as per lmillefiori's comment
I have a model of a tank that I am creating as follows:
model Tank "Simple model of a tank"
parameter Real volume=1 "tank volume (m^3)";
parameter Integer num_ports=1 "Number of ports";
parameter Real static_pressure=1 "Internal Tank Pressure";
parameter Real initial_level = 0;
Stream[num_ports] ports "Stream Connectors";
Real level "Level in % 0-100";
protected
Real vol "Volume of medium in the tank";
Real pressure(start=static_pressure) "Pressure inside the tank";
initial equation
level = initial_level;
/* Pressure */
equation
pressure = vol * 0.01; // Add correct factor here to get from volume to pressure change (based on height and head)
for i in 1:num_ports loop
ports[i].pressure = static_pressure + pressure;
end for;
/* Volume Flow */
equation
der(vol) = sum(ports.m_flow); // Add density factor to get form mass flow to Volume Flow
level = vol * 100 / volume;
end Tank;
How can I make it so that when the level <=0 the tank will not allow any flows with a negative value (no ports can have fluid leaving, but fluid can still enter)? I feel like I am missing something trivial, but can't seem to find a way without having too many equations (over-determined system).
Thanks
You could try with a when equation:
when level < 0 then
reinit(level, 0)
end when;
I am trying to build a very simple model of a distributed thermofluid volume in Modelica and am struggling to implement it correctly with the stream operator. This volume uses DryAirNasa as the medium, and I would like it to have no mass storage, no pressure drop, and no energy storage (much like the Modelica.Fluid.Pipes.StaticPipe model). However, I would like to explicitly perform an energy balance so that there can be heat transfer interactions. I would also prefer not to define the mass flow rate in this model, but let it be defined in one of the boundaries attached to an end of the pipe (e.g., Modelica.Fluid.Sources.MassFlowSource_h).
I have created a test implementation of such a model, but this model apparently lacks one equation according to Dymola. I would appreciate any insights into how to fix this model so that it is correct. If I add the equation
port_a.h_outflow = Medium.specificEnthalpy(state_a)
to the equation section, the model has the same number of equations and unknowns, but I don't have any good justification for adding such an equation.
model AirFlowTemp
// Objective: create a component that has no pressure drop, no mass storage,
and no energy storage, but that has a heat input.
import SI=Modelica.SIunits;
final replaceable package Medium=Modelica.Media.Air.DryAirNasa;
AirFlow.AirFlowPort port_a(redeclare package Medium
= Medium);
AirFlow.AirFlowPort port_b(redeclare package Medium
= Medium);
Interfaces.HeatPort heatPort;
Medium.EnthalpyFlowRate[2] H_flow "enthalpy flow";
SI.HeatFlowRate Q_flow "heat flow rate";
Medium.Temperature T_mean;
Medium.ThermodynamicState state_a;
Medium.ThermodynamicState state_b;
equation
// no pressure drop across the component.
port_a.p = port_b.p;
// Assume that there is no mass storage in the volume
0 = port_a.m_flow + port_b.m_flow;
// Energy balance
H_flow[1] = semiLinear(port_a.m_flow, inStream(port_a.h_outflow), inStream(port_b.h_outflow));
H_flow[2] = semiLinear(port_b.m_flow, inStream(port_b.h_outflow), inStream(port_a.h_outflow));
0 = Q_flow + H_flow[1] + H_flow[2];
state_a = Medium.setState_ph(port_a.p, inStream(port_a.h_outflow));
state_b = Medium.setState_ph(port_b.p, inStream(port_b.h_outflow));
T_mean = (Medium.temperature(state_a) +
Medium.temperature(state_b))/2;
heatPort.Q_flow = Q_flow;
heatPort.T = T_mean;
end AirFlowTemp;
connector AirFlowPort
replaceable package Medium = Modelica.Media.Interfaces.PartialMedium;
Medium.AbsolutePressure p;
flow Medium.MassFlowRate m_flow;
stream Medium.SpecificEnthalpy h_outflow;
stream Medium.MassFraction Xi_outflow[Medium.nXi];
end AirFlowPort;
connector HeatPort
extends Modelica.Thermal.HeatTransfer.Interfaces.HeatPort;
end HeatPort;
I had the same problem doing the same thins about 4 weeks ago.
Try if this works out as a step to get closer to right use of inStream.
Remove
Medium.EnthalpyFlowRate[2] H_flow "enthalpy flow"
SI.HeatFlowRate Q_flow "heat flow rate";
Interfaces.HeatPort heatPort;
SI.HeatFlowRate Q_flow "heat flow rate";
Medium.Temperature T_mean;
T_mean = (Medium.temperature(state_a) + Medium.temperature(state_b))/2;
heatPort.Q_flow = Q_flow;
heatPort.T = T_mean;
=> just testing the pipe, without the heatPort
Use
port_a.outflow*port_a.m_flow = inStream(port_b.outflow)*port_b.m_flow;
port_b.outflow*port_b.m_flow = inStream(port_a.outflow)*port_a.m_flow;
instead of:
H_flow[1] = semiLinear(port_a.m_flow, inStream(port_a.h_outflow), inStream(port_b.h_outflow));
H_flow[2] = semiLinear(port_b.m_flow, inStream(port_b.h_outflow), inStream(port_a.h_outflow));
0 = Q_flow + H_flow[1] + H_flow[2];
Change your Test for no heatport
=> Does this work?
Regards
Uwe