National Annexes: Structure & Versioning Strategy For Eurocodes
This article discusses the implementation of National Annexes (NA) to Eurocodes within the Blueprints library. National Annexes provide country-specific modifications, additional formulas, and parameter values that deviate from the base Eurocode standards. This article aims to establish a clear strategy for managing these variations effectively.
Context
The primary challenge lies in incorporating country-specific adaptations to Eurocodes while maintaining a clean, efficient, and scalable codebase. Currently, the base Eurocodes are implemented, but National Annexes lack systematic support and a version management strategy. The goal is to define a robust framework that minimizes code duplication and ensures maintainability across multiple countries and versions.
Current Situation
- Base Eurocodes (e.g., EN 1992-1-1:2004) are implemented in the main eurocode structure.
- National Annexes are not yet systematically supported.
- No clear strategy exists for managing multiple versions of National Annexes.
Objectives
- Define a clear folder structure for National Annexes.
- Establish a strategy for handling multiple versions of the same National Annex.
- Minimize code duplication between base norms and National Annexes.
- Keep the implementation maintainable for multiple countries.
Proposed Structure
The proposed structure aims to provide a clear and organized approach for managing National Annexes. Here’s one option:
Option 1: Separate national_annex Directory
This option involves creating a separate directory specifically for National Annexes. This approach ensures a clear separation between the base norms and their country-specific adaptations.
blueprints/
└── eurocode/
├── en_1992_1_1_2004/
│ └── chapter_3_materials/
│ └── formula_3_1.py
└── national_annex/
├── netherlands/
│ └── nen_en_1992_1_1_2005/
│ └── chapter_3_materials/
│ └── formula_3_1.py
├── germany/
│ └── din_en_1992_1_1_2005/
│ └── chapter_3_materials/
│ └── formula_3_1.py
└── belgium/
└── nbn_en_1992_1_1_2005/
└── chapter_3_materials/
└── formula_3_1.py
Pros:
- Clear separation between base norms and National Annexes, making it easier to differentiate between the core standards and country-specific modifications.
- Easy to navigate and understand due to the explicit structure that follows a geographical grouping.
- Follows geographical grouping, which aligns well with the nature of National Annexes.
Cons:
- Many nested levels could potentially lead to overly deep directory structures, which might complicate maintenance.
- Potential for deep directory structures, particularly as more countries and versions are added, which could make the codebase harder to manage over time.
Key Decisions Needed
Several critical decisions need to be made to ensure a consistent and maintainable implementation of National Annexes. These decisions cover content strategy, version management, and Eurocode generations.
1. Content Strategy
Agreed: National Annexes should only contain formulas and tables that differ from the base Eurocode, not duplicate everything.
Rationale:
- Reduces code duplication, making the codebase leaner and easier to manage. By only including what is different, the system avoids unnecessary redundancy.
- Easier maintenance because changes to the base Eurocode only need to be reflected in the core implementation, and the National Annexes will automatically inherit those changes unless they explicitly override them.
- Clearer what is actually different per country, which simplifies auditing and ensures that country-specific deviations are easily identifiable.
2. Version Management Strategy
Challenge: National Annexes have multiple versions over time (corrections, updates, etc.).
Managing different versions of National Annexes over time presents a significant challenge. Corrections and updates can lead to multiple versions of the same annex, requiring a robust strategy to handle these variations.
Proposed approach:
- Implement ONE National Annex per norm per country (latest/most relevant version).
- Document version information in:
- Class docstrings
- Formula documentation
- Central documentation file per National Annex
Example implementation for a National Annex formula:
class Form3Dot1NLCharacteristicCompressiveStrength(Formula):
"""Class representing NEN-EN 1992-1-1 National Annex formula for Table 3.1.
This is the Dutch National Annex version which modifies the base Eurocode values.
Source: NEN-EN 1992-1-1+C2:2011 - National Annex Table 3.1
Notes
-----
This formula is based on NEN-EN 1992-1-1+C2:2011.
Previous versions (NEN-EN 1992-1-1:2005) may have different values.
"""
label = "3.1 (NL)"
source_document = NEN_EN_1992_1_1_C2_2011
def __init__(
self,
fck: MPa,
) -> None:
"""Initialize the formula with Dutch National Annex parameters.
NEN-EN 1992-1-1+C2:2011 - National Annex - Table 3.1
Parameters
----------
fck : MPa
[$f_{ck}$] Characteristic compressive cylinder strength [MPa].
"""
super().__init__()
self.fck = fck
@staticmethod
def _evaluate(
fck: MPa,
) -> MPa:
"""Evaluates the formula. See __init__ for details."""
# Dutch-specific calculation or parameter
return fck * 0.85 # Example
# ... rest of the implementation
Example for modified limit values (like in PR #842):
class Form5Dot1NLCriteriumDisregardSecondOrderEffects(ComparisonFormula):
"""Dutch National Annex version of formula 5.1 with modified limit values.
Source: NEN-EN 1993-1-1+C2:2011 - National Annex
Notes
-----
The Dutch National Annex uses different limit values than the base Eurocode:
- Elastic analysis: 12 (instead of 10)
- Plastic analysis: 18 (instead of 15)
"""
label = "5.1 (NL)"
source_document = NEN_EN_1993_1_1_C2_2011
def __init__(
self,
f_cr: N,
f_ed: N,
analysis_type: Literal["elastic", "plastic"]
) -> None:
"""Check if second order effects can be disregarded (Dutch NA version).
NEN-EN 1993-1-1+C2:2011 - National Annex - Formula (5.1)
Parameters
----------
f_cr: N
[$F_{cr}$] Elastic critical buckling load [N].
f_ed: N
[$F_{Ed}$] Design loading on the structure [N].
analysis_type: Literal["elastic", "plastic"]
Type of analysis being performed.
"""
super().__init__()
self.f_cr = f_cr
self.f_ed = f_ed
self.analysis_type = analysis_type
@staticmethod
def _limit(analysis_type: Literal["elastic", "plastic"]) -> float:
"""Returns Dutch NA limit values."""
analysis_type_map = {
"elastic": 12, # NL: 12 instead of 10
"plastic": 18, # NL: 18 instead of 15
}
limit = analysis_type_map.get(analysis_type.lower())
if limit is None:
raise ValueError(
f"Invalid analysis type: {analysis_type}. "
"Must be 'elastic' or 'plastic'."
)
return limit
# ... rest of implementation similar to base formula
Open question: How do we handle conflicting versions when users combine formulas from different NA versions?
3. Eurocode Generations
Agreed: Distinguish between Generation 1 (current) and Generation 2 (upcoming) Eurocodes, but not between minor corrections within a generation.
Rationale:
- Prevents version sprawl by focusing on major standard changes rather than minor corrections, keeping the codebase manageable.
- Supports major standard changes effectively by differentiating between significant Eurocode generations, allowing for future-proof implementation.
Implementation Questions
Several implementation questions need to be addressed to ensure a smooth and consistent integration of National Annexes.
-
Class naming conventions: Should we use suffixes like
NL,DE,BEin class names or rely on import paths?# Option A: Suffix in class name From5Dot1NLCriteriumDisregardSecondOrderEffects # Option B: Same name, different import path from blueprints.eurocode.national_annex.netherlands.nen_en_1993_1_1_2005 import From5Dot1CriteriumDisregardSecondOrderEffectsProposed: Use suffix in class name for clarity (Option A)
-
Documentation: Where should we document which version of the NA is implemented?
- In each formula class docstring ✓
- In
source_documentattribute ✓
-
Inheritance strategy: Should NA formulas inherit from base Eurocode formulas when only parameters differ?
# Option A: Full reimplementation class Form5Dot1NLCriteriumDisregardSecondOrderEffects(ComparisonFormula): # Complete implementation # Option B: Inherit and override class Form5Dot1NLCriteriumDisregardSecondOrderEffects( From5Dot1CriteriumDisregardSecondOrderEffects ): """Dutch NA version with modified limits.""" @staticmethod def _limit(analysis_type: Literal["elastic", "plastic"]) -> float: """Override with Dutch NA limit values.""" # Only override what's differentQuestion: Which approach is cleaner and more maintainable?
-
Testing: How do we test that NA formulas correctly override or extend base formulas?
-
API design: How should users import and use National Annex formulas?
# Explicit import from blueprints.eurocode.national_annex.netherlands.nen_en_1993_1_1_2005.chapter_5_structural_analysis import ( Form5Dot1NLCriteriumDisregardSecondOrderEffects ) # Usage check = Form5Dot1NLCriteriumDisregardSecondOrderEffects( f_cr=1000, f_ed=80, analysis_type="elastic" )
References
- PR #842: First implementation attempt (EN 1993-1-1 Formula 5.1)
- Discussion in team chat (01-12-2025 - 03-12-2025)
Questions for the team
- What do you think about the proposed structure?
- Should we go for Option A (suffix in class name) or Option B (inheritance)?
- How do we handle formulas that only have parameter changes vs. formulas that are completely different?
Acceptance Criteria
Next Steps
- [ ] Gather feedback from core team
- [ ] Make final decision on folder structure
- [ ] Decide on class naming and inheritance strategy
- [ ] Create implementation guidelines document
- [ ] Start with Netherlands (NEN) as pilot implementation
- [ ] Document versioning strategy in contributing guidelines
Dependencies
No response
Confirmation
- [x] I have checked that this feature does not already exist in the issue tracker.
- [x] I have read and understood the contribution guidelines.
For further reading on Eurocodes and National Annexes, consider visiting the European Committee for Standardization (CEN) website.