stopping the indoor spread of covid-19 at 41 cooper square
Post on 02-Oct-2021
1 Views
Preview:
TRANSCRIPT
1
Stopping the Indoor Spread of COVID-19 at 41 Cooper
Square
ME-394 Capstone Senior Design Final Technical Report
Amal Bukhari, Louis Lane, Lutor Mei, Jaywon Woo
Advised by Professor Baglione, Professor Yecko and Professor Bondi
2
Contents Abstract .......................................................................................................................................................... 3
Introduction ................................................................................................................................................... 4
Approach ........................................................................................................................................................ 4
Constraints ..................................................................................................................................................... 4
Methods ......................................................................................................................................................... 4
Ventilation ................................................................................................................................................. 4
Computational Fluid Dynamics Model ...................................................................................................... 7
Mesh Construction ................................................................................................................................ 8
Furniture and Walls ............................................................................................................................... 9
Outlet ..................................................................................................................................................... 9
Inlet ........................................................................................................................................................ 9
Humans and Aerosols .......................................................................................................................... 12
Model Solving Procedure ..................................................................................................................... 13
Particle Track Post Processing ................................................................................................................. 13
Ensight.................................................................................................................................................. 13
MATLAB: Legend of the XML ............................................................................................................... 13
Decay Rate Fitting ................................................................................................................................ 14
Results ...................................................................................................................................................... 15
Future Work ............................................................................................................................................. 16
Filtration................................................................................................................................................... 18
Relative Humidity..................................................................................................................................... 24
Conclusion and Future Work ....................................................................................................................... 25
References ................................................................................................................................................... 26
Appendix I .................................................................................................................................................... 29
MATLAB Script for Diffuser SubModel Convergence Study .................................................................... 29
Particle Post Processing MATLAB Code ................................................................................................... 33
Data Processing and Plotting ............................................................................................................... 33
partcount MATLAB Function ............................................................................................................... 36
combpartcount MATLAB Function ...................................................................................................... 37
XML Parser Function ............................................................................................................................ 39
3
Abstract As members of the Cooper Union community, it is of primary importance to ensure the safety of faculty,
staff and students that need to come to campus during the pandemic. The Cooper Union has already
implemented measures including mask wearing, social distancing and weekly rapid testing to prevent
COVID-19 infections from spreading on campus. Building controls can be used to further increase safety.
The specific methods explored in this project are ventilation, air filtration and increased relative
humidity control. It was found that in-room filtration is more cost effective than increased outdoor air
ventilation, but there is a trade-off between controlling carbon dioxide levels in a space and saving
energy by depending more on filtration than ventilation.
4
Introduction The COVID-19 pandemic has shed light on how crucial it is to control indoor air quality for the sake of
occupant comfort and safety. This is motivated by evidence that the Sars-COV-2 virus can spread via
aerosolized respiratory particles that can stay in the air for prolonged periods of time [1,2,3]. As a result,
it is important to make sure air is being delivered, cleaned and conditioned to minimize incidence of
infection via this method of infection.
Approach A building’s heating, ventilation and air conditioning (HVAC) systems control indoor air quality. With
regards to the pandemic, the three specific parameters we focus on controlling are ventilation, air
filtration and relative humidity. 41 Cooper Square (41CS) is the system this project is making
recommendations for. This specific building is chosen because every building’s HVAC system has its own
intricacies. Our goal was to investigate how the general parameters of ventilation, air filtration and
relative humidity can be adjusted using 41CS’s HVAC system to maximize occupancy safety.
The effect that different ventilation rates have on a room’s airflow is modeled using computational fluid
dynamics (CFD) modeling. To decide on the appropriate ventilation rate beyond the minimum required,
a method of using CO2 to evaluate indoor air quality is investigated. Another important aspect of indoor
air quality is the particulate matter in the air, which is explored via an air quality study of the student
machine shop.
The importance of relative humidity control is substantiated via background research and the need for
increased humidification is illustrated using Building Management System (BMS) data.
Constraints The recommendations made by this project will not require any major renovations to the existing HVAC
system nor will it require significant funds to implement the changes we suggest.
Methods
Ventilation Minimum ventilation guidelines are dictated by Standard 62.1 put out by the American Society of
Heating, Refrigeration and Air-conditioning Engineers (ASHRAE). New York State Mechanical code
matches the ASHRAE Ventilation Rate Standard [4,5]. Maximum occupancies of all classrooms in 41
Cooper Square under normal building conditions reported by Dean Savizky are listed in Table 1. This
information is useful in calculating the minimum ventilation required for a space. Area of a room is also
needed to calculate minimum ventilation required and this information can be found in the building’s
design drawings. Ventilation at 41CS operates based on whether a room is occupied or not, using
occupancy sensors. For this reason, there are minimum unoccupied setpoints and minimum occupied
setpoints. When the room’s occupancy sensor detects that someone has come into the room,
ventilation increases from the unoccupied minimum to the occupied minimum and then increases
further based on temperature control. When people are in a room, they cause the space to get warmer.
In response, more ventilation air is supplied to prevent the temperature from getting too high. By using
this method, although the ventilation system cannot provide ventilation based on the number of
5
occupants, ventilation is still dependent on the level of occupancy since the more people are in a room
the hotter it will get so the space receives more ventilation.
Room number Occupancy LL101 50
LL210 27 101 30
104 32
105 36
106 20
201 14 201A 14
427 35 502 30
503 30
504 40 505 40
506 40 801 26
Table 1: Classroom maximum occupancies
However, although the level of ventilation a room receives is indirectly dependent on occupancy, this
does not take into account concerns such as CO2 levels in the space. Demand-controlled ventilation is an
alternative method of ventilation control that provides ventilation based on the number of occupants
which is determined by the level of CO2 in the space [6]. It is important to monitor CO2 in a space
because it is recognized as an indoor pollutant that can have a negative impact on occupant alertness
and decision-making at 600 ppm-1000 ppm [7]. For this reason, CO2 is used as a proxy for indoor air
quality.
Many classrooms and offices have CO2 readings shown in their BMS graphic, but these levels appeared
excessively high. When the room is empty, such as when the building is closed at night, the CO2 levels
should be near what it is to outside air. Researchers have reported that CO2 levels in NYC have an upper
bound near 500 ppm [8]. This is far below what is reported by BMS data. However, because the
monitors appeared to be working as far as detecting changes in CO2 levels, we wanted to see if there
was a way to correct this data so it could be analyzed to draw a conclusion regarding whether the level
of ventilation currently received by room 104 is sufficient. Room 104 was chosen for this investigation
because it was used often in February and March 2020 before the building was closed and continues to
be used (at a lower occupancy) as an internet café while the building is operating under pandemic
conditions.
To obtain CO2 concentration data to compare to BMS data, Onset HOBO MX1102 data loggers were
bought and installed in this classroom. It was found that the average difference over 24 hours between
the BMS data and the HOBO sensor data was about 680 ppm. 81% of the BMS data points had its offset
from the HOBO sensor data fall within one standard deviation from this average difference of 680 ppm.
6
680 ppm was then subtracted from all BMS data to correct the inflated values. The resulting plot of
corrected BMS data is shown in Figure 1.
Figure 1: Corrected BMS data showing CO2 concentration in classroom 104 under normal and reduced occupancy conditions
The conclusion drawn from the plot is that so long as the building operates under reduced occupancy
conditions it is unnecessary to increase ventilation to this classroom. According to ASHRAE Standard
62.1, the minimum required ventilation rate for room 104 is 277 cubic feet per minute (CFM) and the
room currently is set to have an occupied minimum ventilation rate of 464 CFM. Since occupancy is so
low, as the internet café is spaced to accommodate about 10 students, this level of ventilation is
effectively keeping the CO2 below the 1000 ppm benchmark. However, when the room has normal
occupancy the data from February and March 2020 shows the CO2 concentration often going above the
recommended 1000 ppm. However, it is not definitively known whether the CO2 levels really reach such
high levels because this data may not have been fully corrected. For this reason, we suggest that this
process of obtaining and monitoring CO2 levels is redone when occupancy is normal in the fall of 2021
when in-person learning is scheduled to recommence.
Some things to note include that there is already an Onset HOBO CO2 monitor already installed in
classroom 504. We did not make use of the data from that logger in this project, but since classroom
504 is used often during times of normal occupancy and has a high maximum occupancy, this would be a
good starting place for data collection in the fall. These CO2 monitors were chosen because they had a
reasonable price of about $600, were easy to install, and very convenient in terms of data collection. All
that needs to be done to download data from these monitors is to bring a mobile device with the free
HOBOmobile app installed on it near the monitor and the data is saved to an Excel file that can be
exported from the app via email. However, a drawback to using these monitors is that they need to be
recalibrated every eight days [9]. There is significant sensor drift when the monitors are allowed to
continue logging data beyond this eight-day window. While recalibration simply requires the user to
bring the monitor outside, input what the outside CO2 level is, and allow the monitor to sit outside for
7
five minutes, this is still not very convenient. Also, we do not reliably know what the CO2 levels outside
Cooper are since we did not have outdoor CO2 monitors set up to track this data. Therefore, another
suggestion for the future is to obtain a CO2 monitor to track what the outdoor concentrations are and
see how much they vary outside Cooper. This could potentially be part of a new outdoor weather
station, which the facilities team has interest in setting up. Another drawback to using these HOBO
monitors is that they do not interface with the BMS. So, a better long-term solution would be to work
with the facilities team in selecting an outdoor CO2 sensor as part of a weather station with other
devices connected to the BMS and also setting up these same BMS-compatible CO2 sensors in rooms of
interest to continuously track the CO2 concentrations in.
Computational Fluid Dynamics Model A computational fluid dynamics (CFD) case study is conducted on classroom 506 at Cooper Union’s 41
Cooper Square academic building. The case study utilizes CFD simulations to assess the effect of
ventilation rates and individual positioning on aerosol concentrations within the classroom. Masked
humans are modeled in the room to simulate the transient behavior of exhaled aerosols as they interact
with the room’s specific design, furniture, and HVAC system.
The air dynamics and fluid-particle interactions within the room are simulated using the commercial CFD
software, ANSYS Fluent. A full-scale model of the room is built, capturing the main features relevant to
the flow patterns within the room. The general geometry of the classroom model is shown in Figure 2.
The room model includes inlet diffusers, shown as green, an exhaust transfer duct, shown as red, and
commonly used furniture, shown as blue. Three humans, shown as vertical yellow objects, are also
modeled. Human A stands near the front of the room, Human B stands in the middle, and Human C
stands near the back. The following subsections describe the mesh development, boundary conditions,
solution settings, and assumptions made for these CFD models.
Figure 2: CAD Representation of Classroom CFD Model
The room geometry including the floor plan, locations, dimensions, and ceiling height were obtained
from ventilation mechanical diagrams and “as-built” ventilation shop drawings [10,11]. Dimensions not
8
included in building ventilation schematics were surveyed in person. A tape measure and a laser
distance meter were used for measuring room dimensions.
CFD models consist of a hex-core mesh containing 1.1 million elements generated in Fluent Meshing.
Turbulence within the room is modeled using a K-Epsilon Realizable Turbulence model [12]. Using the K-
Epsilon Turbulence model is deemed appropriate for the case given that the interactions between the
fluid and surfaces are not of primary focus [13]. Detailed equations can be found in the ANSYS Fluent
Theory Guide [12]. Standard wall functions are used to capture the turbulent boundary layers.
Preliminary models are used to confirm that Y+ mesh refinement is appropriate along surfaces of the
model for the sake of using a wall function [12]. For the purposes of this study, humidity is not modeled,
and dry air is the only fluid species simulated. Buoyancy effects are modeled by treating air as an
incompressible ideal gas, density changes being dependent only on temperature and not on local
pressure fields [12]. For this material model, all default values in Fluent are used.
Mesh Construction Meshing for the classroom fluid volume is completed in Fluent Meshing and in ANSYS Meshing. The
procedure is as follows. The geometry file is imported into ANSYS Design Modeler. Within Design
Modeler, superfluous solids and surfaces are suppressed. Face-Split and Projection tools are used in
order to divide volume boundary surfaces into walls, outlets, and inlet faces. Additionally, share
topology is enabled in order to create a continuous mesh between separately imported fluid regions.
Segregation of the fluid volume is conducted in CAD for several reasons. Dividing the fluid volume can
promote more efficient and optimal mesh construction – especially when implementing a mapped
mesh. Additionally, borders between volumes can be specified to be thin walls/surfaces. This allows for
walls to be modeled as two-dimensional objects. Mesh interfaces were considered when producing
mapped meshes. Ultimately, they were not used due to the burden of correctly implementing them
within the software and their reduction in computational efficiency.
Design Modeler files are then imported into ANSYS Meshing to be assigned named-selection boundaries
and cell volumes. For producing a hex-core mesh, geometry files are written out of ANSYS Meshing and
then imported into Fluent Meshing. Subsequent settings in Fluent Meshing are set to produce a mesh of
sufficient adherence to mesh element quality metrics. Boundary layer elements are created for y+
refinement for the usage of standard wall functions. Poly-hex core meshes were originally generated for
these CFD simulations. However, the utilization of poly elements was considered superfluous for
discretizing the geometries within these models. A sample view of a hex-core mesh is shown in Figure 3.
This view displays boundary elements, transitionary tetrahedral elements, and interior hex elements. In
areas of refinement, additional buffer element layers can also be observed.
9
Figure 3: Fluent Meshing Cross-Sectional View of Hex-Core Mesh
Furniture and Walls The locations and overall dimensions of the furniture within the room were obtained by direct
measurements made in person. Several simplifications are made to the furniture featured within the
model. Small, isolated regions of air within the room are neglected along with other small physical
entities that are assumed to have a negligible effect on the larger scale fluid dynamics within the room.
Accordingly, table legs and thickness are not modeled; tables are treated as perfectly thin surfaces
suspended in the air at their respective heights. The layout of tables and desks for future semesters is
currently unknown. For this model, the tables are assumed to be in a seating arrangement typical of
previous semesters. Walls and furniture surfaces are modeled as thermodynamically adiabatic surfaces
by assigning a zero heat flux condition to them [14].
Outlet The location and specific orientation of the exhaust duct within the room is unknown. The exhaust duct
is situated above the perforated paneling found on the classroom ceiling. Due to the inaccessibility of
the exhaust, many physical characteristics of the exhaust remain unknown. The placement of the outlet
is therefore based on scaled shop drawings [11]. The outlet is modeled as a single face of documented
cross-sectional duct area. The effect of the perforated paneling along with the specific orientation of the
outlet is neglected. This is under the assumption that the modeling of these features, or lack thereof,
will not produce a discernable change to the flow behavior beyond the fluid region local to the outlet.
With respect to the CFD model, the exhaust duct is modeled as a pressure outlet boundary. The
boundary condition is assigned a value of 101.325 kPa.
Inlet
The ventilation into the room consists of air flow from a single air handling unit connected by flexible
ductwork to three TITUS TBDI-30 linear slot diffusers [10]. Air handling units that serve classrooms
deliver 100% outside air without any recirculating from spaces within the building. Therefore, for this
10
model, air channeled into the classroom is assumed to be free of any airborne particles. The location of
each diffuser was surveyed similarly to measuring other features. Visual inspection confirms the exact
model of the diffuser as well as its installed configuration.
The unique plenum body shape and diffuser design has been found to substantially effect the nature of
the jets of air entering the room. The diffuser body is therefore simulated. Due to the inaccessibility of
the diffuser, detailed geometry of the body is estimated through scaling manufacturing diagrams [15]. A
representative CAD model of the diffuser is shown in Figure 4.
Figure 4: CAD Representation of TBDI-30 Diffuser of Length 4 ft (1.2192 m)
To minimize the computational cost of the classroom model, the diffuser body is simulated in a separate
submodel. Fluent Profiling is used to export flow velocity profiles from the submodel into the main
classroom model. A convergence study is conducted on the submodel to verify mesh independence
ensuring that the most accurate profiles are exported. For the diffuser sub model, a mapped Multizone
mesh is generated in ANSYS Meshing. An exemplary mapped mesh is shown in Figure 5. A mapped mesh
was favored due to the diffuser geometry being of constant cross-sectional geometry. The mesh
refinement is increased near the outlet of the diffuser. Element sizing settings are adjusted to produce
the different cell counts found in the diffuser convergence test.
11
Figure 5: ANSYS Meshing View of Diffuser Mesh (~16 million elements total)
Results from this convergence study are shown in Figure 6. To produce these results, outlet solution
data is written in ASCII format from Fluent. The ASCII Data is then read into a MATLAB script which finds
the aggregate profile of the data points through a poly-fit function. The maximum velocity of the profile
– which was determined to be representative of all other points along the data curve – is compared
across models with different mesh refinements. The MATLAB script can be found in Appendix I. From
these results, a mesh refinement of 5 million is chosen for simulating the diffuser model under different
air flow rates. Preliminary studies are conducted to ensure that flow behavior between a fully integrated
model and segregated models coupled by Fluent profiling yield similar results. The inlet boundaries of
the CFD model are assigned to be velocity inlets. Temperature data is taken from the Building
Management System (BMS). A value of 67℉ (19.44℃) is assigned to inlet flow as a representative
average value of inflow temperature.
12
Figure 6: Convergence Results of Diffuser Submodel
Humans and Aerosols The three humans placed within the room are modeled as rectangular figures. The rough dimensions of
each human figure are identical and are based on a 65 in (1.651m) tall volunteer subject. To consider the
heat generated by a human, and how it affects the flow within the room, surface temperatures of each
figure are assigned to be 91.4℉ (33℃) – a typical skin temperature [16]. This value is chosen as an
estimate as actual thermal behavior depends heavily on many factors including person weight, posture,
and clothing [17].
The Lagrangian Discrete Phase Model (DPM) is used to simulate aerosols in the room. The air flow within
the room is modeled as a continuous, steady flow. Unsteady Lagrangian particle tracking is coupled with
the steady flow solution to capture interactions between the particles and the continuum of air [12,14].
Particle tracking is advanced with a time step of 0.125 seconds.
The wearing of a mask significantly reduces the velocity of exhalation from talking, coughing, and other
respiratory actions[18]. Significance of breath pulses is further reduced due to their entrainment into an
individual’s thermal plume [19]. This entrainment is also encouraged by the common misfitting of
masks, which leads to a gap at the top edge [18]. For these reasons, exhaled breath is neglected.
Aerosols are introduced into the simulation with no relative velocity with an injection span of 1 in (2.54
cm) at a location approximating the mouth of an individual.
Sustained respiratory activities, such as talking and breathing, have been shown to be effective at
producing a considerable amount of aerosol-sized particles [20]. The injection rate for each individual is
set to 15 particles/sec. This value is chosen as an estimate based on studies indicating the significant
reduction in particle count attributed to mask-wearing [21,22]. The qualitative and quantitative behavior
of aerosol ejection from a mask-wearing individual is however expected to vary with an individual’s type
of mask and mask-fitting [23,24].
13
Finally, aerosols are modeled as ideal tracers within the flow. Gravitational force and inertial effects are
considered to have a very weak effect on particle dynamics at the length scale of most aerosols [25]. For
similar studies, in indoor flow, the stokes number for aerosols has been determined to be much less
than 1, confirming their fidelity as tracers of the flow streamlines [25].
Aerosols are injected for a duration of 5 minutes of respiratory activity. To analyze the clearing rates of
different ventilation settings, particle deposition is neglected [26] and particles are tracked until they are
exhausted from the room domain.
Model Solving Procedure The following procedure describes the set-up of each model. The diffuser sub model is simulated given a
certain ventilation volumetric flow rate. The outlet velocity profile is written and exported as a profile
file. This profile is then imported, oriented, and replicated across the three diffuser locations of the
classroom model. The model is run steady state until convergence is reached. Similar solver settings to
those used by HVAC industry practitioners, are used to promote the convergence of simulations. The
DPM is then enabled; particles are injected and tracked unsteadily. Solution and particle data for post-
processing – discussed in subsequent sections – is generated through calculation activities.
Particle Track Post Processing To quantitively analyze the discrete phase particle model, data must be exported from ANSYS Fluent for
post processing. Fluent offers three export formats for particle data for ANSYS Ensight, ANSYS CFD-Post,
and Fieldview. The use of Ensight and CFD-Post were explored.
Ensight ANSYS Ensight is used as a post-processing software primarily used in this study to visualize and animate
particle location data across the simulated time. Files required for Ensight post-processing, which
include geometry, fluid files, and particle track files per timestep, are all exported from solution
calculations.
MATLAB: Legend of the XML Processing and analyzing the data in CFD-Post did not offer the desired level of flexibility, or ease of use.
However, the XML data format which Fluent exports for CFD-Post is clearly structured and can be read
natively by MATLAB. MATLAB provides a sample code for importing an XML file to a MATLAB structure
format in the Help Center. Once the XML has been read, the data is in a semi-organized structure
format. While the data is properly nested in a tree format, it contains lots of empty cells, column, and is
generally difficult to work with. To read and reformat the data, a function named ‘partcount’ was
written. This function is input a Fluent Particle Track XML file, and outputs an array where each row is
the particle data as follows:
14
Variable Name Description
umintime Time elapsed in minutes.
pir Total particle count in room. relpir Relative total particle count in room (scaled based on maximum number
of particles in the room)
injection The injection number of each particle. Describes the source of each particle (front, middle, or back of room.)
Table 2: Collected variable from CFD particle tracks.
This is the most data that can be read from the particle track export without being able to decode the
base64/little endian (B64/LE) format, which the remainder of particle data is encoded in. Data locked
behind this format is particle locations, particle times, and a wealth of other parameters. More can be
read about this in the future works section.
Additionally, a function called ‘combpartcount’ was developed to take multiple particle track files from
the same simulation and process them both individually and as an aggregate. This enabled simple
processing of particle injections from three different sources simultaneously and drastically decreased
computational time.
Using these two functions, the particle data was extracted from the particle track data, and structured in
a user friendly format. This enabled rapid data processing, with flexibility unparalleled by commercial
post processing solutions.
Decay Rate Fitting To calculate the time constant of each ventilation rate, a first order exponential was fit to the particle
count data from the data peak onwards. A comparison of the exponential fit, and calculated particle
tracks can be seen in Figure 7. The first order exponential fit in MATLAB returns coefficients 𝑎 & 𝑏 for
the function 𝑦 = 𝑎𝑒𝑏𝑥. Using 𝑏, we can calculate the time constant as 𝜏 =1
𝑏.
Figure 7: Comparison of particle track data and fitted exponential.
15
Results The three ventilation rates compared using CFD modeling are based on the minimum, intermediate,
and maximum occupied flow rates specified in the BMS for classroom 506. The three ventilation models
are simulated for a total of 60 minutes in real time. The aerosols injected for 5 minutes in these models
are tracked through the room volume until they are exhausted into the transfer duct.
A 3D visualization of particles of constant color scheme is shown in Figure 8. This visualization
depicts a time of T = 10 min. Visualizing particle locations from a top-down view shows that the particles
are well-mixed across the volume of the room domain after approximately 10 minutes. This behavior is
observed in all three ventilation rates modeled. In these three cases, initially concentrated streams of
aerosols from all three persons are observed to become uniformly distributed across the room after
approximately 10 minutes of simulated time. This visualization affirms the need for safety measures
beyond social distancing.
Figure 8: 3D Visualization of Aerosols (t = 10 min, 275 CFM (1.73 ACH, 129.8 L/s) case)
For each case, the total number of particles remaining in the room, not exhausted, are recorded
every 30 seconds. The resulting data curves are shown superimposed onto one graph in Figure 9. Results
indicate that in all cases, maximum particle counts are achieved at 5 minutes, the end of injection time.
All curves also display exponential behavior – asymptotically decaying towards a value of 0 particles.
Increasing ventilation rates is shown to have an exponential decrease in particles remaining in the room
at a given time. Furthermore, the maximum aerosol count within the room is reduced with a higher
ventilation rate.
16
Figure 9: Particle Count Comparison for three Ventilation Rates
The decay behavior of particle count for each ventilation rate is studied in further detail. A first-
order exponential function is fit to the decaying portion of the data curves shown in Figure 7. The time
constant of each ventilation rate is shown in Table 3. The results from comparing three cases indicate
that the time constant of exponential particle count decay follows a linear dependence on ventilation
rate.
Ventilation Rate (CFM ;
L/s)
Air Changes
Per Hour
Time Constant
(min)
95% Confidence
Interval
275 ; 130 1.7 34.130 [34.060, 34.235]
750 ; 354 4.7 13.643 [13.300, 14.004]
1200 ; 566 7.6 7.710 [7.457, 7.981] Table 3: Curve-Fit Determined Time Constants for each Ventilation Rate
Future Work
The validity and weight of the simulation results should be considered under the conditions in which
they are produced. Significant simplifications and reductive assumptions are made to this model to
improve computational efficiency. Key areas of further development are discussed in this section. This
future work discussion is split into two sub sections. The first section primarily focuses on efforts to
improve the fidelity of the computational models produced. The second section focuses on areas in
which the work can be further developed.
The simplification to neglect exhaled breath due to mask wearing conditions is made in order to
optimize simulation time. However, doing so significantly simplifies the flow behavior local to the human
body. Aerosol dispersion and exhalation velocity must be taken into account in future models.
Furthermore, many turbulent flow features are neglected within this model. Because the model is run
steady state, anticipated unsteady flow behavior – local to the human heat plumes as well as the overall
17
flow volume – is not modeled. These flow disturbances – large and small scale – are most likely to have
an effect on the transient aerosol dispersion across the room. Modeling them may affect particle
exhaust rates as well as the time scale in which highly concentrated breath pulses become well-mixed
throughout the room. Further work should be completed on considering the effects of inertia and
buoyancy on the aerosols modeled. Additionally, humidity and evaporative effects can be modeled to
improve the fidelity of particle behavior. Above all else, experimental studies should be used to validate
the results of these CFD models.
The current CFD case study makes assumptions on the room geometry. Future models can include
considering different locations of furniture and persons situated within the room. Additionally, longer
durations of particle injections should be implemented such that more sustained respiratory behavior
can be modeled. Furthermore, communication with administration can allow for exact prospective
classroom configurations, seating arrangements, and occupancy levels to be modeled. Current flow rate
to decay time constant results are based off of three ventilation flow rates. In order to more accurately
determine the form dependency of the decay time constant on flow rates, additional ventilation flow
rates should be modeled. With prospective post-processing techniques, additional quantitative and
qualitative measures can be placed on particle tracking. Concentration heat maps can be considered to
study any focused particle distributions within the room. This can be done to study the asymmetries of
the room with respect to the floor plan. Heat maps can also provide insight into the vertical distribution
of particles to assess the effect of thermal buoyancy on particle dispersion.
Decoding Additional XML Data
A key step in improving the post processing of the CFD results is to make better use of the particle track
data. This is largely limited by the capability of decoding the Base 64/Little Endian data format which
much of the particle data is encoded in.
The B64/LE encoding allows a computer processor to rapidly read and write data to a file which does not
need to be read by a human. This is very effective if you are creating a file that is going from one
proprietary software to another, such as Fluent to CFD-Post. However, if you need additional flexibility
beyond the features of the software suite, the B64/LE format presents a technical challenge of first
simply being able to decode the data into an understandable base 10 format, and secondly doing so
computationally efficiently.
To better understand the challenge, we need to understand what Base64/Little Endian. The base 64 is
simply, the value is stored in a base 64 format. For example, [64, 128, 256] can be represented as [vnz].
Then we need to apply a little-endian encoding to it, which is less an encoding, and instead the order of
bytes which a computer process the data. Little endian is simply reading characters, in pairs, in reverse.
If a pair cannot be completed (odd number of characters) a 0 is used to fill the incomplete pair.
18
Figure 10: Fluent XML export data encoding format (Base64/Little Endian)
While this data encoding is relatively simple, MATLAB can convert between base 10 and base 64 with
relative ease, the challenge comes from reading the little-endian data. MATLAB has a 64-character limit
for functions of strings so data must first be broken down into a different format to be switched to big-
endian before conversion to base 10. Separating the string piecewise into character string pairs in cells
was attempted but did not yield comprehensible results.
Having this data in MATLAB would enable complex analysis of the particle tracks to be processed,
allowing heatmaps of particle concentrations to be created, or a light-weight quantitative analysis of
particle position data.
Filtration Levels of particulate matter in the air are another important aspect of indoor air quality. To quantify
how effective in room filtration is in reducing the concentration of particles in the air, in-room air
cleaners that use HEPA filters were deployed in the student machine shop (LL219). The student machine
shop was chosen because it is one of the few consistently occupied spaces. The air quality likely should
be monitored since the work done there produces air pollution, and since there is likely a significant
level of particulate matter in the air we would most easily be able to see a change in the concentration
of particles as we make changes to how the room’s air is being cleaned. First, we made measurements
of the room’s particulate matter without any changes to ventilation or filtration. Next, we deployed 2 in-
room air cleaners. The air cleaners were chosen based on a recommendation given to us by Professor
Baglione. Two air cleaners were used because the largest sized air cleaner available was sized for 500
square feet. Upon calling the manufacturer to inquire into whether a larger size was available, they
informed us this was the largest size but that most customers who were trying to buy air cleaners for a
larger space would just buy more than one. Since the machine shop is 1190 square feet 2 air cleaners
were bought. Note that the machine shop is larger than the 1000 square feet that these air cleaners are
stated as able to cover, but we assumed it would be sufficient coverage considering that a portion of the
square footage of the machine shop is occupied by projects and other machinery.
The particle counter used in this study measures particles in two ranges: 0.5 microns and larger referred
to as “small”, and 2.5 microns and larger, referred to as “large”. These readings are reported in terms of
12345678
A B C D
78563412
D C B A
“Big Endian” “Little Endian” Read order is
A, B, C, D
64, 128, 256
Base 10 Data
vnz
Base 64 Data Base 64/Little Endian
0zvn
19
particle count per cubic foot. Note that such readings may not be comparable to other measures of air
quality or particulate matter. The Air Quality Index, which is commonly provided to the public along with
weather reports, is given as a value between 0 and 500. This value is calculated in part by using PM10
and PM2.5, categories of particulate matter. Some air quality monitors record measurements using
these categories, and such measurements are in units of micrograms per cubic meter.
The initial case represents measurements taken when no in room air cleaners were used an ventilation
was at its normal supply minimum of 400 CFM (or 2 ACH) of outside air. Please note that the reported
supply CFM is the amount of outside air mechanically delivered to the space via air handling unit 1
(AHU1). Because the machine shop, like every other lab, is under negative pressure the total CFM
coming into the room is the amount of outside air delivered by AHU1 plus the amount of transfer air
coming into the shop from the hallway. The amount of transfer air coming in is equal to the exhaust
minus the supply from AHU1.
Since the room’s control sequence prioritizes the maintenance of the differential pressure setpoint, the
amount of the total supply coming into the room via AHU1 cannot be changed directly by only changing
the maximum supply setpoint. Based on what the exhaust is, the supply will increase or decrease to
maintain the differential pressure setpoint. The setpoints displayed by the BMS graphic for this room are
shown in Figure 11.
Figure 11: General supply and exhaust setpoints as displayed by the BMS for the student machine shop prior to changes being made.
Please note that the graphic displays each component of the total exhaust: the general exhaust, the
fume hood and the point exhaust separately. The total exhaust point shown at the top is the addition of
these three sources of exhaust.
To make it so we would always be supplying a certain constant increased amount of outside air via the
AHU, the general exhaust minimum and maximum setpoint were set to be essentially equal so that the
room’s total supply would have to be constant. To make it so the outside air supply from the AHU would
be constant, the supply minimum and maximum were also set to be nearly equal and were chosen to be
equal to the total exhaust minus the differential setpoint. Therefore, the outside air supply was
20
constrained to be constant at the new value the minimum and maximum were changed to. Table 4
shows the values for the ventilation setpoints before and after the changes were made and Figure 12
shows the BMS graphic displaying the machine shop with its new setpoints.
Figure 12: General supply and exhaust setpoints as displayed by the BMS for the student machine shop prior to changes being made.
Name of Setpoint Original setpoint (CFM) Adjusted Setpoint(CFM) min AHU1 supply 400 980 max AHU1 supply 600 990 min general exhaust 576 1189 max general exhaust 1100 1190 Differential setpoint 200 200
Table 4: Student machine shop ventilation setpoints before and after adjustments were made.
The two air cleaners were placed in the machine shop based on availability of space and proximity to an
electrical outlet. Similarly, the particle counter was placed on unused workbench space to avoid
disrupting project work in the machine shop. Each session of recording data lasted for approximately
four hours. During this time, information on activity and occupancy within the shop was recorded so
that patterns or irregularities in the data, such as sudden increases in particle counts, could be
accounted for. Sessions were conducted on Mondays and Wednesdays, as these were the days that the
machine shop was open. For each condition – for example, keeping the air cleaners on for the duration
of the session – data were recorded on both Monday and Wednesday so that days of more similar
activity could be compared and presented in the final results. However, due to time constraints, only
one session of data was recorded for increased ventilation only. Also, shop activity and occupancy were
not recorded for that one session so the rapid increase in particle count that occurred about 45 minutes
into the session remains unexplained.
21
Figure 13: Small particle counts in machine shop under varying conditions
Figure 14: Large particle counts in machine shop under varying conditions
Results of the machine shop air quality study are shown in Figures 13 and 14. Air quality ranges as
shown in Figure 13 were provided with the air quality monitor. Air quality ranges for the large particle
counts were not provided. During these sessions, measurements of relative humidity, temperature, and
carbon dioxide concentrations were also taken. As expected, filtration had no effect on these values so
the data are not shown. The improvement to air quality produced by increased ventilation for the first
45 minutes of its session is similar to the improvement produced by filtration, so a cost analysis was
performed to evaluate the two strategies in terms of cost effectiveness.
22
The equations used to carry out the approximate cost analysis to estimate whether increasing
ventilation or increasing filtration is cheaper are shown below and are explained in John Han’s thesis
[27].
𝑐𝑜𝑠𝑡ℎ𝑡𝑔 [$
𝐶𝐹𝑀∗𝑦𝑟] = ℎ𝑑𝑑 [
℉∗𝐷𝑎𝑦
𝑦𝑟] ∗
1.08𝐵𝑡𝑢
ℎ𝑟∗𝐶𝐹𝑀∗℉∗ [
$ 𝑛𝑎𝑡.𝑔𝑎𝑠
𝑡ℎ𝑒𝑟𝑚] ∗
1
𝜂𝑏𝑜𝑖𝑙𝑒𝑟∗
24ℎ𝑟
𝑑𝑎𝑦∗
1𝑡ℎ𝑒𝑟𝑚
105𝐵𝑡𝑢 (1)
𝑐𝑜𝑠𝑡𝑐𝑙𝑔 [$
𝐶𝐹𝑀∗𝑦𝑟] = 𝑐𝑑𝑑 [
℉∗𝐷𝑎𝑦
𝑦𝑟] ∗
1.08𝐵𝑡𝑢
ℎ𝑟∗𝐶𝐹𝑀∗℉∗ [
$
𝑘𝑊ℎ] ∗
24ℎ𝑟
𝑑𝑎𝑦∗
3.41∗10−3𝑘𝑊ℎ
𝐵𝑡𝑢∗
1
𝐶𝑂𝑃 (2)
𝑐𝑜𝑠𝑡𝑚𝑣𝑔 [$
𝐶𝐹𝑀∗𝑦𝑟] = [
$
𝑘𝑊ℎ] ∗
2765𝑃𝑎
11.1′′𝑤.𝑔.∗
1𝐻𝑃
𝐶𝐹𝑀
1580000𝑃𝑎∗ 𝑓𝑎𝑛𝑆𝑃[′′𝑤. 𝑔. ] ∗
0.746𝑘𝑊
𝐻𝑃∗
8760ℎ𝑟
𝑦𝑟 (3)
The cost of heating in units of dollars per CFM per year is found using Equation (1), where HDD is
heating degree days in units of day multiplied by degree Fahrenheit per year, 1.08 is a constant in units
of Btu per hour per CFM per degrees Fahrenheit, $
therm is the cost of natural gas per therm, ηboiler is
boiler efficiency as a decimal, 24 is a conversion from hours to days and 1
105 is a conversion from therms
to Btu. The cost of cooling is found using Equation (2), where CDD is cooling degree days, 1.08 and 24
are the same constants as in Equation (1), $
kWh is the cost of electricity in dollars per kilowatt hour, and
0.00341 is a constant with units of kWh per Btu. The cost of moving the air is found using Equation (3),
where $
kWh is the same as in Equation (2), fanSP is the static pressure of the air handling unit fan in wg,
0.0001176 is a constant with units of kW per CFM per wg, and 8760 is a conversion from hours to years.
The cost of heating, cooling and moving fluid was added up and then a factor of 0.25 was added to
account for the cost of humidity control. This 25% humidity control factor is an estimate to account for
humidity control costs not being otherwise included in the calculation, so it may be an underestimate of
the actual annual cost of humidity control. After inputting the number of heating and cooling degree
days of 2020 reported by NYSERDA, 2020 energy rates, and the static pressure from air handling unit
three, which serves classrooms and offices, cost was found to be about $7.40 per CFM per year.
To draw a meaningful comparison between the cost of increasing ventilation in classrooms versus
buying, operating and maintaining in-room air cleaners, an approximate cost analysis was done. The
annual cost of increasing the ventilation rate in all classrooms by 1 ACH was found to be about $13,500.
1 ACH was chosen just as an example of an amount of extra ventilation that operators can choose to
supply, since all rooms in 41CS already receive the required minimum CFM. This was compared to the
cost of implementing in-room air cleaners in all the classrooms. This considered the initial cost of
purchasing one or more air cleaners for each room, the cost of replacing the filters the air cleaners use
as often as recommended by the manufacturer, and the cost of the electricity powering the air cleaners.
The number and size of the air cleaners were fit as close as possible to each classroom’s floor area. For
example, classroom 104 has an area of 931 square feet, which corresponds approximately to the area
that can be covered by 2 large air cleaners each sized for 465 square feet. The size of the air cleaner also
impacts the cost, since the larger the air cleaner, the more expensive the first cost is and the more
replacement filters need to be purchased annually. However, for simplicity it was assumed that no
23
matter the size of the air cleaner the power it draws is a constant 29W. This value was obtained by
using a watt meter connected to the air cleaners used in the machine shop, which are the largest sized
air cleaners considered in this analysis. As suggested earlier in this report, if a more sophisticated
wattmeter that could store data is used, this assumption of constant energy consumption could be
corrected in the future. It was also assumed that the air cleaners would be operating for 8 hours a day,
five days a week, for 16 weeks for each of two semesters, for a total of 1280 hours.
It was found that the annual cost to maintain and operate air cleaners for all the classrooms annually is
about $3,100 with a first cost of about $6280. Compared to the annual cost of increasing ventilation by 1
ACH, the annual cost of maintaining and powering air cleaners is about $10,000 less. However, to take
into account the significant initial cost of purchasing the air cleaners the simple payback period was
found by dividing first cost by annual savings. In this case, it is a little over 7 months. When the same
analysis is carried out for offices the simple payback period is about a year and seven months. The cost
of increasing ventilation by 1 ACH in all offices was approximated to be $13,400, which is near to the
cost for increasing classroom ventilation by the same amount. The cost of operating and maintaining the
air cleaners in offices was about $6600 with a first cost of $11,000, both costs are significantly higher
than for classrooms partly because there are more offices than classrooms in 41CS.
24
Relative Humidity The ASHRAE Building Readiness Guide advises relative humidity to be kept between 40 and 60% to
reduce the ability of any viral particles in the air to successfully infect someone [28]. However, this
appears to be based on research done on the survival of Influenza A [29]. Since the ASHRAE guidance
was put out in Spring 2020, more COVID-19 specific research put out shows that there is no evidence
that the specific 60% relative humidity applies to COVID-19. Instead, research suggests that the higher
the relative humidity the better. Of course, this does not mean that we suggest relative humidity be
purposely controlled to be excessively high. As shown in the plot of relative humidity in Figure 15 below,
relative humidity in August does reach a maximum of 82%, but because the relative humidity does not
reach 80% or above for sustained periods of time, it is unlikely that mold growth should occur [30]. The
average relative humidity in August was 60.5%, which is comfortably above the 40% lower limit marked
on Figure 15 and not high enough to threaten mold growth. 40% is proposed as the value to aim to stay
above because how the mucous membranes react to dry air makes people more susceptible to infection
[31,32,33].
Since based on weather data [34] August has historically been the most humid month over the last ten
years, outside air is being sufficiently dehumidified, excluding the few occasions when relative humidity
occasionally reaches 80% and higher. However, the relative humidity data from January shows that
humidification is needed in the winter. January was chosen because it has historically been the least
humid months over the last ten years. The average relative humidity achieved in room 501 in January
was about 20% with a minimum of 9%. The need for humidification in the winter is clear. The best long-
term solution for occupant safety and comfort is to repair air handling unit humidifiers. However, if this
cannot be executed due to budget constraints, a lower cost solution could be to buy space humidifiers.
How much money would really be saved by opting for space humidifiers is left to be done in the fall if
occupancy goes back to normal and the air handling unit humidifiers are not fixed by then.
Figure 15: Relative humidity in room 501 plotted over the months of January and August.
25
Conclusion and Future Work Since this project was done while the building was operating under reduced occupancy, taking CO2 data
to evaluate whether ventilation rates are high enough under normal occupancy is recommended.
Obtaining reliable CO2 monitors that can be regularly recalibrated is necessary to do this. While the
approximate results of a cost analysis calculation showed that it is more cost-effective to implement in-
room air cleaners as compared to increasing ventilation by 1 ACH in all classrooms, the result for offices
is not as definitive. Since there are so many offices, the first cost of purchasing the air cleaners was
about $11,000. So, if there is concern about whether offices have clean enough air, useful future work
could include identifying which offices are being used most frequently and what their occupancy is when
41CS returns to in-person operations.
If air handling unit humidifiers cannot be repaired by Winter 2021, selection and purchase of space
humidifiers could be useful as a way of solving the problem in the meantime. How much money would
be saved or lost by purchasing space humidifiers for all spaces versus repairing the AHU humidifiers is
another cost analysis that could be done.
The air quality study done in the machine shop showed that air cleaners are effective in reducing
particle concentrations in the air. Since occupancy was so low, the majority of the particles being
cleaned from the machine shop air were likely put into the air by machinery in the shop. Future work
should include conducting this study in an occupied classroom to test the effectiveness of air filters
against human respiratory aerosols, in addition to gathering data in longer sessions and under various
conditions. Particle counters should be placed taking into consideration the general airflow of the room,
whether that be the machine shop or a classroom. For example, supply and exhaust ceiling vents in the
machine shop are positioned in such a way that the airflow generally enters the room from the middle,
spreads outwards, and is exhausted from the extremities of the space. Measuring particle counts near
the exhaust vent of a room should give readings more accurate to the entire space as opposed to a
single localized region within that space. A more recent model of wattmeter with accessible software
could be used to measure the power drawn by an air cleaner. The software that would have allowed
recording data on power drawn throughout the session is not available as the product website is now
defunct. The value of wattage used in cost analysis was obtained simply by reading it off the wattmeter
display. This was still a usable value as the power drawn by the air cleaners was very consistent
throughout the experiment.
26
References [1] Zhang, Renyi, Li, Yixin, Zhang, Annie L., Wang, Yuan, and Molina, Mario J. “Identifying airborne
transmission as the dominant route for the spread of COVID-19.” Proceedings of the Natural Academy of
the Sciences. Vol. 117 No. 26 (2020): pp. 14857-14863. https://doi.org/10.1073/pnas.2009637117
[2] Borak, Jonathan. “Airborne transmission of COVID-19.” Occupational Medicine. Vol. 70 No. 5 (2020):
pp. 297-299. https://doi.org/10.1093/occmed/kqaa080
[3] Morawska, Lidia and Milton, Donald K. “It is time to address Airborne transmission of Coronavirus
2019 (COVID 19).” Clinical Infectious Diseases. Vol. 71 No. 9 (2020): pp. 2311 -2313.
https://doi.org/10.1093/cid/ciaa939
[4] ASHRAE. “Ventilation for Acceptable Indoor Air Quality.” ANSI/ASHRAE Standard 62.1-2019. (2019)
[5] International Code Council, Inc. & New York State Department of State, "2020 Mechanical Code of
New York State," November 2019.
https://www.dos.ny.gov/dcea/pdf/pdf/2020%20MCNYS%20November%202019.pdf. [Accessed
November 2020]
[6] ASHRAE. “High-Performance Sequences of Operation for HVAC Systems.” ASHRAE Standard 36-2018.
(2018)
[7] Satish, Usha, Mendell, Mark J., Shekhar, Krishnamurthy, Hotchi, Toshifumi, Sullivan, Douglas,
Streufert, Siegfried, and Fisk, William J. “Is CO2 an indoor pollutant? Direct effects of low-to-moderate
CO2 concentrations on human decision-making performance.” Environmental Health Perspectives. Vol.
120 No. 12 (2012): pp 1671-1677. https://doi.org/10.1289/ehp.1104789
[8] Krajick, Kevin. “The Shutdown is Clearing New York’s Air.” March 25,2020,
(news.climate.columbia.edu)
[9] ONSET. “HOBO MX CO2 Logger (MX1102A) Manual.” (www.onsetcomp.com)
[10] Jonathan Rose Co., LLC and Morphosis. “Heating and Cooling System Layout Fifth Floor.” The Cooper Union, New York, New York. 2008 [11] Method Architects. “Fifth Floor Sheet Metal Drawing.” The Cooper Union, New York, New York. 2010 [12] ANSYS, INC. “ANSYS Fluent 2021 R1 Theory Guide.” 2021 [13] Rahman, Iram. “Computational Fluid Dynamics Tutorial: Modelling Airflow in Hospital Operating Rooms using ANSYS Fluent.” The Cooper Union, New York, New York. 2019 [14] ANSYS, INC. “ANSYS Fluent 2021 R1 User’s Guide.” 2021 [15] Titus, “TBDI-30: Adjustable Plenum Slot Diffuser.” 2019. https://www.titus-hvac.com/Products/Diffusers/TBDI-30 [16] “Understanding Human Body Temperature in Infrared Readings.” Med-Hot , May 19, 2020. https://med-hot.com/measuring-infrared-temperature/#:~:text=The%20normal%20temperature%20of%20skin,surrounding%20air%2C%20regardless%20of%20wind.
27
[17] Bhagat, Rajesh K., Wykes, M. S. Davies, Dalziel, Stuart B., and Linden, P. F.. “Effects of Ventilation on the Indoor Spread of COVID-19.” Journal of Fluid Mechanics vol. 903 (2020). https://doi.org/10.1017/jfm.2020.720. [18] Dbouk, Talib, and Drikakis, Dimitris. “On Respiratory Droplets and Face Masks.” Physics of Fluids vol. 32, no. 6 (2020). https://doi.org/10.1063/5.0015044. [19] Gena, Amayu W., Voelker, Conrad, and Settles, Gary S.. “Qualitative and Quantitative Schlieren Optical Measurement of the Human Thermal Plume.” Indoor Air vol. 30, no. 4 (2020). https://doi.org/10.1111/ina.12674. [20] Jarvis, Michael C. “Aerosol Transmission of SARS-CoV-2: Physical Principles and Implications.” Frontiers in Public Health. vol. 8 (2020). https://doi.org/10.3389/fpubh.2020.590041. [21] Fischer, Emma P., Fischer, Martin C., Grass, David, Henrion, Isaac, Warren, Warren S., and Westman, Eric. “Low-Cost Measurement of Facemask Efficacy for Filtering Expelled Droplets during Speech.” American Association for the Advancement of Science vol. 6, no. 36 (2020). https://doi.org/10.1101/2020.06.19.20132969. [22] Asadi, Sima, Cappa, Christopher D., Barreda, Santiago, Wexler, Anthony S., Bouvier, Nicole M., and Ristenpart, William D.. “Efficacy of Masks and Face Coverings in Controlling Outward Aerosol Particle Emission from Expiratory Activities.” Nature vol. 10, no. 1 (2020). https://doi.org/10.1038/s41598-020-72798-7. [23] Tcharkhtchi, Abbas, Abbasnezhad, Navideh., Seydani, Mohammad Zarbini, Zirak, Nader, Farzaneh, S., and Shirinbayan, Mohammadali. “An Overview of Filtration Efficiency through the Masks: Mechanisms of the Aerosols Penetration.” Bioactive Materials vol. 6, no. 1 (2021). https://doi.org/10.1016/j.bioactmat.2020.08.002. [24] Konda, Abhiteja, Prakash, Abhinav, Moss, Gregory A., Schmoldt, Michael, Grant, Gregory
D., and Guha, Supratik. “Aerosol Filtration Efficiency of Common Fabrics Used in Respiratory
Cloth Masks.” ACS Nano vol. 14, no. 5 (2020). https://doi.org/10.1021/acsnano.0c03252.
[25] Vuorinen, Ville, Aarnio, Mia, Alava, Mikko, Alopaeus, Ville, Atanasova, Nina, Auvinen,
Mikko, and Balasubramanian, Nallannan, et al. “Modelling Aerosol Transport and Virus
Exposure with Numerical Simulations in Relation to SARS-CoV-2 Transmission by Inhalation
Indoors.” Safety Science vol. 130 (2020). https://doi.org/10.1016/j.ssci.2020.104866.
[26] Zhang, Z., and Chen, Qingyan.. “Experimental Measurements and Numerical Simulations of
Particle Transport and Distribution in Ventilated Rooms.” Atmospheric Environment vol .40, no.
18 (2006). https://doi.org/10.1016/j.atmosenv.2006.01.014.
[27] Han, John, “Laboratory ventilation energy conservation methods,” Master of Engineering thesis,
Cooper Union, New York, NY.
[28] ASHRAE. “Building Readiness.” November 12, 2020, Building Readiness (ashrae.org).
[29] ASHRAE. “Reopening of Schools and Universities.” August 20, 2020, (ashrae.org)
[30] Riordan, Frank and Tsongas, G.A.,“Minimum Conditions for Visible Mold Growth,” ASHRAE Journal,
Vol. 58 No.9 (2016) pp. 32-43.
[31] Spena, Angelo, Palombi, Leonardo, Corcione, Massimo, Carestia, Mariachiara, and Spena,Vincenzo
A., “On the optimal indoor air conditions for SARS-CoV-2 Inactivation. An Enthalpy Based Approach,”
Intl. J. Environ. Res. Public Health, Vol. 17 No.17 (2020) https://doi.org/10.3390/ijerph17176083
28
[32] Woloff, Peder and Kjægaard, Soren K., “The dichotomy of relative humidity on indoor air quality,”
2007, Environment International, Vol.33 No. 6 (2007) pp.850-857,
https://doi.org/10.1016/j.envint.2007.04.004
[33] Ahlawat, Ajit, Wiedensohler, Alfred and Mishra, Sumit K., Aerosol and Air Quality Research, Vol. 20
No. 1(2020) pp. 1856-1861. https://doi.org/10.4209/aaqr.2020.06.0302
[34] Weather Underground, “New York City, NY Weather History,” May 8, 2021, (wunderground.com)
29
Appendix I
MATLAB Script for Diffuser SubModel Convergence Study clc; clear all; close all;
fileID = fopen('16mil_far2.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
M(5) = spliney(C);
fileID = fopen('10mil_far.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
M(4) = spliney(C);
fileID = fopen('commit_1_faroutlet.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
M(3) = spliney(C);
fileID = fopen('1mill_far.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
M(2) = spliney(C);
fileID = fopen('500k_far.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
M(1) = spliney(C);
figure();
mesh = [5e5 1e6 5e6 10e6 16e6];
plot(mesh,M,'-o', 'MarkerIndices',1:length(M),'Linewidth',1.25);
set(gca,'Fontsize',15);
xlabel('Mesh Element Count','Fontsize',25);
ylabel('Maximum Velocity [m/s]','Fontsize',25);
ylim([3 4.5]);
xlim([0 18e6]);
function max2 =spliney(C)
%% Group Counts
[t1, t2] = groupcounts(C(:,2));
Citer=1;
C = sortrows(C,2);
%plot(C(:,2),C(:,5));
%% Processing for Each Y Height
for i =1:length(t1)
xmat(i)={C(Citer:Citer+t1(i)-1,2:5)};
Citer = Citer+t1(i);
end
avgvel= zeros(length(xmat),2);
for i = 1:length(xmat)
temp12 = cell2mat(xmat(1,i));
velmagavg = sum(temp12(:,4))/length(temp12(:,4));
avgvel(i,1) = temp12(1,1);
avgvel(i,2) = velmagavg;
end
30
y = true;
i = 1;
while y == true
x = avgvel(i,2);
if x == 0
avgvel(i,:) = [];
else
i = i +1;
end
len = length(avgvel);
if i > len
y = false;
end
end
y= true;
j = 2;
ja = 1;
p = polyfit(avgvel(:,1),avgvel(:,2).*3.28,8);
y1 = polyval(p,avgvel(:,1));
%plot(avgvel(:,1),y1);
hold on;
p1 = polyfit(C(:,2),C(:,5),8);
y2 = polyval(p1,C(:,2));
max2 = max(y2);
% plot(C(:,2).*39.3701,y2,'Linewidth',1.5);
%plot(avgvel(:,1),avgvel(:,2).*3.28);
hold on;
end
%{
fileID = fopen('1mill_far.txt','rt');
formatSpec = '%f32 %f32 %f32 %f32 %f32 %f32';
sizeA = [5 1];
A = textscan(fileID, formatSpec);
fclose(fileID);
C = cell2mat(A(1,1:5));
%% Group Counts
[t1, t2] = groupcounts(C(:,2));
Citer=1;
C = sortrows(C,2);
%plot(C(:,2),C(:,5));
%% Processing for Each Y Height
for i =1:length(t1)
xmat(i)={C(Citer:Citer+t1(i)-1,2:5)};
Citer = Citer+t1(i);
end
avgvel= zeros(length(xmat),2);
for i = 1:length(xmat)
temp12 = cell2mat(xmat(1,i));
velmagavg = sum(temp12(:,4))/length(temp12(:,4));
avgvel(i,1) = temp12(1,1);
avgvel(i,2) = velmagavg;
end
y = true;
i = 1;
while y == true
x = avgvel(i,2);
if x == 0
avgvel(i,:) = [];
else
31
i = i +1;
end
len = length(avgvel);
if i > len
y = false;
end
end
y= true;
j = 2;
ja = 1;
while y == true
xmid = avgvel(j,2);
xlow = avgvel(j-1,2);
bam1(ja) = abs(xmid-xlow);
if abs(xmid-xlow)>10
avgvel(j,:) = [];
else
j = j+1;
end
len = length(avgvel);
if j > len
y = false;
end
ja= ja+1;
end
p = polyfit(avgvel(:,1),avgvel(:,2).*3.28,8);
y1 = polyval(p,avgvel(:,1));
%plot(avgvel(:,1),y1);
hold on;
p1 = polyfit(C(:,2),C(:,5).*3.28,8);
y2 = polyval(p1,C(:,2));
plot(C(:,2),y2);
%plot(avgvel(:,1),avgvel(:,2).*3.28);
ylim([0 15])
%{
for i = 1:length(xmat)
xmat(1,i)
end
ydivspec = 10;
ydivfd = 10;
yspec = 1/100; %cm
ytot = length(t1);
yspecp1 = floor(ytot*yspec);
yspecp2=floor( ytot*(1-yspec));
yiter1 = floor(yspecp1/ydivspec);
yiter2 = floor((yspecp2-yspecp1)/ydivfd);
yiter3 = floor((length(t1)-yspecp2)/ydivspec);
for i = 1: yspecp1
if rem(i,yiter1) ==0
ymat(countmat,1) = xmat(i);
countmat=countmat+1;
end
end
ymat(1) = xmat(1);
ymat(countmat)=xmat(yspecp1);
countmat=countmat+1;
for i = yspecp1+1: yspecp2
if rem(i-yspecp1,yiter2) ==0
ymat(countmat,1) = xmat(i);
countmat=countmat+1;
32
end
end
ymat(countmat)=xmat(yspecp2);
countmat=countmat+1;
for i = yspecp2+1:length(t1)
if rem(i-yspecp2,yiter3) ==0
ymat(countmat,1) = xmat(i);
countmat=countmat+1;
end
end
output = cell2mat(ymat);
filename = 'postprocess.xlsx';
writematrix(output,filename);
%}
%}
33
Particle Post Processing MATLAB Code
Data Processing and Plotting %% Fluent XML Data Processing
% Louis Lane
% COVID Mitigation - ME Senior Project 2021
clc, clear all, close all
%% 275 CFM
CFM275_1back = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\275CFMThermal\Run1\back.xml';
CFM275_1lecturer = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\275CFMThermal\Run1\front.xml';
CFM275_1mid = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\275CFMThermal\Run1\mid.xml';
[back275_1, lec275_1, mid275_1, agg275_1] = combpartcount(CFM275_1back, CFM275_1lecturer,
CFM275_1mid);
%% 750 CFM
CFM750_1back = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\750CFMThermal\particle-b.xml';
CFM750_1lecturer = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\750CFMThermal\particle-f.xml';
CFM750_1mid = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\750CFMThermal\particle-m.xml';
[back750_1, lec750_1, mid750_1, agg750_1] = combpartcount(CFM750_1back, CFM750_1lecturer,
CFM750_1mid);
%% 1200 CFM
CFM1200_1back = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\1200CFMThermal\back.xml';
CFM1200_1lecturer = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\1200CFMThermal\front.xml';
CFM1200_1mid = 'C:\Users\lanel\Downloads\Thermal Models Louis\Thermal
Models\1200CFMThermal\mid.xml';
[back1200_1, lec1200_1, mid1200_1, agg1200_1] = combpartcount(CFM1200_1back, CFM1200_1lecturer,
CFM1200_1mid);
clear CFM1200_2agg CFM1200_1agg CFM275_1back CFM275_1lecturer CFM275_1mid CFM275_2agg
CFM750_1back CFM750_1lecturer CFM750_1mid CFM750_2agg
%% SAVE VARIABLES
save ThermalComparison.mat back1200_1 lec1200_1 mid1200_1 agg1200_1 back750_1 lec750_1 mid750_1
agg750_1 back275_1 lec275_1 mid275_1 agg275_1
%% CFM Comparison
axlabelfont = {'FontSize', 25};
mainfontsize = 15;
tickfont = {'FontSize', mainfontsize};
lgdfont = 20;
% Plot the aggregate/mean particle count for each CFM vs each other.
figure()
plot(agg275_1(1,:), agg275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1);
hold on
plot(agg750_1(1,:), agg750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1);
plot(agg1200_1(1,:), agg1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1);
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('275 CFM (1.7 ACH, 129 L/s)', '750 CFM (4.7 ACH , 354 L/s)', '1200 CFM (7.5 ACH, 566
L/s)');
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, 'CFMComparison.png')
%% Constant CFM, Different Locations
figure()
plot(lec275_1(1,:), lec275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec275_1), 'LineWidth', 1)
hold on
34
plot(mid275_1(1,:), mid275_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec275_1), 'LineWidth', 1)
plot(back275_1(1,:), back275_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec275_1), 'LineWidth',
1)
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('Human A', 'Human B', 'Human C')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, '275CFMPersonComp.png')
figure()
plot(lec750_1(1,:), lec750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
hold on
plot(mid750_1(1,:), mid750_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
plot(back750_1(1,:), back750_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('Human A', 'Human B', 'Human C')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, '750CFMPersonComp.png')
figure()
plot(lec1200_1(1,:), lec1200_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec1200_1), 'LineWidth',
1)
hold on
plot(mid1200_1(1,:), mid1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec1200_1), 'LineWidth',
1)
plot(back1200_1(1,:), back1200_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec1200_1),
'LineWidth', 1)
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('Human A', 'Human B', 'Human C')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, '1200CFMPersonComp.png')
%% Constant location, different CFM
figure()
plot(back275_1(1,:), back275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
hold on
plot(back750_1(1,:), back750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
plot(back1200_1(1,:), back1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('275 CFM (1.7 ACH, 129 L/s)', '750 CFM (4.7 ACH , 354 L/s)', '1200 CFM (7.5 ACH, 566
L/s)')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, 'humanCCFMComp.png')
figure()
plot(lec275_1(1,:), lec275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
hold on
plot(lec750_1(1,:), lec750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
plot(lec1200_1(1,:), lec1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
ax = gca();
35
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('275 CFM (1.7 ACH, 129 L/s)', '750 CFM (4.7 ACH , 354 L/s)', '1200 CFM (7.5 ACH, 566
L/s)')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, 'humanACFMComp.png')
figure()
plot(mid275_1(1,:), mid275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
hold on
plot(mid750_1(1,:), mid750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1)
plot(mid1200_1(1,:), mid1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1)
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('275 CFM (1.7 ACH, 129 L/s)', '750 CFM (4.7 ACH , 354 L/s)', '1200 CFM (7.5 ACH, 566
L/s)')
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
saveas(gcf, 'humanBCFMComp.png')
%% Table Export
clear vals nn idx T
times = [0,15,30,45,60];
for nn = 1:length(times)
[temp(nn), idx(nn)] = min(abs(agg275_1(1,:)-times(nn)));
vals(nn,1) = agg275_1(1,idx(nn));
vals(nn,2) = agg275_1(2,idx(nn));
[temp(nn), idx(nn)] = min(abs(agg750_1(1,:)-times(nn)));
vals(nn,3) = agg750_1(1,idx(nn));
vals(nn,4) = agg750_1(2,idx(nn));
[temp(nn), idx(nn)] = min(abs(agg1200_1(1,:)-times(nn)));
vals(nn,5) = agg1200_1(1,idx(nn));
vals(nn,6) = agg1200_1(2,idx(nn));
end
names = {'275 Time (mins)', '275 Count', '750 Time (mins)', '750 Count', '1200 Time (mins)',
'1200 Count'};
T = array2table(vals, 'VariableNames', names);
writetable(T, '15minexports.xlsx');
%% Calculate Time constants
[tc275, coeffs275] = timeconstant(agg275_1);
[tc750, coeffs750] = timeconstant(agg750_1);
[tc1200, coeffs1200] = timeconstant(agg1200_1);
figure()
plot(agg275_1(1,:), agg275_1(2,:), '-x', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1);
hold on
plot(agg750_1(1,:), agg750_1(2,:), '-o', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth', 1);
plot(agg1200_1(1,:), agg1200_1(2,:), '-s', 'MarkerIndices', 1:10:length(lec750_1), 'LineWidth',
1);
plot(coeffs275, 'g')
plot(coeffs750, 'c')
plot(coeffs1200, 'm')
ax = gca();
ax.FontSize = mainfontsize;
xlabel('Time (Minutes)', 'FontSize', 25)
ylabel('Particle Count', 'FontSize', 25)
lgd = legend('275 CFM (1.7 ACH, 129 L/s)', '750 CFM (4.7 ACH , 354 L/s)', '1200 CFM (7.5 ACH, 566
L/s)', '275 Exp1 Fit', '750 Exp1 Fit', '1200 Exp1 Fit');
lgd.FontSize = lgdfont;
set(gcf, 'units', 'points', 'position', [0, 0, 700, 500])
%% Time Constant Fcn
function [tc, fitcoeffs] = timeconstant(aggArray)
36
[tempmax, maxidx] = max(aggArray(2,:));
fitcoeffs = fit(aggArray(1,maxidx:length(aggArray))',aggArray(2,maxidx:length(aggArray))',
'exp1');
tc = coeffvalues(fitcoeffs);
end
partcount MATLAB Function %% XML Process Functions
% pir = # of particles in room.
% relpir = # of particles in room scaled to maximum .
% umintime = unique time steps in minutes (time in minutes without
% duplicates), utime is unique time steps in seconds
function [PartData] = partcount(XMLdata)
%% 1 | Import the XML file.
XMLfile = parseXML(XMLdata); % Read and structure xml files
%% 2 | Clean up empty rows through the "Section" tree
n=2;
XMLfile.Children(:,n-1:n:end) = [];
XMLfile.Children(3).Children(:,n-1:n:end) = [];
XMLfile.Children(3).Children(1).Children(:,n-1:n:end) = [];
%% 3 | for each section, clear out the empty rows in the "Data" tree
for ii = 2:length(XMLfile.Children(3).Children)
XMLfile.Children(3).Children(ii).Children(:,n-1:n:end) = [];
end
%% 4 | Create lookup table for Data item #s and their corresponding Item name
% Row 1 is the ID
% Row 2 is the Item name
XMLfile.Children(2).Children(:,n-1:n:end) = [];
for ii = 1:length(XMLfile.Children(2).Children)
SecIDLkUptemp = struct2cell(XMLfile.Children(2).Children(ii).Attributes(1)); % Extracts
the ID # or component from structure
SecIDLkUp(1, ii) = SecIDLkUptemp(2);
SecIDLkUptemp = struct2cell(XMLfile.Children(2).Children(ii).Attributes(2)); % Extracts
the ID Name from structure
SecIDLkUp(2, ii) = SecIDLkUptemp(2);
clear SecIDLkUptemp; % Get rid of temp var
SecIDLkUp = strrep(SecIDLkUp, ' ', '_'); % Replaces all spaces with underscores
SecIDLkUp(2,ii) = strcat(SecIDLkUp(2,ii),'_'); % Adds an underscore before each SecIDName
for ID# concat later
end
SecIDLkUp(2,:) = strcat(SecIDLkUp(2,:), SecIDLkUp(1,:));
%SecIDLkUp = string(SecIDLkUp(2,:));
%% 5 | Extract Data from each "Data item" and create an array within a structure for that
section.
% the format of the structure is:
% Section
% -> Data item
% -> Raw data.
% The XML data structure is frustrating to deal with, so this will
% reorganize it into something that we can deal with more easily in MATLAB.
% sec = zeros(1,length(XMLfile.Children(3).Children));
% sec.data = 1:length(XMLfile.Children(3).Children(1).Children);
% sec.data.val = THE DATA
% sec.data.v(qq) = ('id', SecIDLkUp(1, :);
syms ii qq nn
for ii = 1:length(XMLfile.Children(3).Children)
% Keep in mind that the matlab indexes at 1 and the XML ID indexes at 0
for nn = [1,3,4,5] % all of these Data items are single integers. This could be done
better by reading the "type" variable in Items. 2 is dealt with separatly, 3 should always be "5"
for fluid air tracking.
val2temp = strsplit(XMLfile.Children(3).Children(ii).Children(nn).Children.Data, '
'); % Separate the data into cells using a ' ' delimiter.
val2temp = cell2mat(cellfun(@str2num, val2temp, 'UniformOutput', false));
varname = string(SecIDLkUp(2,nn)); % Create naming array for SecIDs
sec.track(ii).(varname) = val2temp;
end
for qq = 2
37
val2temp = strsplit(XMLfile.Children(3).Children(ii).Children(qq).Children.Data, '
'); % Separate the data into cells using a ' ' delimiter.
val2temp(length(val2temp)) = []; % These two lines remove artifacts from the strsplit
command
val2temp(length(val2temp)) = [];
val2temp = cell2mat(cellfun(@str2num, val2temp, 'UniformOutput', false));
varname = string(SecIDLkUp(2,qq)); % Create naming array for SecIDs
sec.track(ii).(varname) = val2temp;
end
end
%% 6 | Reorganize Data
time = zeros(1,length(sec.track)+1); % create a time array one longer than the times
reported in the xml. The extra row is for t=0
partcount = time; % create another 0 array.
for ii = 2:length(time)
track(ii) = ii; % Track of line
time(ii) = sec.track(ii-1).Particle_Time_2; % Time of track
partcount(ii) = length(sec.track(ii-1).Particle_ID_1); % Number of particles in track
end
utime = unique(time); % Array of unique time steps
if length(sec.track(1).Region_3) == 1
injection = sec.track(1).Injection_0;
injection = (ones(length(utime),1)*injection).';
else
for ii = 2:length(time)
injection(ii) = sec.track(ii-1).Injection_0;
end
end
partcount = partcount.'; % Transpose partcount for matrix algebra
idx = zeros(1,length(utime)); % Create array of zeros
for ii = 1:length(time)
idx(ii,:) = zeros(1,length(utime)); % Create a row of zeros for each unique time step.
This is used as an index for finding when the particle_time changes.
end
for ii = 1:length(utime)
idx(:,ii) = time==utime(ii); % Fill in each column with 1 if the time matches the unique
single step time.
end
for ii = 1:length(utime)
pir(ii) = sum(idx(:,ii).*partcount); % Sum the particle count for each unique time step
end
imax = (pir==max(pir)); % find the index lf the maximums
for ii = 1:length(imax)
amax(ii) = pir(ii)*imax(ii); % amax is the actual max, this code takes the index and uses
it to find the value of the maximum.
end
amax = unique(amax); % These two lines figures out if the peak is a longer than a single
peak, and then picks the first peak/single value to use for making the relative particle data.
amax = amax(amax~=0);
relpir = pir/amax; % This is the relative particle count ie particle count/maximum particle
count
umintime = utime/60; % unique time in minutes.
PartData = [umintime; pir; relpir; injection]; % Packages all of the data nicely in a single
array.
end
combpartcount MATLAB Function function [data1, data2, data3, PartData] = combpartcount(XMLdata1, XMLdata2, XMLdata3)
%% Function Description
% This function takes three seperate injections in an XML format from ANSYS
% Fluent and then proccess the data for them individually for them and as a
% group.
% The inputs are [XMLdata1, XMLdata2, XMLdata3] which is a string address
% to your XML files. For example: XMLdata1 =
'C:\Users\lanel\Downloads\Louis_Ventilation_Rates\750CFM_Run1\particle-back.xml';
% The outputs are: [data1, data2, data3, PartData]
% data1 through data3 are the individual imports of the XMLdata for each
38
% injection in a processable format. The structure for these arrays are:
% [umintime (time elapsed in minutes);
% pir (number of particles in the room);
% relpir (number of particles in the room, divided by max # of parts)
% injection (the ANSYS Fluent injection number assigned)]
% PartData is similar to above, but is an aggregate sum of all of the
% injections (all of the XMLdata combined.) Since each time step is a sum
% of all three injections, this array does not have the injection #.
% The data in this array is
% structured:
% [umintime (time elapsed in minutes);
% pir (number of particles in the room);
% relpir (number of particles in the room, divided by max # of parts)]
%% Import and Concatonate XML Data
% data1 thru data3 are in individual particle exports for XMLdata1 thru
% XMLdata3 respectively. These can be used to plot individual particle
% counts for each injection.
data1 = partcount(XMLdata1);
data2 = partcount(XMLdata2);
data3 = partcount(XMLdata3);
partcomb = data1; % Start the concatonated matrix
partcomb = cat(2, partcomb, data2); % add data2
partcomb = cat(2, partcomb, data3); % and then add data3
%% Sort catted data into linear time series
% At this point we now have all of the data stacked on top of each other in
% the 'partcomb' double.
[tsorted, idx] = sort(partcomb, 2); % This sorts the 'partcomb' array such
% that row is in ascending numerical order, then reporting the values back
% as 'tsorted' and the original index of them as 'idx'. The next loop uses
% the index of the time value to assign the correct particle count values.
% by reassigning the values based off of 'partcomb' and 'idx' for each
% column, then moving along the rows.
for qq = 1:length(tsorted);
for nn = 1:4
sorted(nn, qq) = partcomb(nn, idx(1,qq));
end
end
clear qq nn idx
%% Find total particle count.
% Now we have all of the data in order, in one big spreadsheet. This next
% section sums the particle counts for each time step. This same code is
% used in the 'partcount' function that process aggregate particle track
% data.
time = sorted(1,:);
utime = unique(sorted(1,:));
idex = zeros(1,length(utime)); % Create array of zeros
for ii = 1:length(time)
idex(ii,:) = zeros(1,length(utime)); % Create a row of zeros for each unique time step.
This is used as an index for finding when the particle_time changes.
end
for ii = 1:length(utime)
idex(:,ii) = time==utime(ii); % Fill in each column with 1 if the time matches the unique
single step time.
end
for ii = 1:length(utime)
pir(ii) = sum(idex(:,ii).*(sorted(2,:).')); % Sum the particle count for each unique time
step
end
imax = (pir==max(pir)); % find the index lf the maximums
for ii = 1:length(imax)
39
amax(ii) = pir(ii)*imax(ii); % amax is the actual max, this code takes the index and uses
it to find the value of the maximum.
end
clear ii time idex
amax = unique(amax); % These two lines figures out if the peak is a longer than a single
peak, and then picks the first peak/single value to use for making the relative particle data.
amax = amax(amax~=0);
relpir = pir/amax; % This is the relative particle count ie particle count/maximum particle
count
PartData = [utime; pir; relpir]; % Packages all of the data nicely in a single array.
end
XML Parser Function function theStruct = parseXML(filename)
% PARSEXML Convert XML file to a MATLAB structure.
try
tree = xmlread(filename);
catch
error('Failed to read XML file %s.',filename);
end
% Recurse over child nodes. This could run into problems
% with very deeply nested trees.
try
theStruct = parseChildNodes(tree);
catch
error('Unable to parse XML file %s.',filename);
end
% ----- Local function PARSECHILDNODES -----
function children = parseChildNodes(theNode)
% Recurse over node children.
children = [];
if theNode.hasChildNodes
childNodes = theNode.getChildNodes;
numChildNodes = childNodes.getLength;
allocCell = cell(1, numChildNodes);
children = struct( ...
'Name', allocCell, 'Attributes', allocCell, ...
'Data', allocCell, 'Children', allocCell);
for count = 1:numChildNodes
theChild = childNodes.item(count-1);
children(count) = makeStructFromNode(theChild);
end
end
% ----- Local function MAKESTRUCTFROMNODE -----
function nodeStruct = makeStructFromNode(theNode)
% Create structure of node info.
nodeStruct = struct( ...
'Name', char(theNode.getNodeName), ...
'Attributes', parseAttributes(theNode), ...
'Data', '', ...
'Children', parseChildNodes(theNode));
if any(strcmp(methods(theNode), 'getData'))
nodeStruct.Data = char(theNode.getData);
else
nodeStruct.Data = '';
end
% ----- Local function PARSEATTRIBUTES -----
function attributes = parseAttributes(theNode)
% Create attributes structure.
40
attributes = [];
if theNode.hasAttributes
theAttributes = theNode.getAttributes;
numAttributes = theAttributes.getLength;
allocCell = cell(1, numAttributes);
attributes = struct('Name', allocCell, 'Value', ...
allocCell);
for count = 1:numAttributes
attrib = theAttributes.item(count-1);
attributes(count).Name = char(attrib.getName);
attributes(count).Value = char(attrib.getValue);
end
end
top related