openepd 2.0.0__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. openepd/__init__.py +1 -1
  2. openepd/__version__.py +2 -2
  3. openepd/api/__init__.py +19 -0
  4. openepd/api/base_sync_client.py +550 -0
  5. openepd/api/category/__init__.py +19 -0
  6. openepd/api/category/dto.py +25 -0
  7. openepd/api/category/sync_api.py +44 -0
  8. openepd/api/common.py +239 -0
  9. openepd/api/dto/__init__.py +19 -0
  10. openepd/api/dto/base.py +41 -0
  11. openepd/api/dto/common.py +115 -0
  12. openepd/api/dto/meta.py +69 -0
  13. openepd/api/dto/mf.py +59 -0
  14. openepd/api/dto/params.py +19 -0
  15. openepd/api/epd/__init__.py +19 -0
  16. openepd/api/epd/dto.py +121 -0
  17. openepd/api/epd/sync_api.py +105 -0
  18. openepd/api/errors.py +86 -0
  19. openepd/api/pcr/__init__.py +19 -0
  20. openepd/api/pcr/dto.py +41 -0
  21. openepd/api/pcr/sync_api.py +49 -0
  22. openepd/api/sync_client.py +67 -0
  23. openepd/api/test/__init__.py +19 -0
  24. openepd/bundle/__init__.py +1 -1
  25. openepd/bundle/base.py +1 -1
  26. openepd/bundle/model.py +5 -6
  27. openepd/bundle/reader.py +5 -5
  28. openepd/bundle/writer.py +5 -4
  29. openepd/compat/__init__.py +19 -0
  30. openepd/compat/pydantic.py +29 -0
  31. openepd/model/__init__.py +1 -1
  32. openepd/model/base.py +114 -15
  33. openepd/model/category.py +39 -0
  34. openepd/model/common.py +33 -25
  35. openepd/model/epd.py +97 -78
  36. openepd/model/factory.py +48 -0
  37. openepd/model/lcia.py +24 -13
  38. openepd/model/org.py +28 -18
  39. openepd/model/pcr.py +42 -14
  40. openepd/model/specs/README.md +19 -0
  41. openepd/model/specs/__init__.py +20 -4
  42. openepd/model/specs/aluminium.py +67 -0
  43. openepd/model/specs/asphalt.py +87 -0
  44. openepd/model/specs/base.py +60 -0
  45. openepd/model/specs/concrete.py +453 -23
  46. openepd/model/specs/glass.py +404 -0
  47. openepd/model/specs/steel.py +193 -0
  48. openepd/model/specs/wood.py +130 -0
  49. openepd/model/standard.py +2 -3
  50. openepd/model/validation/__init__.py +19 -0
  51. openepd/model/validation/common.py +59 -0
  52. openepd/model/validation/numbers.py +26 -0
  53. openepd/model/validation/quantity.py +131 -0
  54. openepd/model/versioning.py +129 -0
  55. {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/METADATA +36 -5
  56. openepd-3.0.0.dist-info/RECORD +59 -0
  57. openepd-2.0.0.dist-info/RECORD +0 -22
  58. {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/LICENSE +0 -0
  59. {openepd-2.0.0.dist-info → openepd-3.0.0.dist-info}/WHEEL +0 -0
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2023 by C Change Labs Inc. www.c-change-labs.com
2
+ # Copyright 2024 by C Change Labs Inc. www.c-change-labs.com
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -18,10 +18,182 @@
18
18
  # Find out more at www.BuildingTransparency.org
19
19
  #
20
20
  from enum import StrEnum
21
+ from typing import Literal
21
22
 
22
- import pydantic as pyd
23
+ from openepd.compat.pydantic import pyd
24
+ from openepd.model.base import BaseOpenEpdSchema
25
+ from openepd.model.common import OpenEPDUnit
26
+ from openepd.model.specs.base import BaseOpenEpdHierarchicalSpec, BaseOpenEpdSpec
27
+ from openepd.model.validation.common import together_validator
28
+ from openepd.model.validation.numbers import RatioFloat
29
+ from openepd.model.validation.quantity import LengthMmStr, PressureMPaStr, validate_unit_factory
23
30
 
24
- from openepd.model.base import BaseOpenEpdSpec
31
+
32
+ class AciExposureClass(StrEnum):
33
+ """
34
+ American Concrete Institute concrete exposure classes.
35
+
36
+ * `aci.F0` - Concrete not subjected to freezing-and-thawing cycles
37
+ * `aci.F1` - Concrete experiences freezing-and-thawing cycles with limited exposure to water
38
+ * `aci.F2` - Concrete exposed to freezing-and-thawing cycles with frequent exposure to water
39
+ * `aci.F3` - Concrete exposed to freezing-and-thawing cycles with continual exposure to water
40
+ and exposure to deicing chemicals
41
+ * `aci.S0` - Exposed to <150 ppm of SO4 in water and <0.1% SO4 in soil
42
+ * `aci.S1` - Exposed to <1500 ppm of SO4 in water and <0.2% SO4 in soil
43
+ * `aci.S2` - Exposed to <10000 ppm of SO4 in water and <2% SO4 in soil
44
+ * `aci.S3` - Exposed to >10000 ppm of SO4 in water or >2% SO4 in soil
45
+
46
+ * `aci.C1` - Concrete in contact with moisture, but the external source of chloride does not reach it.
47
+ * `aci.C2` - Concrete subjected to moisture and an external source of chlorides such as deicing chemicals,
48
+ salt, brackish water, seawater, or spray from these sources.
49
+ * `aci.W0` - Concrete dry in service
50
+ * `aci.W1` - Concrete in contact with water, no requirement for low permeability
51
+ * `aci.W2` - Concrete in contact with water where low permeability is required
52
+ """
53
+
54
+ F0 = "aci.F0"
55
+ F1 = "aci.F1"
56
+ F2 = "aci.F2"
57
+ F3 = "aci.F3"
58
+ S0 = "aci.S0"
59
+ S1 = "aci.S1"
60
+ S2 = "aci.S2"
61
+ S3 = "aci.S3"
62
+ C1 = "aci.C1"
63
+ C2 = "aci.C2"
64
+ W0 = "aci.W0"
65
+ W1 = "aci.W1"
66
+ W2 = "aci.W2"
67
+
68
+
69
+ class CsaExposureClass(StrEnum):
70
+ """
71
+ Canadian Standard Association concrete exposure classes.
72
+
73
+ * `csa.C-XL` - Structurally reinforced concrete exposed to chlorides or other severe environment with or without
74
+ freezing and thawing conditions, with higher durability performance expectations than the C-1, A-1
75
+ or S-1 classes.
76
+
77
+ * `csa.C-1` - Structurally reinforced concrete exposed to chlorides with or without freezing and thawing conditions.
78
+ Examples: bridge decks, parking decks and ramps, portions of marine structures located within the tidal
79
+ and splash zones, concrete exposed to seawater spray, and salt water pools.
80
+ * `csa.C-2` - Non-structurally reinforced (i.e. plain) concrete exposed to chlorides and freezing and thawing.
81
+ Examples: garage floors, porches, steps, pavements, sidewalks curbs and gutters.
82
+ * `csa.C-3` - Continuously submerged concrete exposed to chlorides but not to freezing and thawing.
83
+ Example: underwater portions of marine structures.
84
+ * `csa.C-4` - Non-structurally reinforced concrete exposed to chlorides but not to freezing and thawing.
85
+ Examples: underground parking slabs on grade.
86
+
87
+ * `csa.F-1` - Concrete exposed to freezing and thawing in a saturated condition but not to chlorides.
88
+ Examples: pool decks, patios, tennis courts, freshwater pools and fresh water control structures.
89
+ * `csa.F-2` - Concrete in an unsaturated condition exposed to freezing and thawing but not to chlorides.
90
+ Examples: exterior walls and columns.
91
+
92
+ * `csa.N` - Concrete not exposed to chlorides nor to freezing and thawing.
93
+ Examples: footings and interior slabs, walls and columns.
94
+
95
+ * `csa.A-1` - Structurally reinforced concrete exposed to severe manure and/or silage gases, with or without
96
+ freeze-thaw exposure. Concrete exposed to the vapour above municipal sewage or industrial effluent,
97
+ where hydrogen sulphide gas may be generated.
98
+ Examples: reinforced beams, slabs, and columns over manure pits and silos, canals, and pig slats;
99
+ and access holes, enclosed chambers and pipes that are partially filled with effluents.
100
+ * `csa.A-2` - Structurally reinforced concrete exposed to moderate to severe manure and/or silage gases and liquids,
101
+ with or without freeze-thaw exposure.
102
+ Examples: reinforced walls in exterior manure tanks, silos and feed bunkers, and exterior slabs.
103
+ * `csa.A-3` - Structurally reinforced concrete exposed to moderate to severe manure and/or silage gases and liquids,
104
+ with or without freeze-thaw exposure in a continuously submerged condition. Concrete continuously
105
+ submerged in municipal or industrial effluents.
106
+ Examples: interior gutter walls, beams, slabs and columns; sewage pipes that are continuously full
107
+ (e.g. force mains); and submerged portions of sewage treatment structures.
108
+ * `csa.A-4` - Non-structurally reinforced concrete exposed to moderate manure and/or silage gases and liquids, without
109
+ freeze-thaw exposure.
110
+ Examples: interior slabs on grade.
111
+
112
+ * `csa.S-1` - Concrete subjected to very severe sulphate exposures.
113
+ Exposed to >10000 ppm of SO4 in water or >2% SO4 in soil
114
+ * `csa.S-2` - Concrete subjected to severe sulphate exposure.
115
+ Exposed to <10000 ppm of SO4 in water and <2% SO4 in soil
116
+ * `csa.S-3` - Concrete subjected to moderate sulphate exposure.
117
+ Exposed to <1500 ppm of SO4 in water and <0.2% SO4 in soil
118
+ """
119
+
120
+ C_XL = "csa.C-XL"
121
+ C_1 = "csa.C-1"
122
+ C_2 = "csa.C-2"
123
+ C_3 = "csa.C-3"
124
+ C_4 = "csa.C-4"
125
+ F_1 = "csa.F-1"
126
+ F2 = "csa.F-2"
127
+ N = "csa.N"
128
+ S_1 = "csa.S-1"
129
+ S_2 = "csa.S-2"
130
+ S_3 = "csa.S-3"
131
+ A_1 = "csa.A-1"
132
+ A_2 = "csa.A-2"
133
+ A_3 = "csa.A-3"
134
+ A_4 = "csa.A-4"
135
+
136
+
137
+ class EnExposureClass(StrEnum):
138
+ """
139
+ EN 206 Class (Europe).
140
+
141
+ European Standard concrete exposure classes.
142
+
143
+ * `en206.X0` - No risk of corrosion or attack.
144
+
145
+ Corrosion induced by carbonation.
146
+
147
+ * `en206.XC1` - Dry or permanently wet.
148
+ * `en206.XC2` - Wet, rarely dry.
149
+ * `en206.XC3` - Moderate humidity.
150
+ * `en206.XC4` - Cyclic wet and dry.
151
+
152
+ Corrosion induced by chlorides from sea water.
153
+
154
+ * `en206.XS1` - Exposed to airborne salt but not in direct contact with sea water.
155
+ * `en206.XS2` - Permanently submerged.
156
+ * `en206.XS3` - Tidal, splash and spray zones.
157
+
158
+ Corrosion induced by chlorides other than from sea water.
159
+
160
+ * `en206.XD1` - Moderate humidity.
161
+ * `en206.XD2` - Wet, rarely dry.
162
+ * `en206.XD3` - Cyclic wet and dry.
163
+
164
+ Freeze/thaw attack with or without de-icing agents.
165
+
166
+ * `en206.XF1` - Moderate water saturation, without deicing agent.
167
+ * `en206.XF2` - Moderate water saturation, with deicing agent.
168
+ * `en206.XF3` - High water saturation, without de-icing agent.
169
+ * `en206.XF4` - High water saturation, with de-icing agent or sea water.
170
+
171
+ Chemical attack.
172
+
173
+ * `en206.XA1` - Slightly aggressive chemical environment.
174
+ * `en206.XA2` - Moderately aggressive chemical environment.
175
+ * `en206.XA3` - Highly aggressive chemical environment.
176
+
177
+ """
178
+
179
+ en206_X0 = "en206.X0"
180
+ en206_XC1 = "en206.XC1"
181
+ en206_XC2 = "en206.XC2"
182
+ en206_XC3 = "en206.XC3"
183
+ en206_XC4 = "en206.XC4"
184
+ en206_XS1 = "en206.XS1"
185
+ en206_XS2 = "en206.XS2"
186
+ en206_XS3 = "en206.XS3"
187
+ en206_XD1 = "en206.XD1"
188
+ en206_XD2 = "en206.XD2"
189
+ en206_XD3 = "en206.XD3"
190
+ en206_XF1 = "en206.XF1"
191
+ en206_XF2 = "en206.XF2"
192
+ en206_XF3 = "en206.XF3"
193
+ en206_XF4 = "en206.XF4"
194
+ en206_XA1 = "en206.XA1"
195
+ en206_XA2 = "en206.XA2"
196
+ en206_XA3 = "en206.XA3"
25
197
 
26
198
 
27
199
  class CmuWeightClassification(StrEnum):
@@ -35,55 +207,313 @@ class CmuWeightClassification(StrEnum):
35
207
  """Lightweight CMU has a density less than 105 lbs/cu. ft."""
36
208
 
37
209
 
38
- class CmuOptions(BaseOpenEpdSpec):
210
+ class CmuOptions(BaseOpenEpdSchema):
39
211
  """Concrete Masonry Unit options."""
40
212
 
41
213
  load_bearing: bool | None = pyd.Field(
42
214
  description="Load-Bearing. CMUs intended to be loadbearing, rather than simply cosmetic",
215
+ example=True,
43
216
  default=None,
44
- json_schema_extra={"example": True},
45
217
  )
46
218
  aerated_concrete: bool | None = pyd.Field(
47
- description="AAC Aerated Concrete. Aerated Autoclaved Concrete, a foam concrete.",
48
- default=None,
49
- json_schema_extra={"example": True},
219
+ description="AAC Aerated Concrete. Aerated Autoclaved Concrete, a foam concrete.", example=True, default=None
50
220
  )
51
221
  insulated: bool | None = pyd.Field(
52
- description="Insulated. CMUs with integral insulation",
53
- default=None,
222
+ description="Insulated. CMUs with integral insulation", example=True, default=None
54
223
  )
55
224
  sound_absorbing: bool | None = pyd.Field(
56
- description="Sound Absorbing. CMUs structured for sound absorbtion",
57
- default=None,
225
+ description="Sound Absorbing. CMUs structured for sound absorbtion", example=True, default=None
58
226
  )
59
227
  white: bool | None = pyd.Field(
60
- description="White. CMU using white cement and light-colored aggregate",
61
- default=None,
228
+ description="White. CMU using white cement and light-colored aggregate", example=True, default=None
62
229
  )
63
230
  recycled_aggregate: bool | None = pyd.Field(
64
- description="Recycled aggregate. CMU using primarily reycled aggregates",
65
- default=None,
231
+ description="Recycled aggregate. CMU using primarily reycled aggregates", example=True, default=None
66
232
  )
67
233
  groundface: bool | None = pyd.Field(
68
- description="Ground Face. Ground or Honed facing, typically for improved appearance", default=None
234
+ description="Ground Face. Ground or Honed facing, typically for improved appearance", example=True, default=None
69
235
  )
70
236
  splitface: bool | None = pyd.Field(
71
- description="Splitface. Rough surface texture via splitting; aggregate can be seen", default=None
237
+ description="Splitface. Rough surface texture via splitting; aggregate can be seen", example=True, default=None
238
+ )
239
+ smoothface: bool | None = pyd.Field(
240
+ description="Smooth Face. Standard smooth-faced blocks", example=True, default=None
72
241
  )
73
- smoothface: bool | None = pyd.Field(description="Smooth Face. Standard smooth-faced blocks", default=None)
74
242
  slumpstone: bool | None = pyd.Field(
75
243
  description="Slumpstone. A slightly rounded, random distortion with the look of rustic adobe.",
244
+ example=True,
245
+ default=None,
246
+ )
247
+
248
+
249
+ class ConcreteTypicalApplication(BaseOpenEpdSpec):
250
+ """Typical Application for Concrete."""
251
+
252
+ fnd: bool | None = pyd.Field(
253
+ description="Foundation. Typically used in direct contact with soil, e.g. footings, piles, mass concrete, "
254
+ "mat foundations, and similar applications.",
255
+ example=True,
256
+ default=None,
257
+ )
258
+ sog: bool | None = pyd.Field(
259
+ description="Slab on Grade. Typically used in continuously supported horizontal "
260
+ "applications e.g. slab on grade, topping slabs, sidewalks, and roadways.",
261
+ example=True,
262
+ default=None,
263
+ )
264
+ hrz: bool | None = pyd.Field(
265
+ description="Elevated Horizontal. Typically used in elevated horizontal applications, either on metal deck or "
266
+ "where soffit formwork must be removed, e.g. post-tension plates, rebar plates, beams and slabs, "
267
+ "waffle slabs.",
268
+ example=True,
269
+ default=None,
270
+ )
271
+ vrt_wall: bool | None = pyd.Field(description="Vertical Wall.", example=True, default=None)
272
+ vrt_column: bool | None = pyd.Field(description="Vertical Column.", example=True, default=None)
273
+ vrt_other: bool | None = pyd.Field(
274
+ description="Vertical Other. Typically used in vertical applications other than "
275
+ "walls or columns, e.g. sloped surfaces where formwork is required "
276
+ "on multiple faces.",
277
+ example=True,
278
+ default=None,
279
+ )
280
+ sht: bool | None = pyd.Field(
281
+ description="Shotcrete. Pneumatically applied, without formwork on all sides.", example=True, default=None
282
+ )
283
+ cdf: bool | None = pyd.Field(
284
+ description="Flowable Fill (CDF). Typically used to fill voids, backfill retaining "
285
+ "walls, as a sub-base, and similar applications. Also called Controlled "
286
+ "Density Fill (CDF) or Controlled Low Strength Materials (CLSM).",
287
+ example=True,
76
288
  default=None,
77
289
  )
290
+ sac: bool | None = pyd.Field(
291
+ description="Typically used in concrete sidewalks and barrier curbs.", example=True, default=None
292
+ )
293
+ pav: bool | None = pyd.Field(description="Typically used in pervious concrete", example=True, default=None)
294
+ oil: bool | None = pyd.Field(
295
+ description="Concretes for use in creation, maintenance, and decommissioning of "
296
+ "petroleum extraction wells and similar applications. Includes foamed "
297
+ "cement; often called cement in the drilling industry. Differs from "
298
+ "flowable fill and grout in that it contains no sand or other aggregates.",
299
+ example=True,
300
+ default=None,
301
+ )
302
+ grt: bool | None = pyd.Field(
303
+ description="Cement grouting is a slurry that is placed as a flowable liquid. It is "
304
+ "an effective material for filling and strengthening granular soils, "
305
+ "voids in rocks, foundation underpinnings, and other underground voids. "
306
+ "Also called structural grout, these materials typically impart"
307
+ " significant strength to the system",
308
+ example=True,
309
+ default=None,
310
+ )
311
+ ota: bool | None = pyd.Field(
312
+ description="Typical application not covered by other values.", example=True, default=None
313
+ )
78
314
 
79
315
 
80
316
  class CmuSpec(BaseOpenEpdSpec):
81
317
  """Standardized Concrete Masonry Unit-specific extension for OpenEPD."""
82
318
 
83
- strength: str = pyd.Field(
84
- description="Compressive strength",
85
- json_schema_extra=dict(example="4000 psi"),
86
- )
319
+ strength: str = pyd.Field(description="Compressive strength", example="4000 psi")
87
320
  options: CmuOptions = pyd.Field(
88
321
  description="Options for CMU. List of true/false properties", default_factory=CmuOptions
89
322
  )
323
+
324
+
325
+ class Cementitious(BaseOpenEpdSchema):
326
+ """List of cementitious materials, and proportion by mass."""
327
+
328
+ opc: RatioFloat | None = pyd.Field(default=None, description="Ordinary Gray Portland Cement")
329
+ wht: RatioFloat | None = pyd.Field(default=None, description="White Portland Cement")
330
+ ggbs: RatioFloat | None = pyd.Field(default=None, description="Ground Granulated Blast Furnace Slag")
331
+ flyAsh: RatioFloat | None = pyd.Field(default=None, description="Fly Ash, including types F, CL, and CH")
332
+ siFume: RatioFloat | None = pyd.Field(default=None, description="Silica Fume")
333
+ gg45: RatioFloat | None = pyd.Field(default=None, description="Ground Glass, 45um or smaller")
334
+ natPoz: RatioFloat | None = pyd.Field(default=None, description="Natural pozzolan")
335
+ mk: RatioFloat | None = pyd.Field(default=None, description="Metakaolin")
336
+ CaCO3: RatioFloat | None = pyd.Field(default=None, description="Limestone")
337
+ other: RatioFloat | None = pyd.Field(default=None, description="Other SCMs")
338
+
339
+
340
+ class TypicalApplication(BaseOpenEpdSchema):
341
+ """Concrete typical application."""
342
+
343
+ fnd: bool | None = pyd.Field(description="Foundation", default=None)
344
+ sog: bool | None = pyd.Field(description="Slab on Grade", default=None)
345
+ hrz: bool | None = pyd.Field(description="Elevated Horizontal", default=None)
346
+ vrt_wall: bool | None = pyd.Field(description="Vertical Wall", default=None)
347
+ vrt_column: bool | None = pyd.Field(description="Vertical Column", default=None)
348
+ vrt_other: bool | None = pyd.Field(description="Vertical Other", default=None)
349
+ sht: bool | None = pyd.Field(description="Shotcrete", default=None)
350
+ cdf: bool | None = pyd.Field(description="Flowable Fill (CDF,default=None)", default=None)
351
+ sac: bool | None = pyd.Field(description="Sidewalk and Curb", default=None)
352
+ pav: bool | None = pyd.Field(description="Paving", default=None)
353
+ oil: bool | None = pyd.Field(description="Oil Patch", default=None)
354
+ grt: bool | None = pyd.Field(description="Cement Grout", default=None)
355
+ ota: bool | None = pyd.Field(description="Other", default=None)
356
+
357
+
358
+ class ConcreteV1Options(BaseOpenEpdSchema):
359
+ """Concrete options."""
360
+
361
+ lightweight: bool | None = pyd.Field(description="Lightweight", default=None)
362
+ plc: bool | None = pyd.Field(description="Portland Limestone Cement", default=None)
363
+ scc: bool | None = pyd.Field(description="Self Compacting", default=None)
364
+ finishable: bool | None = pyd.Field(description="Finishable", default=None)
365
+ air: bool | None = pyd.Field(description="Air Entrainment", default=None)
366
+ co2: bool | None = pyd.Field(description="CO2 Curing", default=None)
367
+ white: bool | None = pyd.Field(description="White Cement", default=None)
368
+ fiber_reinforced: bool | None = pyd.Field(description="Fiber reinforced", default=None)
369
+
370
+
371
+ class ReadyMixV1(BaseOpenEpdHierarchicalSpec):
372
+ """Concretes to be mixed and then poured on-site."""
373
+
374
+ _EXT_VERSION = "1.0"
375
+
376
+
377
+ class FlowableFillV1(BaseOpenEpdHierarchicalSpec):
378
+ """
379
+ Flowable fill is a slurry that is placed as a flowable liquid (high slump) and sets with no compaction.
380
+
381
+ It is often used in tight or restricted access areas where placing and compacting
382
+ fill is difficult. Applications include filling large voids such as abandoned underground storage
383
+ tanks, basements, tunnels, mines, and sewers. It can also be used as paving sub-base, bridge
384
+ abutment, and retaining wall backfill. Also called Controlled Density Fill (CDF) or Controlled
385
+ Low Strength Materials (CLSMs). These materials typically have compressive strengths
386
+ under 1200 psi.
387
+ """
388
+
389
+ _EXT_VERSION = "1.0"
390
+
391
+
392
+ class OilPatchV1(BaseOpenEpdHierarchicalSpec):
393
+ """
394
+ Concretes for use in petroleum extraction wells and similar applications.
395
+
396
+ Includes foamed cement; often called cement in the drilling industry. Differs from
397
+ flowable fill and grout in that it contains no sand or other aggregates.
398
+ """
399
+
400
+ _EXT_VERSION = "1.0"
401
+
402
+
403
+ class ConcretePavingV1(BaseOpenEpdHierarchicalSpec):
404
+ """Concrete paving."""
405
+
406
+ _EXT_VERSION = "1.0"
407
+
408
+
409
+ class ShotcreteV1(BaseOpenEpdHierarchicalSpec):
410
+ """Concretes sprayed on a target."""
411
+
412
+ _EXT_VERSION = "1.0"
413
+
414
+
415
+ class CementGroutV1(BaseOpenEpdHierarchicalSpec):
416
+ """
417
+ Cement grouting is a slurry that is placed as a flowable liquid.
418
+
419
+ It is an effective material for filling and
420
+ strengthening granular soils, voids in rocks, foundation underpinnings, and other underground voids. Also called
421
+ structural grout, these materials typically impart significant compressive strength to the system.
422
+
423
+ """
424
+
425
+ _EXT_VERSION = "1.0"
426
+
427
+
428
+ class ConcreteV1(BaseOpenEpdHierarchicalSpec):
429
+ """Concrete spec."""
430
+
431
+ _EXT_VERSION = "1.0"
432
+
433
+ strength_28d: PressureMPaStr | None = pyd.Field(
434
+ default=None, example="30 MPa", description="Concrete strength after 28 days"
435
+ )
436
+ strength_early: PressureMPaStr | None = pyd.Field(
437
+ default=None,
438
+ example="30 MPa",
439
+ description="A strength spec which is to be reached earlier than 28 days (e.g. 3d)",
440
+ )
441
+ strength_early_d: Literal[3, 7, 14] | None = pyd.Field(default=None, description="Test Day for the Early Strength")
442
+ strength_late: PressureMPaStr | None = pyd.Field(
443
+ default=None,
444
+ example="30 MPa",
445
+ description="A strength spec which is to be reached later than 28 days (e.g. 42d)",
446
+ )
447
+ strength_late_d: Literal[42, 56, 72, 96, 120] | None = pyd.Field(
448
+ default=None, description="Test Day for the Late Strength"
449
+ )
450
+ slump: LengthMmStr | None = pyd.Field(description="Minimum test slump", example="40 mm", default=None)
451
+ w_c_ratio: RatioFloat | None = pyd.Field(description="Ratio of water to cement", example=0.3, default=None)
452
+ aci_exposure_classes: list[AciExposureClass] = pyd.Field(
453
+ description=(AciExposureClass.__doc__ or "").lstrip(), default_factory=list
454
+ )
455
+ csa_exposure_classes: list[CsaExposureClass] = pyd.Field(
456
+ description=(CsaExposureClass.__doc__ or "").lstrip(), default_factory=list
457
+ )
458
+ en_exposure_classes: list[EnExposureClass] = pyd.Field(
459
+ description=(EnExposureClass.__doc__ or "").lstrip(), default_factory=list
460
+ )
461
+ cementitious: Cementitious | None = pyd.Field(
462
+ default=None,
463
+ description="List of cementitious materials, and proportion by mass. Each field is 0 to 1.",
464
+ )
465
+ application: TypicalApplication | None = pyd.Field(description="Typical Application", default=None)
466
+ options: ConcreteV1Options | None = pyd.Field(description="Concrete options", default=None)
467
+
468
+ # Nested specs
469
+ ReadyMix: ReadyMixV1 | None = None
470
+ FlowableFill: FlowableFillV1 | None = None
471
+ OilPatch: OilPatchV1 | None = None
472
+ ConcretePaving: ConcretePavingV1 | None = None
473
+ Shotcrete: ShotcreteV1 | None = None
474
+ CementGrout: CementGroutV1 | None = None
475
+
476
+ _compressive_strength_unit_validator = pyd.validator("strength_28d", allow_reuse=True, check_fields=False)(
477
+ validate_unit_factory(OpenEPDUnit.MPa)
478
+ )
479
+ _strength_early_unit_validator = pyd.validator("strength_early", allow_reuse=True)(
480
+ validate_unit_factory(OpenEPDUnit.MPa)
481
+ )
482
+ _strength_late_unit_validator = pyd.validator("strength_late", allow_reuse=True)(
483
+ validate_unit_factory(OpenEPDUnit.MPa)
484
+ )
485
+
486
+ @pyd.root_validator
487
+ def _late_validator(cls, values):
488
+ together_validator("strength_late", "strength_late_d", values)
489
+ return values
490
+
491
+ @pyd.root_validator
492
+ def _early_validator(cls, values):
493
+ together_validator("strength_early", "strength_early_d", values)
494
+ return values
495
+
496
+
497
+ class PrecastConcreteV1(BaseOpenEpdHierarchicalSpec):
498
+ """Precast Concrete spec."""
499
+
500
+ _EXT_VERSION = "1.0"
501
+
502
+ strength_28d: PressureMPaStr | None = pyd.Field(
503
+ default=None, example="30 MPa", description="Concrete strength after 28 days"
504
+ )
505
+
506
+ lightweight: bool | None = pyd.Field(description="Lightweight", default=None)
507
+ steel_mass_percentage: RatioFloat | None = pyd.Field(
508
+ default=None,
509
+ description="Percent of total mass that is steel reinforcement. Steel reinforcement "
510
+ "substantially changes functional performance and usually adds substantial GWP "
511
+ "per declared unit.",
512
+ )
513
+
514
+ insulated: bool | None = pyd.Field(description="Insulated", default=None)
515
+ gfrc: bool | None = pyd.Field(description="Glass Fiber Reinforced Concrete", default=None)
516
+
517
+ _compressive_strength_unit_validator = pyd.validator("strength_28d", allow_reuse=True)(
518
+ validate_unit_factory(OpenEPDUnit.MPa)
519
+ )