# How to create better IFC files with Revit
IFC is the ISO standard of how BIM data should be stored. Revit is one
of the two BIM programs used by almost all players in the AEC
industry. Autodesk is also one of the corporate bodies behind the
creation of the IFC ISO standard. It should therefore stand to reason
that creating and exporting high quality IFC files out of Revit should
be easy. Unfortunately, this isn't the case, and
[poor IFC support is one of Revit's biggest problems](../why-revit-is-shit/article.md).
In this article, I will walk through some of the fundamental concepts
in IFC, and explain how to capture that data with Revit, so that the
quality of your BIM data improves, and the longevity of the BIM
digital twin can be increased. In contrast, if you simply supply a
`.rvt` file to your clients, you are merely providing a BIM model with
a shelf-life of 3 years (the lifespan of Autodesk support), and with
no guarantee of interoperability or quality of the BIM data structure.
To start with, I will be blunt and advise that the out-of-the-box
Revit provides extremely poor IFC export and import support. For this
reason, there is an
[open-source IFC import and export plugin for Revit](
https://github.com/Autodesk/revit-ifc/tree/Dev).
Without installing this, there is little you can do with Revit. If you
know how to compile it yourself, please compile the "Dev" branch, as
that will give you the latest features, as it is a moving target as
with most open-source things. You will need to install this to follow
the rest of this article.

Finally, Autodesk as produced the
[Autodesk Revit IFC Manual 2018](
https://www.descor.com/allegati/ifc-manual-2018-enu.pdf)
which helps describe the various options of this open source IFC
exporter. Give it a read, as it will explain all the options in the
exporter. It's a little vague on a few points, but hopefully this
article will help clear things up.
## Revit and IFC version support
One of the first questions people ask is what's the difference between
the IFC versions that you can choose to export to.
Most of the industry (at least from my experience in Australia) is
still producing IFC2x3. However, IFC2X3 lacks many features of IFC4,
so in an ideal world we should aim to produce IFC4 IFCs as much as
possible. However, although Autodesk's marketing department might tell
you otherwise, IFC4 support in Revit is currently quite hit and miss,
although from watching the commits, it is slowly improving. I would
recommend trying to export your project in both IFC2X3 and IFC4. If
all the geometry is able to be exported in IFC4, then I would use
IFC4, because there are ways to set the attributes and data. If the
geometry itself cannot be exported, but it works in IFC2X3, then you
have little choice but to stick with IFC2X3, as geometry
representation is not one of those things you can easily control in
Revit.
## Fundamental IFC concepts
IFC is a bold attempt to improve the transparency and interoperability
of BIM data in the industry. It does this by creating a technical
specification that BIM vendors (Autodesk, Graphisoft, FreeCAD), and
BIM authors (yourself) attempt to follow.
This IFC specification defines different types of elements,
procedures, people, and concepts found in the building industry. These
concepts have different data associated with them, which should be
organised in a certain way to be easily analysed and discovered. Not
all concepts are physical! They can refer to people and timelines. If
an element is a physical object, like walls and floors, it can have a
geometric representation association with them. This allows us to see
our buildings digitally in 2D or 3D. Other data, such as for quantity
take-off, doesn't need to have any geometry associated with it, so a
QS can work purely with raw data.
It is important to have a grasp of these fundamental concepts, which
can be found in
[Chapter 4, IFC fundamental concepts and assumptions](
http://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/schema/chapter-4.htm)
in the
[latest IFC4 specification](
http://www.buildingsmart-tech.org/ifc/IFC4/Add2/html/).
If you think that IFC is merely about calling some shapes walls, and
other shapes floors, and hopefully opening it in one program and
another, you will be surprised to find that IFC offers much more
insight than that, if people used it properly, that is.
## IFC project declaration in Revit
The most funamental concept is the ability to declare your project.
The "project" is not a visible element in Revit, but it does have
attributes associated with it. Below is a list of these attributes.
Most of the values for these attributes are derived from your "Project
Information" settings. When you export an IFC, Revit will
automatically create one `IfcProject`. Let's see what the attributes
are, and where to go to set them correctly:
- `GlobalId` - set automatically and cannot be modified via the UI. It
can, however be modified via the Revit API.
- `OwnerHistory` - set automatically, I won't go into detail but
suffice to say it is set with garbage data and cannot be relied upon
for actual ownership history
- `Name` - this is usually the "short name" or code of the project, it
can be set by changing the "Project Number" attribute.
- `Description` - this can be set by creating a new project parameter
(shared or otherwise) called `IfcDescription`, and making it
available to the "Project Information" category. Please ensure that
you group this parameter under a group named "IFC Parameters".
- `ObjectType` - this can be set by creating a new project parameter
(shared or otherwise) called `IfcObjectType` and making it available
to the "Project Information" category. Please ensure that you group
this parameter under a group named "IFC Parameters".
- `LongName` - this is the full project name, and can be set by
changing the "Project Name" attribute.
- `Phase` - the project phase is set by the "Project Status"
attribute.
- `RepresentationContexts` - Revit will automatically define only one
representation context, which will be a 3-dimensional model, with a
coordinate system and true north.
- `UnitsInContext` - the units are taken from your "Project Units"
settings. It is generally correct. Units can get pretty confusing in
IFC with unit definitions and IFC sometimes advocating specific
units in certain attributes, but this is not a Revit problem, this
is an IFC problem.
If you're curious where these attributes are specified, you can read
the `IfcProject`
[specification page](
http://www.buildingsmart-tech.org/ifc/IFC4/Add2/html/schema/ifckernel/lexical/ifcproject.htm).
The coordinate system of the `IfcGeometricRepresentationContext` is
used to define the offset of the project coordinates from the global
point of origin. This seems to always be set to `(0, 0, 0)`, and I
don't think there is a way to change that through the UI. By default,
true north is Y, east is X, and up / elevation is Z. Please note that
the `IfcProject` does _not_ define the site location.
It is not currently possible to have another
`IfcGeometricRepresentationContext` to represent plan views out of
IFC. Yes, IFC can support native plan views, not just derived plan
views from IFC 3D representations, but Autodesk doesn't allow you to
unfortunately.
## Project library
IFC files don't necessarily only contain a BIM project. Just as you
have Revit families, and can somewhat propagate shared parameters, IFC
allows you to create project libraries that define either types of
objects or groups of properties (known as property sets in IFC lingo).
Technically, you could create your families in IFC format, and it can
have parametric data stored within it, and other programs like FreeCAD
or GeometryGym use this functionality.
This is not possible within Revit.
## IFC object definitions and object type definitions in Revit
There are many objects that are defined in IFC. In Revit, you are used
to categories such as walls, floors, ceilings, and columns. Similarly,
in IFC, there is `IfcWall`, `IfcSlab`, `IfcCovering`, and `IfcColumn`.
IFC has more object "classes" than what is defined in Revit, and goes
into more detail and across more disciplines. Therefore, when you
export to an IFC, you will have to "map" your Revit categories to IFC
object "classes".
All object occurrences are defined by a mapping table supplied by
Autodesk that maps Revit family categories to IFC objects. You can see
this by going to `File -> Export -> Options -> IFC Options`. IFC
objects are defined as subclasses of `IfcObject`, whereby you will
most commonly be dealing with subclasses of `IfcProduct`, such as
walls, beams, etc.

You will notice that the mapping table has two columns: one for IFC
Class Name and one for IFC Type. This is, however, extremely
misleading because the IFC Type field does _not_ refer to the IFC
object type. For example, an `IfcBeam` has an associated
`IfcBeamType`, which serves a purpose similar to a parent class to
which attributes / property sets / geometric representations can be
inherited from (and overriden in the child).
Instead, the IFC Type field actually refers to `PredefinedType`
attribute that exists for both IFC objects and IFC object types. These
are basically more detailed subcategories of the semantic IFC class
name. For example, an `IfcBeam` has a `PredefinedType` attribute which
may contain an enum of `IfcBeamTypeEnum`, where you can specify your
beam to be a `BEAM`, `JOIST`, `HOLLOWCORE`, `LINTEL`, and so on. So
the IFC Type field is actually referring to the enum value, which must
be defined in all uppercase. In the screenshot above, `CONDUITSEGMENT`
is an enum value of `IfcCableCarrierSegmentTypeEnum`.
There is a fundamental problem in Revit whereby the semantic object
you are modeling determines what modeling capabilities you have. If
you want to model a roof, you don't necessarily get the same tools as
modeling a floor, even though geometrically they can be very similar.
This leads to people misusing objects for inappropriate IFC types.
Thankfully, there is some way to mitigate this by ensuring that it is
exported correctly into IFC, regardless of the Revit category being
used.
If you add a project parameter called `IfcExportAs` (type or instance,
both works) as a text parameter and place it in the `IFC Parameters`
group, then you can override the IFC class and predefined type on an
instance-by-instance or type-by-type basis. For instance, if you
create a new generic in-place model, and type in `IfcCovering`, and
export it into an IFC, it will turn into an `IfcCovering` object. If
you alternatively type in `IfcCovering.SKIRTINGBOARD`, you will export
it as an `IfcCovering` object, and its `PredefinedType` attribute will
be set to `SKIRTINGBOARD`. This pattern of
`IfcClass.ENUMVALUEINUPPERCASE` generally works for all classes and
types. This is a great way of adding semantics to generic models.
If you are only interested in setting the `PredefinedType` but keeping
the IFC Class, you can add a project parameter called `IfcExportType`,
and fill it simply with `SKIRTINGBOARD`. Yes, this is a double up in
functionality with the `IfcExportAs` parameter, but I'm mentioning it
for completeness.
However, keep in mind that this trick only works with user-created
families and in-place models. It does _not_ work on system families.
If somebody decides to model a fence using the railing tool or an
office partition with a curtain wall, you can't fix it.
## IFC object attributes in Revit
Each IFC object subclass has a series of attributes that are composed
of the attributes of that particular class, as well as the attributes
inherited by any parent classes. In the latest IFC4Add2 specification,
it is now very easy to see this as each IFC object page has a section
called "Attribute Inheritance", which lists it all out for you.
For instance, an `IfcWall` inherits `GlobalId`, `OwnerHistory`,
`Name`, and `Description` from its parent `IfcRoot`. You will notice
that this is the same as `IfcProject` above. This is because both
`IfcWall` and `IfcProject` inherit from `IfcRoot`. Just like
`IfcProject`, the `GlobalId` and `OwnerHistory` attributes are special
and behave as described above. However, just like in `IfcProject` the
`Name` field is special, the `Name` field of an `IfcWall` is also
special (this applies to most `IfcObject` children). By default, it
will be named after the family name, followed by the family type name,
followed by the family type "tag", which is an autogenerated numerical
ID. These 3 values are concatenated together with the ":" symbol as a
separator. If it is an in-place family, it will use the in-place model
name twice as the first two fields.
If you want a much more sensible name, you can set its `Name` value
manually. Just create a parameter called `IfcName` and add to to the
`IFC Parameters` group. This is the same technique used to set the
`Description` attribute.
This pattern of adding a parameter named after the attribute and
prefixed with `Ifc` is common to all attributes. For instance, an
`IfcWall` also has an attribute called `Tag` (which is ambiguous, but
we'll complain about that later). You can set the value of `Tag` by
creating a parameter called `IfcTag`.
## IFC object types in Revit
As opposed to `PredefinedType`, there is the true concept of object
types in IFC. Any `IfcObject` can have a type definition relationship
(`IfcRelDefinesByType`, or inverse `IsTypedBy`) to an `IfcTypeObject`.
This corresponds roughly (but not exactly) to the selected type of the
Revit family of that object.
For instance, if you create a new wall in Revit of a wall family
"Basic Wall", and choose the type "Wall 1", then your `IfcWall` will
by `isTypedBy` an `IfcWallType` with the name `Wall 1`. In IFC
nomenclature, this is the proper place you should store the human
referrable name. For instance, walls are often given human codes that
correspond to a construction type, such as BLK01, or CON03, or PTN05.
In Revit, although your company might have a standard, it is ambiguous
whether it is stored as a type name, type mark, mark, keynote, or
something else entirely. In IFC, the proper place to store it is in
the `IfcTypeObject`'s `Name` attribute. Given the default mapping,
this must mean that you need to name your Revit family type name's
after your construction type if you want proper IFC exports.
However, it is also possible to override the `Name` attribute using
the trick of creating an `IfcName` parameter in the `IFC Parameters`
group, but this time setting it as a type based parameter instead of
an instance based parameter. Now you can set it to whatever you want.
This creates a little catch: Revit doesn't usually allow two
parameters with the same name, one as a type-based, and one as an
instance-based parameter. This limits you to either name your types
properly, or name your elements properly, but not both. One
workaround, which may be considered bad Revit practice, is to have one
as a project parameter (say, your instance-based one for convention)
and one as a shared parameter (say, your type-based one). This allows
Revit to have two parameters that are named the same. As long as you
don't have any scripts which use the name as the identifier, you'll be
OK with this approach, but it can be confusing.
This issue also occurs with the `Description` attribute. It also
occurs with _any_ attribute that shares a name between objects and
object types. This includes property sets - you can set property set
parameters to be type based to assign that property set attribute to
the object type - but you will run into this limitation where you have
to choose either instance or type.
You will probably notice at this stage that IFC type objects created
by Revit have their tag filled out automatically with a generated
numerical ID. It's probably some internal ID which you can query with
the API, though I haven't tested this. You can override it just like
any other attribute, with no known ill effect.
## Setting IFC object property sets in Revit
Property sets are basically groups of parameters which can be further
set on object and object types. In IFC, each object or type has a list
of related property sets which apply to it. Some of these are specific
to that class of IFC object, and some apply to many objects.
You can export IFC property set data by checking these two boxes in
the IFC setup settings.

It is not compulsory to fill this property set data in. In contrast,
Revit has properties which always show even if you have no intention
of filling them in, and the absence of information may sometimes be
misinterpreted as intentional data (such as the default value of a
boolean checkbox). This is known as the NULL vs empty problem in
Revit, and can mislead BIM users. In IFC, you do not need to include a
property unless you want to fill it with information.
For instance, an `IfcWall` can have the
[`Pset_WallCommon`](
http://www.buildingsmart-tech.org/ifc/IFC4/final/html/schema/ifcsharedbldgelements/pset/pset_wallcommon.htm)
property set applied to it. This property set has attributes such as
`AcousticRating`, `FireRating`, `ThermalTransmittance`, `LoadBearing`
and so on. Although there is room for improvement, there is generally
a sensible set of attributes defined in IFC.
In addition, if your `IfcWall` is concrete, you can use the
`Pset_ConcreteElementGeneral` and describe attributes such as
`ConstructionMethod` (In-Situ / Precast), `StrengthClass`, and
`ReinforcementVolumeRatio`, among others. If your wall isn't concrete,
you simply exclude this property set.
If you have additional details specific to your project, then you can
always create your own property sets and create your own attributes.
We'll see how to do this soon. Ideally, you should create an
`IfcProjectLibrary` so that people know what to expect in your
project, but as mentioned above, it is not possible to create project
libraries in Revit.
Let's say we wanted to set the `FireRating` value of our `IfcWall` in
the `Pset_WallCommon` property set. You can do this by creating a new
project parameter (probably type based, this time) called `FireRating`
and placing it in the `IFC Parameters` parameter group and filling it
out with whatever you want. In Australia, a value might be something
like `120/120/120` for a 2-hour fire rated wall.
I chose the `FireRating` attribute because Revit actually already has
a `Fire Rating` attribute (notice the space) in its `Identity Data`
parameter group out of the box. Because this exists, Autodesk has
hard-coded this value to set the IFC `FireRating` attribute by
default. However, if both the `Fire Rating` parameter and the IFC
`FireRating` parameter exists in your file, the latter will take
priority, including empty values (see the NULL vs empty problem
described above).
For properties such as `AcousticRating` where there is no OOTB Revit
equivalent, you will always need to add your own project parameter.
Notice that these project parameters are _not_ suffixed with `Ifc` and
do not mention which property set it is part of. That is because by
default Revit only deals with "common" property sets, like
`Pset_WallCommon`. However, it is not clear what is "common" and what
isn't. For instance, you will find that if you tried to define
`StrengthClass` from `Pset_ConcreteElementGeneral` it works, however
if you tried to define `EutrophicationPerUnit` from
`Pset_EnvironmentalImpactIndicators`, it won't work. You will need to
trial your required data on a case by case basis.
What if you wanted to set your own property set, or wanted to overcome
an issue where Revit doesn't support the property like the
`EutrophicationPerUnit` example above? This can be done by setting
values in the `DefaultUserDefinedParameterSets.txt` file that the
exporter comes with. Here is an example of setting a custom `FooBar`
property in `My_Own_Property_Set` for `IfcWall` instances, as well as
the `ClimateChangePerUnit` for `Pset_EnvironmentalImpactValues`.
```
#
# User Defined PropertySet Definition File
#
# Format:
# PropertySet: <Pset Name> I[nstance]/T[ype] <element list separated by ','>
# <Property Name 1> <Data type> <[opt] Revit parameter name, if different from IFC>
# <Property Name 2> <Data type> <[opt] Revit parameter name, if different from IFC>
# ...
#
# Data types supported: Area, Boolean, ClassificationReference, ColorTemperature, Count, Currency,
# ElectricalCurrent, ElectricalEfficacy, ElectricalVoltage, Force, Frequency, Identifier,
# Illuminance, Integer, Label, Length, Logical, LuminousFlux, LuminousIntensity,
# NormalisedRatio, PlaneAngle, PositiveLength, PositivePlaneAngle, PositiveRatio, Power,
# Pressure, Ratio, Real, Text, ThermalTransmittance, ThermodynamicTemperature, Volume,
# VolumetricFlowRate
#
PropertySet: My_Own_Property_Set I IfcWall
FooBar Text
PropertySet: Pset_EnvironmentalImpactValues I IfcWall
ClimateChangePerUnit Real
```
Once this file has been updated, the exporter will recognise your
properties and place them in property sets.
There are a few caveats. For instance, if you wanted to record the
`TotalPrimaryEnergyConsumptionPerUnit`, you will notice that its value
is an `IfcEnergyMeasure`. This is not one of the supported data types
in the mapping file. If you check the
[data type definition](
http://www.buildingsmart-tech.org/ifc/IFC4/final/html/schema/ifcmeasureresource/lexical/ifcenergymeasure.htm),
you will see that it is fundamentally a `REAL` value. Therefore,
although it isn't ideal, you can record it as a `Real` type in the
mapping text file.
You might also notice that if you try to record the
`WaterConsumptionPerUnit`, it will successfully record it as an
`IfcVolumeMeasure` with no mapping required. But, what unit is it in?
The IFC spec states that it is
[usually measured in m3](
http://www.buildingsmart-tech.org/ifc/IFC4/final/html/schema/ifcmeasureresource/lexical/ifcvolumemeasure.htm),
but what about our unit definitions at the beginning of the export?
Revit completely ignores your unit settings and will think your value
is in cubic metres. But, Revit also records a conversion factor in the
IFC file to convert between cubic metres and cubic feet. So depending
on your viewer, it might apply the conversion factor to show it to you
in cubic feet if you then open your file elsewhere. Sound confusing?
That's because it is.
## IFC type property sets in Revit
Property sets for types are very similar to property sets for objects,
except that is applies to types, not instances, and also is defined
differently in the STEP syntax (an attribute as opposed to a
relationship). Go fish.
Just change your parameters to be type based instead of instance based
and it will create a property set for the object type rather than the
object. However, you will run into the unique parameter name issue I
describe above.
## IFC performance property sets
IFC has a great concept where you can document the actual performance
of a built object over time - e.g. machine-measured data from building
automation systems and human specified data such as task and resource
usage. This can be predicted, such as from a simulation, or it can be
actual recordings, to verify the performance of a building. This can
be specified at different life-cycle phases of the building.
This can't be done in Revit to my knowledge.
Next.
## Quantity surveying and quantity take-off in Revit
IFC has the concept of a special set of properties which can be set
for each object to define quantities. This can be quantities such as
counts, lengths, areas, and volumes, and are designed to be useful for
quantity surveyors to easily quantify different elements from the BIM
model. They are similar to property sets, but are treated a little
specially under-the-hood.
The geometric representation therefore does not need to necessarily be
100% accurate, or even exist at all, as long as these values are
filled in correctly. You may have noticed that Revit does actually
understand quantities, so let's see how they translate into IFC.
Pop quiz time: if you draw a wall length of 18ft, joined to another
wall at one end, with a void in it (either via profile, void cut, or
hosted door / window / element), what length should be recorded for
quantity take-off purposes in IFC, and what length value will you see
when you export it out of Revit?

The answer is that your IFC file will contain absolutely nothing at
all. By default, Revit will not export any quantity values into IFC.
This means your model is useless if a QS wants to use the IFC file to
do quantity take-off (odds are, they aren't doing it this way anyway,
but ... we're talking about an ideal future here).
Let's play fair this time. Let's say you click the checkbox in the
export properties that isn't on by default that says "export base
quantities". Now, what value will you expect? 18ft? Less? Will it take
into account that the wall profile starts and stops?
The answer is 18.33333ft. Or something else, depending on how the wall
decided to join to the other wall. No, it won't consider the gaping
hole. Does this have any correlation with the greyed out "Dimensions"
parameter group in your Revit properties? Nope.
What about areas and volumes? Well, Revit will record a value called
`NetSideArea` and `NetSideVolume` which is meant to be the full volume
minus any penetrations or holes. Does it actually consider the
penetrations when recording these values? Nope. In fact, it is
misnamed. It should instead be recorded as `GrossSideArea` and
`GrossVolume`.
It's also worth mentioning that `NetSideVolume` is not actually a
valid IFC quantity name. The real name is `NetVolume`, not
`NetSideVolume`. Revit seems to have gotten the quantity names all
mixed up.
What happens if you export both Revit properties and quantity base
properties? You'll get _multiple_ quantity readouts depending on where
they look, and both will give different values, maybe in the right
place, maybe not, and maybe with the right name, maybe not.
Can you override any of these things to fix it manually? No.
The moral of the story is that quantities are currently hopelessly
broken in Revit and if your QS trusts it, get a new QS. In contrast,
the open-source BIM tool
[FreeCAD has an IFC quantities auditor](
http://yorik.uncreated.net/guestblog.php?2019=9)
\- Revit should learn a thing or two from FreeCAD.
## Next steps to creating better IFC files
This post covers the basics of IFC, and doesn't cover many other
concepts such as relationships, associations, classifications,
parametric data, and composition ... and not to mention we haven't
even talked about geometry! However, I believe it should give a
relatively good introduction to the current capabilities of Revit an
OpenBIM, which is to say, not much, but at least it's something. At
the very least, you'll be able to neaten up some of your parameter
storage and improve some data export.
In the future, should time permit, I will cover more IFC concepts in
another article.