With the framework for the V-HAB simulation finished you can finally start the actual work. The next few chapters will show you the basics you require to simulate LSS in V-HAB and first off are the stores and phases. Basically a store in V-HAB is the virtual representation of a real store inside a LSS. For example, the ISS has buffer stores for oxygen and nitrogen. These would be represented within V-HAB as stores. But a store alone cannot contain matter in the simulation. It always requires a phase that defines the current matter state (solid, liquid or gas). It is also possible for a store to contain multiple phases. For example, if a gas is used to pressurize the liquid in a store (which is done for example for smaller fuel tanks) you have a gas and a liquid phase inside the same store. In 1.4.1 Creating a New System in V-HAB you already added one store and one gas phase to the system but without actually knowing what you are doing and how it works. Therefore, we are going to take a closer look at the working of stores and phases in this chapter. First off a phase always requires a store, without a store there can be no phase. So the first part we will discuss is the creation of stores. The basic code that is used to add a store is:

matter.store(this, 'StoreName', StoreVolume);

Where StoreName can be exchanged by you to give the store a meaningful name. You should refrain from using something like Store1 or Tank2 since it will be hard to guess the actual use the store has from these names. Try to use names that are easy for someone else to understand when looking at your code and that allow to guess what the store is used for. Instead of StoreVolume you can set either a number(float) or use any variable that contains a float to define the volume in m³ that this store has. Note that if you have multiple phases in the same store the volume has to be large enough to support this since the store volume is defined before the phase volumes are defined. The input this is the system you are adding the store to and since the addition of stores takes place in the createMatterStructure() function of the respective system, as explained in 1.4.1 Creating a New System in V-HAB , the variable this is already defined correctly and you just have to provide it as input for the store as shown here.

The store also has an optional input that allow you to change advanced settings for the store. 

matter.store(this, 'StoreName', fStoreVolume, tGeometry);

The tGeometry input is a struct which you can provide to a store that will be saved as a store property. This is useful if you want to provide information about the geometry of the store for other calculations within V-HAB and since the input is a struct you can decide the fieldnames and therefore the type of geometry (sphere, cube…) for the store.

Now you should be able to add the necessary stores for the simulation to the system. The suggested store names and volumes that will be used later on during this tutorial are.

Store Name

Store Volume (m³)

Cabin

55

HX_Coolant

0.02

O2_Generation

0.52

CO2_Removal

1.01

Water_Supply

1.1

Condensate_Storage1

Waste_Storage

10

Vacuum

1e6


For the cabin store you can simply change the volume of the store to the value provided in the table. The other stores have to be added by you. With this code however you only have an empty store that does not contain any matter at all. In order to add matter, you have to add a phase to the store. There are currently four different phases that can be used in V-HAB solid, liquid, gas and mixture that each have individual inputs and characteristics. Generally, a phase can be added using the following code

matter.phases.XXX(oStore, 'PhaseName', struct('Substance',fMass), YYY);

Where XXX and YYY are specific for the type of phase you want to use. However, the first three inputs are equal for all phases. The first input you have to provide for a phase is the store object to which the phase should be added. This can be done by using the toStores property of the system and the store name. For example, the phase that was added in 1.4.1 Creating a New System in V-HAB used this.toStores.Cabin to create the phase in the store with the name Cabin. The second input is the name of the phase which has to be provided as string. The third input is a struct containing the matter the phase should contain. The fieldnames of the struct have to be names of substances that are saved in the matter table and the field values are the masses you want the respective substance to have. Again from the previous chapter the phase you added used struct('N2', 1) to add one kilogram of nitrogen to the phase. If you want to add more than one substance you can simply add additional fields to the struct like this struct('N2', 1, 'O2', 0.1). Since the actual process of adding a phase depends on the type of phase you want to add, the remaining part of the chapter is split into subchapters that each discuss one phase type.

1.4.2.1 Solid

In order to add a solid phase to the system you have to use the following code:

