Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
agilliland committed Feb 23, 2017
0 parents commit 93d4410
Show file tree
Hide file tree
Showing 24 changed files with 1,770 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets" : ["es2015"]
}
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

[{package.json,bower.json,*.yml}]
indent_size = 2
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
logs
*.log
npm-debug.log*
pids
*.pid
*.seed
lib-cov
coverage
.nyc_output
.grunt
.lock-wscript
build/Release
node_modules
jspm_packages
.npm
.node_repl_history

# app specific ignores
/dist
11 changes: 11 additions & 0 deletions jasmine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"spec_dir": "test",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
37 changes: 37 additions & 0 deletions karma.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
var path = require('path');

var TEST_DIR = path.resolve(__dirname, 'test');

var webpackConfig = require('./webpack.config');
webpackConfig.resolve.alias.testdata = TEST_DIR + "/testdata";

module.exports = function(config) {
config.set({
basePath: TEST_DIR,
files: [
{ pattern: '**/*.spec.js', watched: false, included: true, served: true }
],
browsers: ['PhantomJS'],
frameworks: ['jasmine'],
reporters: ['progress'],
preprocessors: {
'**/*.spec.js': ['webpack']
},
webpack: {
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
resolve: webpackConfig.resolve,
watch: true
},
webpackServer: {
noInfo: true
}
});
};
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "buildzero-energy-model",
"version": "0.1.0",
"description": "",
"main": "",
"author": "",
"license": "AGPL-3.0",
"scripts": {
"build": "webpack -d",
"test": "karma start karma.config.js --single-run"
},
"dependencies": {
"underscore": "^1.8.3"
},
"devDependencies": {
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"jasmine": "^2.5.3",
"jasmine-core": "^2.5.2",
"karma": "^1.5.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-webpack": "^2.0.2",
"webpack": "^1.13.1"
}
}
194 changes: 194 additions & 0 deletions src/model/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
often we need to pass in large groups of definitions for a given calculation,
such as in the solar gains and heat transfer by transmissions calcs which need
the entire building envelope definition including assemblies, etc.
it may be ideal to maintain a separate set of data structures for the persisted
info about model, normalized for easy collection and management by category, but
to then create a working data structure for the model usage itself which is a
denormalized structure where things like assembly data is merged with areas to
make it easier to access the relevant attributes.
*/

let BUILDING = {
assemblies: ASSEMBLIES,
areas: AREAS,
windows: WINDOWS,
ground: GROUND
}

let ASSEMBLIES = {
asm01: ASSEMBLY
};

let ASSEMBLY = {
id: "asm01", // unique identifier, UUID?
name: "Wall", // user defined name
type: "wall", // {"roof", "wall", "floor"}
adjacent_to: "outdoorair", // {"outdoorair", "ground", "ventilated"}
layers: [{ // and ORDERED list of layers making up the assembly
name: "gypsum",
thickness: 0.63,
r_per_inch: 0.9
},{
name: "cellulose", // user defined name
thickness: 3.5, // thickness of material
r_per_inch: 3.6 // r-value per inch of material
},{
name: "sheathing",
thickness: 0.63,
r_per_inch: 1.4
}],
u_value_supplement: 0, // a user defined supplement to the u-value
absorptivity: 0.6, // coefficient of heat absorption (TODO: ok?)
emissivity: 0.1, // coefficient of heat emission (TODO: ok?)

// this stuff is all calculated
thickness: 13.25, // total thickness
r_value: 41.6 // total r-value (TODO: how to calc?)
u_value: 0, // total u-value (TODO: how to calc?)
g_value: 0.023 // absorptivity * r-value * u-value
};


let WINDOWS = {
win01: WINDOW
};

let WINDOW = {
id: "win01", // unique identifier, UUID?
name: "Double Pane", // user defined name

// this stuff is all calculated
thickness: 13.25, // total thickness
r_value: 41.6 // total r-value (TODO: how to calc?)
u_value: 0, // total u-value (TODO: how to calc?)
g_value: 0.023 // absorptivity * r-value * u-value
};


let AREA = {
name: "Front Wall",
group: "front",
assembly: "asm01",
area: 100, // capture unit?
orientation: 74,
inclination: 30,
windows: [{
name: "Large Bay Window",
area: 40, // capture unit?
component_id: "win01",
frame_id: "frame01",
// installation situation??
shading: {
height: 0,
horizontal_distance: 0,
reveal_depth: 0,
distance_to_reveal: 0,
overhang_depth: 0,
distance_to_overhang: 0,
additional_reduction_winter: 0,
additional_reduction_summer: 0,
reduction_factor_Z_for_temporary: 0
}
}]
}


