Index: intern/smoke/extern/smoke_API.h
===================================================================
--- intern/smoke/extern/smoke_API.h	(revision 29368)
+++ intern/smoke/extern/smoke_API.h	(working copy)
@@ -41,7 +41,7 @@
 struct FLUID_3D *smoke_init(int *res, float *p0, float dt);
 void smoke_free(struct FLUID_3D *fluid);
 
-void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta);
+void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, int *border_colli);
 void smoke_step(struct FLUID_3D *fluid, size_t framenr);
 
 float *smoke_get_density(struct FLUID_3D *fluid);
Index: intern/smoke/intern/FLUID_3D.cpp
===================================================================
--- intern/smoke/intern/FLUID_3D.cpp	(revision 29368)
+++ intern/smoke/intern/FLUID_3D.cpp	(working copy)
@@ -35,14 +35,6 @@
 #include <omp.h>
 #endif // PARALLEL 
 
-// boundary conditions of the fluid domain
-#define DOMAIN_BC_FRONT  0 // z
-#define DOMAIN_BC_TOP    1 // y
-#define DOMAIN_BC_LEFT   1 // x
-#define DOMAIN_BC_BACK   DOMAIN_BC_FRONT
-#define DOMAIN_BC_BOTTOM DOMAIN_BC_TOP
-#define DOMAIN_BC_RIGHT  DOMAIN_BC_LEFT
-
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -126,6 +118,18 @@
 		_obstacles[x]    = false;
 	}
 
+	// boundary conditions of the fluid domain
+	// set default values -> vertically non-colliding
+	DOMAIN_BC_FRONT = true;
+	DOMAIN_BC_TOP = false;
+	DOMAIN_BC_LEFT = true;
+	DOMAIN_BC_BACK = DOMAIN_BC_FRONT;
+	DOMAIN_BC_BOTTOM = DOMAIN_BC_TOP;
+	DOMAIN_BC_RIGHT	= DOMAIN_BC_LEFT;
+
+	colloPrev = 1;	// default value
+
+
 	// set side obstacles
 	int index;
 	for (int y = 0; y < _yRes; y++)
@@ -133,11 +137,11 @@
 	{
 		// front slab
 		index = x + y * _xRes;
-		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
 
 		// back slab
 		index += _totalCells - _slabSize;
-		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
 	}
 
 	for (int z = 0; z < _zRes; z++)
@@ -145,11 +149,11 @@
 	{
 		// bottom slab
 		index = x + z * _slabSize;
-		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
 
 		// top slab
 		index += _slabSize - _xRes;
-		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
+		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
 	}
 
 	for (int z = 0; z < _zRes; z++)
@@ -163,6 +167,7 @@
 		index += _xRes - 1;
 		if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
 	}
+
 }
 
 FLUID_3D::~FLUID_3D()
@@ -193,10 +198,11 @@
 }
 
 // init direct access functions from blender
