Chapter 6 Geotech Engineering Laboratory: Soil Density#
1. Introduction#

Fig. 17 **Figure 4.3 **: Classical Proctor and Sand cone test for estimation of soil density#
🧱 Soil Density in Geotechnical Engineering#
📘 Definition#
Soil density refers to the mass of soil per unit volume. It’s a key parameter in assessing compaction, load-bearing capacity, permeability, and stability of soil for construction and geotechnical applications.
Types of Soil Density#
Type |
Description |
---|---|
Bulk Density |
Includes moisture; total mass per unit volume |
Dry Density |
Mass of solids only, per unit volume (moisture excluded) |
Maximum Dry Density (MDD) |
Highest dry density achievable with optimal moisture |
Relative Density |
Ratio of field density to lab density (used for granular soils) |
🎯 Importance in Geotechnical Engineering#
Foundation Stability: Influences settlement and bearing capacity
Compaction Control: Ensures strength, minimizes voids
Permeability & Drainage: Affects water movement and seepage
Slope & Embankment Safety: Critical in evaluating failure risk
Earthworks Quality Assurance: Used to validate construction standards
🧪 Lab Measurement – Proctor Compaction Test#
Methods:#
Type |
ASTM Standard |
Energy Applied |
Use Case |
---|---|---|---|
Standard Proctor |
ASTM D698 |
12,300 ft-lbf/ft³ |
Residential & non-critical fill |
Modified Proctor |
ASTM D1557 |
56,000 ft-lbf/ft³ |
Highways, airports, structural fill |
Test Principle:#
Compact soil in a mold at varied moisture contents
Record wet mass and compute dry density
Plot dry density vs. moisture content
Peak defines maximum dry density and optimum moisture
Key Equations:#
Bulk Density:
\(( \rho_{bulk} = \frac{M_{wet} - M_{mold}}{V_{mold}} \))Dry Density:
\(( \rho_{dry} = \frac{\rho_{bulk}}{1 + w} \))
Where ( w ) is moisture fraction (e.g., 12% → 0.12)
🏜️ Field Measurement – Sand Cone Test#
Standard: ASTM D1556#
Used to measure in-place density of compacted soil in the field.
Procedure:#
Excavate a small test hole
Fill hole with calibrated dry sand using cone apparatus
Weigh sand used and calculate hole volume
Weigh excavated soil and moisture content
Compute bulk and dry densities, then compare to lab reference
Equations:#
Hole Volume:
( V = \frac{M_{sand}}{\rho_{sand}} - V_{cone} )Dry Density:
( \rho_{dry} = \frac{M_{soil}}{V \times (1 + w)} )
Acceptance:#
≥ 95% of lab dry density → Structural zones
90–95% → General backfill
< 90% → May require moisture correction or re-compaction
Would you like a comparison table between Proctor and Sand Cone methods for teaching purposes or a plotting module for moisture vs. density visualization?
2. Simulation#
🧱 Interactive Proctor Soil Compaction Tool Summary#
📘 What It Is#
A Jupyter-based widget tool for entering and evaluating lab test data from a Proctor compaction test. It calculates dry densities for each trial, identifies the maximum dry density and optimum moisture content, and provides automated compaction recommendations.
⚙️ How It Works#
🔧 Inputs#
Number of Trials: Adjustable with a slider (1–10)
Mold Mass & Volume: Constants used across all trials
Trial Inputs: Moisture content (%) and wet mass (kg) entered per trial
🔢 Computation Logic#
Calculates:
Bulk Density:
\(( \rho_{bulk} = \frac{M_{wet} - M_{mold}}{V_{mold}} \))Dry Density:
\(( \rho_{dry} = \frac{\rho_{bulk}}{1 + w} \)), where \(( w \)) is moisture fraction
Finds trial with maximum dry density
Assesses if results meet compaction specs
🧱 Proctor Soil Compaction Methods – U.S. Standards & Procedures#
📑 U.S. Standards Overview#
Method |
ASTM Standard |
Common Name |
Energy Applied |
---|---|---|---|
Standard Proctor |
ASTM D698 |
“Classical Method” |
12,300 ft-lbf/ft³ |
Modified Proctor |
ASTM D1557 |
“Modified Energy Method” |
56,000 ft-lbf/ft³ |
⚙️ Procedure Comparison Table#
Step |
Standard Proctor (D698) |
Modified Proctor (D1557) |
---|---|---|
Mold Size |
1/30 ft³ (4-inch diameter) |
Same or 1/13.33 ft³ (6-inch diameter) |
Compaction Layers |
3 layers |
5 layers |
Hammer Weight |
5.5 lb |
10 lb |
Drop Height |
12 inches |
18 inches |
Number of Blows/layer |
25 |
25 |
Moisture Variation |
Multiple trials with varying moisture |
Multiple trials with varying moisture |
Measurements Taken |
Wet mass, mold volume, moisture content |
Same |
Calculated Outputs |
Bulk density, dry density, compaction curve, optimum moisture |
Same |
Application |
Residential, embankments, non-critical fills |
Airports, highways, structural fills |
📐 Interpretation Notes#
Bulk Density:
\(( \rho_{bulk} = \frac{M_{wet} - M_{mold}}{V_{mold}} \))Dry Density:
\(( \rho_{dry} = \frac{\rho_{bulk}}{1 + w} \)), where \(( w \)) is moisture fractionCurve Analysis:
Peak of dry density vs. moisture content curve defines:Maximum Dry Density (MDD)
Optimum Moisture Content (OMC)
📊 Output & Interpretation#
Output Metric |
What It Means |
---|---|
Dry Density Table |
Summary per trial showing moisture, mass, bulk and dry densities |
Maximum Dry Density |
Indicates the peak compaction achieved in lab |
Optimum Moisture Content |
Moisture level where compaction peaked |
Density Recommendation |
Evaluates suitability for field applications |
Moisture Recommendation |
Flags moisture content alignment with cohesive soil norms |
✅ Use this tool to validate field compaction targets, interpret lab data trends, and train learners on soil behavior under controlled moisture conditions.
import numpy as np
import pandas as pd
import ipywidgets as widgets
from IPython.display import Markdown, display
# 📋 Setup input widgets
num_trials = widgets.IntSlider(value=5, min=1, max=10, description='Number of Trials:')
mass_mold_input = widgets.FloatText(value=2.10, description='Mold Mass (kg):')
volume_input = widgets.FloatText(value=0.00100, description='Mold Volume (m³):')
# Function to generate inputs for each trial
def generate_trial_inputs(n):
trial_widgets = []
for i in range(n):
moisture = widgets.FloatText(value=12 + i*1.5, description=f'Moisture % (Trial {i+1})')
mass_wet = widgets.FloatText(value=4.2 + i*0.1, description=f'Wet Mass (kg, Trial {i+1})')
trial_widgets.append((moisture, mass_wet))
return trial_widgets
trial_data = generate_trial_inputs(num_trials.value)
def update_trials(change):
global trial_data
trial_data = generate_trial_inputs(change['new'])
input_box.children = [mass_mold_input, volume_input] + [w for pair in trial_data for w in pair]
num_trials.observe(update_trials, names='value')
input_box = widgets.VBox([mass_mold_input, volume_input] + [w for pair in trial_data for w in pair])
run_button = widgets.Button(description='Generate Report')
# 📊 Evaluation logic
def evaluate_compaction(max_dry_density, optimum_moisture):
if max_dry_density >= 1800:
density_status = "✅ Suitable for highway subgrade or structural fill."
elif max_dry_density >= 1600:
density_status = "⚠️ Acceptable for general backfill, but not load-bearing zones."
else:
density_status = "❌ Unsuitable for critical applications—consider reprocessing or additives."
if 10 <= optimum_moisture <= 18:
moisture_status = "✅ Moisture content falls within typical optimum range for cohesive soils."
else:
moisture_status = "⚠️ Moisture content may be too low/high—field adjustment recommended."
return density_status, moisture_status
# 🧱 Calculation and Markdown display
def on_run_click(b):
entries = []
mold_mass = mass_mold_input.value
V = volume_input.value
for pair in trial_data:
moisture = pair[0].value / 100
wet_mass = pair[1].value
bulk_density = (wet_mass - mold_mass) / V
dry_density = bulk_density / (1 + moisture)
entries.append({
'moisture': round(pair[0].value, 1),
'mass_wet': round(wet_mass, 2),
'bulk_density': round(bulk_density, 2),
'dry_density': round(dry_density, 2)
})
df = pd.DataFrame(entries)
idx_max = df['dry_density'].idxmax()
max_dry_density = df.loc[idx_max, 'dry_density']
optimum_moisture = df.loc[idx_max, 'moisture']
density_status, moisture_status = evaluate_compaction(max_dry_density, optimum_moisture)
# 📄 Report generation
report = f"""
### 🧱 Proctor Soil Compaction Report
| Trial | Moisture Content (%) | Wet Mass (kg) | Bulk Density (kg/m³) | Dry Density (kg/m³) |
|-------|----------------------|----------------|------------------------|----------------------|
"""
for i, row in df.iterrows():
report += f"| {i+1} | {row['moisture']:.1f} | {row['mass_wet']:.2f} | {row['bulk_density']:.2f} | {row['dry_density']:.2f} |\n"
report += f"""
#### 🔍 Key Results
- **Maximum Dry Density**: {max_dry_density:.2f} kg/m³
- **Optimum Moisture Content**: {optimum_moisture:.1f} %
---
### 🧭 Interpretation & Recommendations
- **Density Assessment**: {density_status}
- **Moisture Assessment**: {moisture_status}
"""
display(Markdown(report))
run_button.on_click(on_run_click)
display(widgets.VBox([num_trials, input_box, run_button]))
3. Simulation#
🏜️ Sand Cone Test Report – Field Soil Density Determination (ASTM D1556)#
📋 Test Summary#
The sand cone method is used to determine the in-place density of compacted soil in the field. It compares the mass of soil excavated to the volume filled by calibrated sand from the cone apparatus.
🧪 Input Parameters#
Parameter |
Symbol |
Unit |
Description |
---|---|---|---|
Mass of Cone + Sand (Before) |
( M_1 ) |
kg |
Apparatus + sand before test |
Mass of Cone + Sand (After) |
( M_2 ) |
kg |
Apparatus + sand after filling hole |
Calibration Density of Sand |
( \rho_{sand} ) |
kg/m³ |
Known bulk density of calibration sand |
Mass of Excavated Soil |
( M_{soil} ) |
kg |
Mass of soil removed from test hole |
Moisture Content |
( w ) |
% |
Lab-tested moisture content of excavated soil |
⚙️ Computation#
1. Volume of Test Hole#
\(( V = \frac{M_1 - M_2}{\rho_{sand}} \))
Mass of sand poured divided by calibration density
2. Bulk Density#
\(( \rho_{bulk} = \frac{M_{soil}}{V} \))
3. Dry Density#
\(( \rho_{dry} = \frac{\rho_{bulk}}{1 + \frac{w}{100}} \))
🛠️ Corrections in Sand Cone Test#
📏 1. Apparatus Calibration#
Correction Type |
Description |
---|---|
Sand Density Calibration |
Ensure sand used has known unit weight (dry) via standard mold |
Cone Volume Adjustment |
Account for volume in the cone tip that doesn’t enter the hole |
🧪 2. Moisture Content Correction#
Correction Type |
Description |
---|---|
Dry Density Adjustment |
Bulk density converted to dry density using lab moisture content |
Evaporative Losses |
Prevent moisture evaporation between excavation and lab weighing |
⚙️ 3. Excavation Volume Correction#
Correction Type |
Description |
---|---|
Over-excavation |
Correct if the hole is excessively large or irregular in shape |
Collapsing Walls |
Account for soil collapsing which artificially increases volume |
🌡️ 4. Environmental Factors#
Correction Type |
Description |
---|---|
Temperature Effects |
Sand density varies with thermal expansion in extreme conditions |
Wind/Handling Losses |
Fine sand or soil particles lost during transfer |
📊 5. Field vs. Lab Density Comparison#
Correction Type |
Description |
---|---|
Compaction Ratio |
Compute field dry density as % of lab Proctor max dry density |
Specification Thresholds |
Adjust acceptance based on project-specific compaction targets |
📄 Sample Output Table#
Trial |
Sand Before (kg) |
Sand After (kg) |
Excavated Soil (kg) |
Moisture (%) |
Bulk Density (kg/m³) |
Dry Density (kg/m³) |
---|---|---|---|---|---|---|
1 |
12.50 |
10.10 |
3.85 |
11.5 |
1604.17 |
1438.83 |
2 |
12.40 |
10.05 |
3.90 |
12.0 |
1630.43 |
1456.63 |
🧭 Interpretation#
Compare dry density to lab Proctor maximum to assess compaction adequacy
Typical field compaction requirements:
Structural fill: ≥ 95% of Modified Proctor
Subgrade/backfill: ≥ 90% of Standard Proctor
If dry density is low, moisture adjustment or re-compaction may be needed
import pandas as pd
import ipywidgets as widgets
from IPython.display import Markdown, display
# 💡 Style for wide labels and input alignment
label_style = {'description_width': '250px'}
input_layout = widgets.Layout(width='450px')
# 🔧 Reference Inputs with styling
rho_sand_input = widgets.FloatText(
value=1550.0, description='Sand Density (kg/m³):',
style=label_style, layout=input_layout)
cone_tip_volume_input = widgets.FloatText(
value=0.00001, description='Cone Tip Volume Correction (m³):',
style=label_style, layout=input_layout)
lab_dry_density_input = widgets.FloatText(
value=1800.0, description='Lab Max Dry Density (kg/m³):',
style=label_style, layout=input_layout)
num_trials = widgets.IntSlider(
value=2, min=1, max=10, description='No. of Trials:',
style=label_style, layout=input_layout)
# 📋 Trial Input Generator with styled widgets
def create_trial_inputs(n):
trials = []
for i in range(n):
M1 = widgets.FloatText(
value=12.5, description=f'Trial {i+1} – M₁: Mass Before (kg)',
style=label_style, layout=input_layout)
M2 = widgets.FloatText(
value=10.1, description=f'Trial {i+1} – M₂: Mass After (kg)',
style=label_style, layout=input_layout)
M_soil = widgets.FloatText(
value=3.85, description=f'Trial {i+1} – Excavated Soil (kg)',
style=label_style, layout=input_layout)
moisture = widgets.FloatText(
value=11.5, description=f'Trial {i+1} – Moisture (%)',
style=label_style, layout=input_layout)
trials.append((M1, M2, M_soil, moisture))
return trials
trial_inputs = create_trial_inputs(num_trials.value)
def update_trials(change):
global trial_inputs
trial_inputs = create_trial_inputs(change['new'])
trial_box.children = [rho_sand_input, cone_tip_volume_input, lab_dry_density_input] + \
[w for group in trial_inputs for w in group]
num_trials.observe(update_trials, names='value')
trial_box = widgets.VBox([rho_sand_input, cone_tip_volume_input, lab_dry_density_input] + \
[w for group in trial_inputs for w in group])
run_btn = widgets.Button(description='Compute & Generate Report', layout=widgets.Layout(width='250px'))
# 🧮 Calculation and Markdown Output
def on_run_click(b):
rho_sand = rho_sand_input.value
cone_tip_volume = cone_tip_volume_input.value
lab_dry_density = lab_dry_density_input.value
rows = []
for i, group in enumerate(trial_inputs):
M1 = group[0].value
M2 = group[1].value
M_soil = group[2].value
moisture = group[3].value
volume = ((M1 - M2) / rho_sand) - cone_tip_volume
bulk_density = M_soil / volume if volume > 0 else 0
dry_density = bulk_density / (1 + moisture / 100) if bulk_density > 0 else 0
compaction = (dry_density / lab_dry_density) * 100 if lab_dry_density > 0 else 0
remark = (
"✅ Pass: Suitable for structural fill" if compaction >= 95 else
"⚠️ Acceptable for subgrade/backfill" if compaction >= 90 else
"❌ Fail: Rework or adjust moisture"
)
rows.append({
'Trial': i + 1,
'Volume (m³)': round(volume, 5),
'Bulk Density (kg/m³)': round(bulk_density, 2),
'Dry Density (kg/m³)': round(dry_density, 2),
'Compaction (%)': round(compaction, 1),
'Remark': remark
})
df = pd.DataFrame(rows)
# 📝 Markdown Report
report_md = """
### 🏜️ Sand Cone Test – Field Density Report with Corrections
| Trial | Volume (m³) | Bulk Density (kg/m³) | Dry Density (kg/m³) | Compaction (%) | Remark |
|-------|-------------|-----------------------|----------------------|----------------|--------|
"""
for row in rows:
report_md += f"| {row['Trial']} | {row['Volume (m³)']} | {row['Bulk Density (kg/m³)']} | {row['Dry Density (kg/m³)']} | {row['Compaction (%)']} | {row['Remark']} |\n"
report_md += f"""
#### 📌 Reference Settings
- **Sand Calibration Density**: {rho_sand:.1f} kg/m³
- **Cone Tip Volume Correction**: {cone_tip_volume:.5f} m³
- **Lab Max Dry Density**: {lab_dry_density:.1f} kg/m³
---
### 🧭 Interpretation Guide
- **≥ 95%** → ✅ Structural zone approved
- **90–95%** → ⚠️ Acceptable for general fill
- **< 90%** → ❌ May require moisture adjustment or re-compaction
"""
display(Markdown(report_md))
run_btn.on_click(on_run_click)
# 📦 Display Interface
display(widgets.VBox([num_trials, trial_box, run_btn]))
4. Self-Assessment#
🧠 Proctor Soil Compaction – Conceptual, Reflective & Quiz Questions#
🔍 Conceptual Questions#
What is the role of dry density and moisture content in determining optimal soil compaction?
Why is the mold volume critical to computing bulk and dry densities accurately?
How does moisture content influence the ability of soil particles to rearrange and compact?
What distinguishes bulk density from dry density and why must moisture be corrected?
How do you identify optimum moisture content from a set of Proctor test trials?
💭 Reflective Questions#
While entering trial data, which values had the greatest impact on dry density trends?
What might cause a trial to show lower dry density even with increasing moisture—what field behavior could that reflect?
Have you ever seen soil over-compacted in the field—how would dry density results confirm or challenge that impression?
If your optimum moisture is outside the 10–18% range, what construction concerns might you raise?
How confident are you in explaining the logic behind selecting 1800 kg/m³ as a pass/fail threshold for field density?
Dry Density Calculations#
Q1. Which formula correctly computes dry density from bulk density and moisture content?
A. \(( \rho_{dry} = \rho_{bulk} / (1 + w) \)) ✅
B. \(( \rho_{dry} = \rho_{bulk} \times w \))
C. \(( \rho_{dry} = \rho_{bulk} - w \))
D. \(( \rho_{dry} = \rho_{bulk} \times (1 + w) \))
Q2. If mold mass = 2.10 kg, wet mass = 4.40 kg, and volume = 0.001 m³, what is the bulk density?
A. 2300 kg/m³
B. 2200 kg/m³
C. 2300 g/cm³
D. \(( \frac{4.40 - 2.10}{0.001} = \)) 2300 kg/m³ ✅
Q3. Optimum moisture content corresponds to:
A. Minimum dry density
B. Wettest soil possible
C. Peak of dry density vs. moisture curve ✅
D. Saturated soil condition
Interpretation & Specifications#
Q4. Maximum dry density of 1620 kg/m³ falls into which recommendation category?
A. ✅ Suitable for structural fill
B. ⚠️ Acceptable for general backfill ✅
C. ❌ Unsuitable
D. Requires no action
Q5. Why might a moisture value of 21.5% be flagged in the report?
A. It’s dry and safe
B. It exceeds typical cohesive soil range ✅
C. It’s not used in compaction
D. Moisture always increases density
🔍 Conceptual Questions#
What does the sand cone test measure in the context of field compaction?
Why must the volume of the cone tip be subtracted from the sand volume?
How does moisture content influence dry density computation?
Why is sand calibration density critical to accurate volume determination?
What is the significance of comparing field dry density to lab maximum dry density?
💭 Reflective Questions#
How might field conditions (e.g., soil texture, weather) affect your measurements during a sand cone test?
What are the consequences of neglecting cone volume correction in compaction analysis?
If a field test shows 87% compaction, what design risks or construction decisions might follow?
How confident are you in explaining each correction factor (volume, moisture, standard comparison) to a site technician?
When entering multiple trials, what trends in moisture vs. dry density might suggest over-compaction or poor water control?
🧪 Quiz Questions#
Calculation & Accuracy#
Q1. What is the correct formula to compute dry density from bulk density and moisture content?
A. \(( \rho_{\text{dry}} = \rho_{\text{bulk}} \times (1 + w) \))
B. \(( \rho_{\text{dry}} = \rho_{\text{bulk}} / (1 + w/100) \)) ✅
C. \(( \rho_{\text{dry}} = \rho_{\text{bulk}} - w \))
D. \(( \rho_{\text{dry}} = \rho_{\text{bulk}} \times w \))
Q2. In a trial with M₁ = 12.50 kg and M₂ = 10.10 kg, what is the sand mass used?
A. 2.10 kg
B. 2.40 kg ✅
C. 0.00001 m³
D. Depends on moisture content
Q3. Which correction is essential to prevent overestimation of hole volume?
A. Sand grain size
B. Cone tip volume ✅
C. Soil texture
D. Temperature adjustment
Interpretation & Design Implications#
Q4. A field dry density of 1710 kg/m³ compared to lab max of 1800 kg/m³ yields:
A. 95.0% compaction ✅
B. 90.0% compaction
C. 85.0% compaction
D. Cannot determine
Q5. Field compaction falling below 90% typically requires:
A. No action
B. Sand replacement
C. Moisture adjustment or re-compaction ✅
D. Mold volume calibration