// ELEMENT:
// name
// group (for logically organizing surfaces together)
// area (length * width + user determined addition - user determined subtraction)
// assembly id (defines physical qualities of element like R value)
// angle deviation from North (0=North, 90=East, 180=South, 270=West)
// angle of inclination from horizontal (0/180=flat, 90=vertical)
// ?? reduction factor shading
// ?? exterior absorptivity
// ?? exterior emissivity
//
// GLAZING ELEMENTS:
// name
// area (lenth * width + user determined)
// element id (where this is installed)
// glazing component id (window properties)
// frame component id (window frame properties)
// ?? installation situation (not sure exactly what this is for)
//
// GLAZING ELEMENT SHADING:
// height of shading object
// horizontal distance
// window reveal depth (lateral reveal)
// distance from glazing edge to reveal (lateral reveal)
// overhang depth (reveal/overhang)
// distance from upper glazing edge to overhang (reveal/overhang)
// additional reduction factor winter shading
// additional reduction factor summer shading
// reduction factor z for temporary sun protection (manual shade ??)

let GENERAL_SETTINGS = {
floor_area: 336, // m2
occupants: 17, // people
occupant_density: 20.0, // m2/person (this can be area/occupants)
metabolic_load: 88, // W/person
appliance_load: 10.0, // W/m2
lighting_load: 10.0, // W/m2
outdoor_air: 10.0, // liter/s/person
dhw: 5.0, // liter/m2/person

// lighting specific
daylighting_factor: 1,
lighting_occupancy_factor: 1,
constant_illumination_factor: 1,
is_parasitic_lighting: 1,
annual_parasitic_load: 6
};


// should be an array with each element corresponding to an hour of the day (0-23)
// each entry is an object with the relevant data about usage for that hour
let SCHEDULE = [
{
// NOTE: it is important to be able to tell if a given hour of the day
// is considered a night-time or day-time hour.
// default seems to be day-time = 9am-6pm
// weekday usage
wd_heat_point: 16,
wd_cool_point: 29,
wd_occupancy: 0.10,
wd_appliance: 0.10,
wd_lighting: 0.10,
// weekend usage
we_heat_point: 16,
we_cool_point: 29,
we_occupancy: 0.10,
we_appliance: 0.10,
we_lighting: 0.10
}
];

// should be an array with each element corresponding to a month of year (0=jan, 11=dec)
// each entry is an object with the relevant data for the given month
let CLIMATE = [
{
mon: "jan",
temp: 4,
wind_speed: 4.6,
avg_solar_S: 166,
avg_solar_SE: 119,
avg_solar_E: 64,
avg_solar_NE: 33,
avg_solar_N: 30,
avg_solar_NW: 38,
avg_solar_W: 85,
avg_solar_SW: 144,
avg_solar_HOR: 116,
solar_altitude: 22.4,
dry_air_humidity: 3.60,
atmospheric_pressure: 98645,
relative_humidity: 65,
dew_point: -3.033512786,
sky_cover: 0.616689098,
sky_temp: 260.3223678,
solar_transmittance: 0.92
}
];
56 changes: 56 additions & 0 deletions src/model/dynamic_parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

// Clause 12.x - Dynamic Parameters


// 12.2.1.1 (page 62) gainUtilizationFactor
function gainUtilizationFactor(heatBalanceRatio, heatingHeatGains, heatingHeatTransfer) {
// next calculate the building time constant
let buildingTimeConstant = buildingTimeConstant();

// finally we calculate the building inertia coefficient
let buildingInertia = buildingInertia(buildingTimeConstant);

// depending on our heat balance ratio, determine the final approach
if (heatBalanceRatio === 1) {
// == buildingInertia / (buildingInertia + 1)
} else if (heatBalanceRatio > 0) {
// == 1 / buildingInertia
} else {
// == (1 - heatBalanceRatio^buildingInertia) / (1 - heatBalanceRatio^(buildingInertia + 1))
}
}

// Building Inertia - 12.2.1.1/12.2.1.2 (page 62,64)
function buildingInertia(buildingTimeConstant) {
// NOTE: these constants are specific to MONTHLY calculations
return 1.0 + (buildingTimeConstant / 15);
}

// Internal heat capacity of the building - 12.3.1.1 (page 67)
// unit = J/K (joules/kelvin)
function internalHeatCapacity(buildingEnvelope) {
// sum the internal heat capacity of each building element in contact w/ internal air

// defaults for element heat capacities
// very light = 80000 * areaOfElement
// light = 110000 * areaOfElement
// medium = 165000 * areaOfElement
// heavy = 260000 * areaOfElement
// very heavy = 370000 * areaOfElement
}

// Building Time Constant - 12.2.1.3 (page 66)
// Characterizes the internal thermal inertia of the conditioned zone
// == (internalHeatCapacity * 3600) / (heatTransferCoefficientByTransmissionAdjusted + heatTransferCoefficientByVentilationAdjusted)
// unit == hours
function buildingTimeConstant(internalHeatCapacity, representativeHeatTransferCoefficientByTransmission, representativeHeatTransferCoefficientByVentilation) {
// the values for heat transfer coefficients used here are meant to be representative of the dominating season,
// so it should be values for a mid-winter month in the case of a heating dominated climate, or it should be a mid-summer
// month in the case of a cooling dominated climate
return (internalHeatCapacity / 3600) / (representativeHeatTransferCoefficientByTransmission + representativeHeatTransferCoefficientByVentilation);
}

// 12.2.1.2 (page 72) lossUtilizationFactor
function lossUtilizationFactor(heatBalanceRatio) {

}
Loading

0 comments on commit 93d4410

Please sign in to comment.