-void FLUID_3D::initBlenderRNA(float *alpha, float *beta)
+void FLUID_3D::initBlenderRNA(float *alpha, float *beta, int *border_colli)
 {
 	_alpha = alpha;
 	_beta = beta;
+	_border_colli = border_colli;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -204,6 +210,10 @@
 //////////////////////////////////////////////////////////////////////
 void FLUID_3D::step()
 {
+	if (colloPrev != *_border_colli) {	// If border rules have been changed
+		setBorderCollisions();
+	}
+
 #if PARALLEL==1
 	int threadval = 1;
 	threadval = omp_get_max_threads();
@@ -351,6 +361,83 @@
 
 }
 
+
+// Set border collision model from RNA setting
+
+void FLUID_3D::setBorderCollisions() {
+
+
+	colloPrev = *_border_colli;		// saving the current value
+
+	// boundary conditions of the fluid domain
+
+	if (colloPrev == 0) {		// No collisions
+		DOMAIN_BC_FRONT = false;
+		DOMAIN_BC_TOP = false;
+		DOMAIN_BC_LEFT = false;
+	}
+	else if (colloPrev == 2) {	// Collide with all sides
+		DOMAIN_BC_FRONT = true;
+		DOMAIN_BC_TOP = true;
+		DOMAIN_BC_LEFT = true;
+	}
+	else	{	// Default values: Collide with "walls", but not top and bottom
+		DOMAIN_BC_FRONT = true;
+		DOMAIN_BC_TOP = false;
+		DOMAIN_BC_LEFT = true;
+	}
+
+	DOMAIN_BC_BACK = DOMAIN_BC_FRONT;
+	DOMAIN_BC_BOTTOM = DOMAIN_BC_TOP;
+	DOMAIN_BC_RIGHT	= DOMAIN_BC_LEFT;
+
+
+
+	// set side obstacles
+	int index;
+	for (int y = 0; y < _yRes; y++)
+	for (int x = 0; x < _xRes; x++)
+	{
+		// front slab
+		index = x + y * _xRes;
+		if(DOMAIN_BC_BOTTOM==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// back slab
+		index += _totalCells - _slabSize;
+		if(DOMAIN_BC_TOP==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+
+	for (int z = 0; z < _zRes; z++)
+	for (int x = 0; x < _xRes; x++)
+	{
+		// bottom slab
+		index = x + z * _slabSize;
+		if(DOMAIN_BC_FRONT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// top slab
+		index += _slabSize - _xRes;
+		if(DOMAIN_BC_BACK==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+
+	for (int z = 0; z < _zRes; z++)
+	for (int y = 0; y < _yRes; y++)
+	{
+		// left slab
+		index = y * _xRes + z * _slabSize;
+		if(DOMAIN_BC_LEFT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+
+		// right slab
+		index += _xRes - 1;
+		if(DOMAIN_BC_RIGHT==1) _obstacles[index] = 1;
+		else _obstacles[index] = 0;
+	}
+}
+
 //////////////////////////////////////////////////////////////////////
 // helper function to dampen co-located grid artifacts of given arrays in intervals
 // (only needed for velocity, strength (w) depends on testcase...
@@ -664,10 +751,10 @@
 	if(DOMAIN_BC_LEFT == 0)  setNeumannX(_xVelocity, _res, 0, _zRes);
 	else setZeroX(_xVelocity, _res, 0, _zRes); 
 
-	if(DOMAIN_BC_TOP == 0)   setNeumannY(_yVelocity, _res, 0, _zRes);
+	if(DOMAIN_BC_FRONT == 0)   setNeumannY(_yVelocity, _res, 0, _zRes);
 	else setZeroY(_yVelocity, _res, 0, _zRes); 
 
-	if(DOMAIN_BC_FRONT == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
+	if(DOMAIN_BC_TOP == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
 	else setZeroZ(_zVelocity, _res, 0, _zRes);
 
 	// calculate divergence
@@ -1063,10 +1150,10 @@
 	if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
 	else setZeroX(_xVelocityOld, res, zBegin, zEnd);
 
-	if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
+	if(DOMAIN_BC_FRONT == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
 	else setZeroY(_yVelocityOld, res, zBegin, zEnd); 
 
-	if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
+	if(DOMAIN_BC_TOP == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
 	else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
 }
 
@@ -1117,10 +1204,10 @@
 	if(DOMAIN_BC_LEFT == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
 	else setZeroX(_xVelocityTemp, res, zBegin, zEnd);				
 
-	if(DOMAIN_BC_TOP == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
+	if(DOMAIN_BC_FRONT == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
 	else setZeroY(_yVelocityTemp, res, zBegin, zEnd); 
 
-	if(DOMAIN_BC_FRONT == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
+	if(DOMAIN_BC_TOP == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
 	else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
 
 	setZeroBorder(_density, res, zBegin, zEnd);
Index: intern/smoke/intern/FLUID_3D.h
===================================================================
--- intern/smoke/intern/FLUID_3D.h	(revision 29368)
+++ intern/smoke/intern/FLUID_3D.h	(working copy)
@@ -46,7 +46,7 @@
 		FLUID_3D() {};
 		virtual ~FLUID_3D();
 
-		void initBlenderRNA(float *alpha, float *beta);
+		void initBlenderRNA(float *alpha, float *beta, int *border_colli);
 		
 		// create & allocate vector noise advection 
 		void initVectorNoise(int amplify);
@@ -116,6 +116,17 @@
 		float *_beta; // was _buoyancy <-- as pointer to get blender RNA in here
 		float _tempAmb; /* ambient temperature */
 
+		bool DOMAIN_BC_FRONT;  // z
+		bool DOMAIN_BC_TOP;    // y
+		bool DOMAIN_BC_LEFT;   // x
+		bool DOMAIN_BC_BACK;   // DOMAIN_BC_FRONT
+		bool DOMAIN_BC_BOTTOM; // DOMAIN_BC_TOP
+		bool DOMAIN_BC_RIGHT;  // DOMAIN_BC_LEFT
+		int *_border_colli; // border collision rules <-- as pointer to get blender RNA in here
+		int colloPrev;		// To track whether value has been changed (to not
+							// have to recalibrate borders if nothing has changed
+		void setBorderCollisions();
+
 		// WTURBULENCE object, if active
 		// WTURBULENCE* _wTurbulence;
 
Index: intern/smoke/intern/smoke_API.cpp
===================================================================
--- intern/smoke/intern/smoke_API.cpp	(revision 29368)
+++ intern/smoke/intern/smoke_API.cpp	(working copy)
@@ -85,9 +85,9 @@
 	wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); 
 }
 
-extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta)
+extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, int *border_colli)
 {
-	fluid->initBlenderRNA(alpha, beta);
+	fluid->initBlenderRNA(alpha, beta, border_colli);
 }
 
 extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
Index: release/scripts/ui/properties_physics_smoke.py
===================================================================
--- release/scripts/ui/properties_physics_smoke.py	(revision 29368)
+++ release/scripts/ui/properties_physics_smoke.py	(working copy)
@@ -80,6 +80,9 @@
                 col.prop(domain, "maxres", text="Divisions")
                 col.label(text="Particle:")
                 col.prop(domain, "initial_velocity", text="Initial Velocity")
+                sub = col.column()
+                sub.active = domain.initial_velocity
+                sub.prop(domain, "velocity_multiplier", text="Multiplier")
 
                 if wide_ui:
                     col = split.column()
@@ -92,7 +95,11 @@
                 sub.prop(domain, "dissolve_speed", text="Time")
                 sub.prop(domain, "dissolve_smoke_log", text="Slow")
 
+                layout.label(text="Domain Border Collisions:")
+                layout.prop(domain, "smoke_domain_colli", expand=True)
+
             elif md.smoke_type == 'FLOW':
+
                 flow = md.flow_settings
 
                 split = layout.split()
Index: source/blender/blenkernel/intern/smoke.c
===================================================================
--- source/blender/blenkernel/intern/smoke.c	(revision 29368)
+++ source/blender/blenkernel/intern/smoke.c	(working copy)
@@ -237,7 +237,7 @@
 		if(!smd->domain->shadow)
 			smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");
 
-		smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta));
+		smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->border_collisions));
 
 		if(smd->domain->wt)	
 		{
@@ -713,11 +713,14 @@
 			smd->domain->omega = 1.0;			
 			smd->domain->alpha = -0.001;
 			smd->domain->beta = 0.1;
+			smd->domain->border_collisions = 1;		// vertically non-colliding
 			smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
 			smd->domain->strength = 2.0;
 			smd->domain->noise = MOD_SMOKE_NOISEWAVE;
 			smd->domain->diss_speed = 5;
-			// init view3d buffer
+			smd->domain->vel_multi = 1.0;
+			// init 3dview buffer
+
 			smd->domain->viewsettings = 0;
 			smd->domain->effector_weights = BKE_add_effector_weights(NULL);
 		}
@@ -910,9 +913,11 @@
 
 								// Uses particle velocity as initial velocity for smoke
 								if(smd->domain->flags & MOD_SMOKE_INITVELOCITY) {
-								velocity_x[index] = pa->state.vel[0];
-								velocity_y[index] = pa->state.vel[1];
-								velocity_z[index] = pa->state.vel[2];										
+
+									velocity_x[index] = pa->state.vel[0]*smd->domain->vel_multi;
+									velocity_y[index] = pa->state.vel[1]*smd->domain->vel_multi;
+									velocity_z[index] = pa->state.vel[2]*smd->domain->vel_multi;
+
 								}										
 								
 								// obstacle[index] |= 2;
Index: source/blender/makesdna/DNA_smoke_types.h
===================================================================
--- source/blender/makesdna/DNA_smoke_types.h	(revision 29368)
+++ source/blender/makesdna/DNA_smoke_types.h	(working copy)
@@ -47,6 +47,11 @@
 #define SM_CACHE_LIGHT		0
 #define SM_CACHE_HEAVY		1
 
+/* domain border collision */
+#define SM_BORDER_OPEN		0
+#define SM_BORDER_VERTICAL	1
+#define SM_BORDER_CLOSED	2
+
 typedef struct SmokeDomainSettings {
 	struct SmokeModifierData *smd; /* for fast RNA access */
 	struct FLUID_3D *fluid;
@@ -84,6 +89,9 @@
 	struct PointCache *point_cache[2];	/* definition is in DNA_object_force.h */
 	struct ListBase ptcaches[2];
 	struct EffectorWeights *effector_weights;
+	int border_collisions;	/* How domain border collisions are handled */
+	float vel_multi;				// Multiplier for particle velocity
+
 } SmokeDomainSettings;
 
 
Index: source/blender/makesrna/intern/rna_smoke.c
===================================================================
--- source/blender/makesrna/intern/rna_smoke.c	(revision 29368)
+++ source/blender/makesrna/intern/rna_smoke.c	(working copy)
@@ -120,6 +120,12 @@
 		{SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
 		{0, NULL, 0, NULL, NULL}};
 
+	static EnumPropertyItem smoke_domain_colli_items[] = {
+		{SM_BORDER_OPEN, "BORDEROPEN", 0, "Open", "Smoke doesn't collide with any border"},
+		{SM_BORDER_VERTICAL, "BORDERVERTICAL", 0, "Vertically Open", "Smoke doesn't collide with top and bottom sides"},
+		{SM_BORDER_CLOSED, "BORDERCLOSED", 0, "Collide All", "Smoke collides with every side"},
+		{0, NULL, 0, NULL, NULL}};
+
 	srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
 	RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings");
 	RNA_def_struct_sdna(srna, "SmokeDomainSettings");
@@ -209,6 +215,13 @@
 	RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits it's velocity from the emitter particle");
 	RNA_def_property_update(prop, 0, NULL);
 
+	prop= RNA_def_property(srna, "velocity_multiplier", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "vel_multi");
+	RNA_def_property_range(prop, -2.0, 2.0);
+	RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
+	RNA_def_property_ui_text(prop, "Multiplier", "Multiplier to adjust velocity passed to smoke");
+	RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
 	prop= RNA_def_property(srna, "dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
 	RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
@@ -241,7 +254,13 @@
 	RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
 	RNA_def_property_update(prop, 0, NULL);
 
+	prop= RNA_def_property(srna, "smoke_domain_colli", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "border_collisions");
+	RNA_def_property_enum_items(prop, smoke_domain_colli_items);
+	RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
+	RNA_def_property_update(prop, 0, NULL);
 
+
 	prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
 	RNA_def_property_struct_type(prop, "EffectorWeights");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