The oStore and sName and struct('Substance',fMass) inputs were already explained. The solid phase has the additional input fTemperature that allows you to set the temperature of the phase in K. The matter table calculates the actual volume of the solid phase. In our example, the food for the astronauts is a solid phase as well as part of the waste produced by the astronauts. Simply add the following solid phase to the code after the store definitions.

matter.phases.solid(oStore, 'PhaseName', struct('Substance',fMass), fTemperature);

Store

Phase Name

Substances

Temperature

Waste_Storage

Solid_Waste

'C42H69O13N5',0.1

293

For the food we must use a specific library store. For now simply add this line of code to add the food:

components.matter.FoodStore(this, 'Food',  100, struct('Food', 100));

Note that the matter Food represents the standard diet of Astronaut used on the ISS, while the chemical substance in the solid waste compartment is an often used approximation for the composition of human feces.

1.4.2.2 Liquid

In order to add a liquid phase to the system you have to use the following code:

matter.phases.liquid(oStore, 'PhaseName', struct('Substance',fMass), fTemperature, fPressure);

The oStore and sName and struct('Substance',fMass) inputs were already explained. The liquid phase has the additional inputs that allow the user to specify the assumed Volume, Temperature and Pressure for this phase. In general V-HAB assumes liquids to be incompressible and they currently do not change their pressure/volume unless specifically prompted to do so. You can now go ahead and add the required liquid phases according to the following table.

Store

Phase Name

Substances

Temperature

Pressure

Condensate_Storage

Condensate

'H2O',1

293

1e5

HX_Coolant

Coolant

'H2O',10

293

1e5

O2_Generation

Water

'H2O',10

293

1e5

Water_Supply

Water

'H2O',1000

293

1e5

Waste_Storage

Liquid_Waste

'H2O',0.1

293

1e5

1.4.2.3 Gas

Gas phases will most likely be the type of phase you will use most frequently since gases are commonly found in LSS. In order to add a gas phase to the system you have to use the following code:

matter.phases.gas(oStore, 'PhaseName', struct('Substance',fMass), fVolume, fTemperature);

Again the inputs oStore and sName and struct('Substance',fMass) were already explained in the general section about phases. Aside from these, the gas phase has the inputs fVolume and fTemperature, which allow you to specify the initial Volume and Temperature of the Gas Phase. The volume of the gas phase will be overwritten by V-HAB with the remaining volume of the store after subtracting liquid and solid phases that are in the same store. This means that if you add a store with 1 m³ volume and add a solid phase with 0.5 m³ of volume and a gas phase with the input parameter of 1 m³ for the volume V-HAB will automatically change the volume of your gas phase to 0.5 m³. You can now go ahead and add the required gas phases for the introductory system using the following values.

Store

Phase Name

Substances

Volume

Temperature

O2_Generation

Hydrogen

'H2',0.3

0.25

293

O2_Generation

Oxygen

'O2',0.1

0.25

293

For gas phases you often do not want to define the masses of the components but rather the partial pressures of the substances. For example for the cabin air we want to have ~78% nitrogen ~21% Oxygen and a bit of water (humidity) and CO2. In order to easily define such a phase you can use a helper which is called through the store to which you want to add the phase. You should replace the initial definition of the CabinAir phase with the one shown below. Note that it is not possible to define a phase with the same name twice!:

%                               sHelper,   sPhaseName, fVolume,          tfPartialPressure,               fTemperature, rRelativeHumidity)
this.toStores.Cabin.createPhase(  'gas',   'CabinAir',   54.99, struct('N2', 8e4, 'O2', 2e4, 'CO2', 500),          293,          0.5);

The comments above the inputs here describe the necessary values, the first input always has to be the helper you want to use. A list of these helpers can be found in core/+matter/+helper/+phase. The following inputs depend on the helper you want to use, so you have to open the respective helper and look at them. In this case the inputs are the phase volume, the partial pressure composition (0.8 bar Nitrogen, 0.2 bar Oxygen, 500 Pa CO2) and the temperature. The relative humidity is an optional parameter if you do not want to define the partial pressure of water, but rather the relative humidity directly, in this case the humidity is 50%.


In addition there are optional parameters which can be used when defining phases through helpers. For example, the air phase in the CO2 filter is small and it makes no sense to model very small volumes as normal phases because they would limit the time step significantly. For that purpose we can use so called "flow" phases where the assumption is that the phase composition is defined through the in flows because the phase itself is infinitesimal small and contains no mass. TO define a flow phase for the CO2 filter you can use the call:

%                              		  sHelper,  sType,  sPhaseName, fVolume,          tfPartialPressure,               fTemperature, rRelativeHumidity)
this.toStores.CO2_Removal.createPhase(  'gas', 'flow',   'Air',   0.01, struct('N2', 8e4, 'O2', 2e4, 'CO2', 500),          293,          0.5);

Note that the volume is still a required parameter, but it does not influence the phase behavior in the simulation. It is only used to calculate initial parameters for the phase which make sense.


On the other hand we sometimes have phases which should be infinitely large. In the current example this would be the vacuum around the spacecraft. It should not change its composition no matter what we do with it. That can be achieved using a boundary phase, which can be done e.g. using the following definition:

%                              	 sHelper,  sType,  sPhaseName, fVolume,     tfPartialPressure,        fTemperature, rRelativeHumidity)
this.toStores.Vacuum.createPhase(  'gas', 'boundary',   'Vacuum',   1e6, 	struct('N2', 2),          3,          0);

This assumes a phase with 2 Pa pressure and 3 K temperature, which will be kept constant at these levels, no matter how much we add or remove from the phase. The volume is again only used for the initial definition of parameters, but then does not play a role in the phase behavior any more. Note that you can also boundary phases if you want to model environmental conditions from test data (e.g. the surrounding air of a test chamber), as you can change the composition of the boundary phase during a simulation directly through its functions.

Of course, both flow and boundary phases can also be defined without helpers. in that case you need to use the general definition with the specific addition flow or boundary before the phase state. It also works with solids, liquids or mixture phases:

matter.phases.flow.gas(oStore, 'PhaseName', struct('Substance',fMass), fVolume, fTemperature);

matter.phases.boundary.gas(oStore, 'PhaseName', struct('Substance',fMass), fVolume, fTemperature);

1.4.2.4 Mixture

At this point you might be wondering why a fourth phase exists in V-HAB since the physically possible matter states are already covered by the previous three phase types. The mixture phase became necessary since the matter table calculation of matter properties otherwise decided that an impossible combination of substances for the type of phase is present. This occurs for example when absorbing CO2 with a zeolite. The zeolite is a solid and the dominant matter type. Therefore, you might try to model it using a solid phase. Of course, this works as long as only zeolite is in the phase. Nevertheless, if you add CO2, which should be a gas for the given temperature and pressure, the matter table would deduce that this combination is not possible and be unable to calculate the matter properties correctly. The solution to this is the mixture phase. In principle, the mixture phase can represent an arbitrary mixture of solid, gas or liquid. For example a solid or liquid substance present as aerosol in a gas phase could also be modeled with the mixture phase. The difference to the other phases is that it allows phase changes to occur and also for multibe substances in different phase types to be present. For this to work smoothly, the matter table first calculates the current state of the substance at the provided conditions and then calculates the matter properties for each substance at the state in which it currently is present. The initially defined primary phase type is however not change even if all substance in a mixture changed their matter state, as that property is only for information purposes. In order to add an mixture phase to the system the following code has to be used:

matter.phases.mixture(oStore, 'PhaseName', 'sMatterState', struct('Substance',fMass), fTemperature, fPressure);

Additionally to the normal phase inputs the mixture phase has inputs that allow the user to define the initial temperature of the phase, the matter state (solid, gas or liquid) and the absorber substance. If the absorber substance is not specified the phase will assumed the substance with the highest mass as the absorber substance. For the introductory example only one absorber phase is required to remove the CO2 from the atmosphere. In this case lithium hydroxide is used to absorb the CO2 in a chemical reaction and the absorber substance is the lithium hydroxide (LiOH). TO DO: Add this substance to the V-HAB matter table, till then use just Li

Store

Phase Name

Substances

Temperature

Matter State

Pressure

CO2_Removal

LiOH

'Li',50

293

solid

1e5 Pa

1.4.2.5 Plotting

Now we have a few more values that we can add to the plots, but first we have to tell V-HAB to log them. Currently you should have the following line in the setup file configureMonitors() function

%				            	Path to object			   ,   Property , Unit,        Label
oLogger.addValue('Example.toStores.Cabin.toPhases.CabinAir', 'fPressure', 'Pa', 'Total Cabin Pressure');

In this definition the first input is a string towards the object that contains the value you would like to log and the second input is a string for the property you want to log. After that you define the unit and the label of this log value to easier identify it later on. If you are unsure what the path to the respective objects is you can run the simulation and click on the oLastSimObj in your workspace. You will find your system under oSimulationContainer → toChildren and can then navigate to the different parts of your system. The necessary path for logging is then the one you see in the tab starting with your system name (in this case example). For example below is an example where the CabinAir phase is open and you can see the object path in the tab name above the properties.

If you want to log a value from a vector, such as the partial pressure of CO2 from within afPP, you can reference the respective field in the property you define for the log. For example to log the partial pressure of CO2 you can log the property 'this.afPP(this.oMT.tiN2I.CO2)'.

Of course this also works with the partial masses, you just have to reference afMass instead of afPP.

Now try adding the cabin temperature, the partial pressure of CO2 in the cabin, the relative humidity in the cabin, the mass of CO2 in the LiOH and the mass of condensate in the condensate storage


Usually you will have quite a lot of different values you want to plot and you do not want a new figure for every value (because that would result in a lot of figures). Therefore, the plotting in V-HAB allows you to define a cell matrix of plots for each figure. The position of the plot in the matrix defines the position of the plot in the figure, for example a 2x2 cell array which looks like this:

{'"Total Cabin Pressure"', '"Cabin Temperature"';...
 '"Partial Pressure CO2"', '"Relative Humidity"'}

Will result in a figure with 2x2 plots where the top left corner contains the cabin pressure plot and the bottom right corner contains the relative humidity plot. In order to define the figure you first have to create the plot cell which can be done with the following code:

% Define the first row of plots
coPlot{1,1} = oPlotter.definePlot({'"Total Cabin Pressure"'}, 		'Total Cabin Pressure');
coPlot{1,2} = oPlotter.definePlot({'"Cabin Temperature"'}, 			'Cabin Temperature');

% define the second row of plots
coPlot{2,1} = oPlotter.definePlot({'"Partial Pressure CO2 Cabin"'}, 'Partial Pressure CO2 Cabin');
coPlot{2,2} = oPlotter.definePlot({'"Relative Humidity Cabin"'}, 	'Relative Humidity Cabin');

% Define the figure
oPlotter.defineFigure(coPlot, 'Cabin Atmosphere Values');

Note that the values in between the " have to be the same as the labels you defined for the log values, otherwise the plotter will not know what you want to plot. Now try adding a 2x1 plot in a second figure for the CO2 mass and condensate mass. Do not forget to empty the coPlot variable before you reuse it to define new plots. Or use new Variables for each figure you want to define!

If you did everything right you should receive the following two figures:

If the second figure contains plots from the first figure then you reuused the coPlot variable and did not empty it beforehand.

You can find a lot more plotting Options in the plotting subchapter of this step by step introduction! 1.4.10 Advanced Plotting

  • Keine Stichwörter

2 Kommentare

  1. Unbekannter Benutzer (ga25wes) sagt:

    matter.phases.liquid(oStore, 'PhaseName', struct('Substance',fMass), fVolume, fTemperature, fPressure);
    Unbekannter Benutzer (ga56haq) It seems like volume is no longer an accepted input for liquid phases. Got an error that I had too many input arguments  and was confused because here volume is stated. In the human model tutorial, liquid is instantiated without the fVolume input (and it works there). 
    1. Unbekannter Benutzer (ga56haq) sagt:

      Yes you are right, thank you for pointing this out. I changed the definition a while ago to standardize the phase definitions. The solid phase was also reworked to remove the ignored volume parameter. I will change this right now