### ===================================================================================================================
### L6-J strengthening measure
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING
from copy import deepcopy
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.fem_math import fem_greater, fem_smaller
# References for functions and classes in the viiaPackage
from viiapackage.strengthening.helper_functions import viia_check_measure_in_gmc
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
### ===================================================================================================================
### 2. Function to create L6-J strengthening measures
### ===================================================================================================================
[docs]def viia_l6j(project: ViiaProject, variant: int, add_slab: bool = False):
"""
This function creates an L6-J-measure which adds a concrete slab to the existing foundation strips of the building.
It thereby prevents uncontrolled displacement due to loss of load bearing capacity. Existing foundation strips are
effectively merged into one slab, openings in the slabs are removed.
.. warning:: Function is currently not available, it requires updates, please send request to the VIIA automating
team.
.. note:: This function is based on an algorithm in which the foundation strips are ordered according to their
coordinates, after which the strips are connected by searching for points of consecutive strips that are closest
to each other. The algorithm seems to work well, but it is very hard to capture all possibilities of defined
foundation strips. It is therefore possible that errors occur or that the outcome of the function is not the
desired foundation slab.
.. note:: For a merged foundation strip (add_slab=False) the geometry and material are equal to that of the first
foundation strip in the list.
Input:
- project (obj): VIIA project object containing collections of fem objects and project variables.
- variant (int): The variant number of the measure that is in the GMC.
- add_slab (bool): Default value is False. If addSlab is True, a slab is added just above the foundation strips
with reinforcement Ø12-150, effectively connecting all foundation walls to prevent uncontrolled deformations.
If False, the existing foundation strips are merged into one strip without openings.
Output:
- Foundation strips are merged into one slab and modelled in DIANA, or
- Slab is added just above the foundation strips and modelled in DIANA
For example:
>>> project.viia_l6j()
This example will apply the L6-J measure on the building, merging all foundation strips into one strip.
>>> project.viia_l6j(add_slab=True)
This example will apply the L6-J measure on the building, a new slab is created based one the definition of the
foundation strips. The slab will be positioned just above the existing strips.
"""
raise NotImplementedError(
"ERROR: Function to apply L6-J measure is currently not available, script needs updates. Please contact the "
"VIIA automation team.")
# Check if measure is in GMC
measure_type = 'L6-J'
measure_sub_type = f"{measure_type}-{int(variant)}"
viia_check_measure_in_gmc(project=project, measure_sub_type=measure_sub_type)
# Create copy of first strip and remove openings
mergedstrip = deepcopy(project.collections.fstrips[0])
for i in range(1, len(mergedstrip.points)):
del mergedstrip.points[i]
# When there is more than 1 foundation strip, these must be merged
if len(project.collections.fstrips) != 1:
# Find extreme coordinates of individual strips and all strips together
extremesfstrips = []
# Extremes of all strips together
stripsxmin = project.collections.fstrips[0].points[0][0][0]
stripsxmax = project.collections.fstrips[0].points[0][0][0]
stripsymin = project.collections.fstrips[0].points[0][0][1]
stripsymax = project.collections.fstrips[0].points[0][0][1]
for fstrip in project.collections.fstrips:
# Extremes of individual strip
stripxmin = fstrip.points[0][0][0]
stripxmax = fstrip.points[0][0][0]
stripymin = fstrip.points[0][0][1]
stripymax = fstrip.points[0][0][1]
for i in range(1, len(fstrip.points[0])):
if fem_greater(stripxmin, fstrip.points[0][i][0]): stripxmin = fstrip.points[0][i][0]
if fem_greater(fstrip.points[0][i][0], stripxmax): stripxmax = fstrip.points[0][i][0]
if fem_greater(stripymin, fstrip.points[0][i][1]): stripymin = fstrip.points[0][i][1]
if fem_greater(fstrip.points[0][i][1], stripymax): stripymax = fstrip.points[0][i][1]
extremesfstrips.append([stripxmin, stripxmax, stripymin, stripymax])
if fem_greater(stripsxmin, stripxmin): stripsxmin = stripxmin
if fem_greater(stripxmax, stripsxmax): stripsxmax = stripxmax
if fem_greater(stripsymin, stripymin): stripsymin = stripymin
if fem_greater(stripymax, stripsymax): stripsymax = stripymax
sortedextremesfstrips = deepcopy(extremesfstrips)
# If total strips larger in x-direction, first sort strips according to stripymin, than to stripxmin
if fem_greater((stripsxmax - stripsxmin), (stripsymax - stripsymin)):
sortedextremesfstrips.sort(key=lambda ymin: ymin[2])
sortedextremesfstrips.sort(key=lambda xmin: xmin[0])
# If total strips larger in y-direction, first sort strips according to stripxmin, than to stripymin
else:
sortedextremesfstrips.sort(key=lambda xmin: xmin[0])
sortedextremesfstrips.sort(key=lambda ymin: ymin[2])
# Compare original and sorted lists
# This provides the list sortedindices, which can be used to order the fstrips
sortedindices = []
for i in range(0, len(sortedextremesfstrips)):
for j in range(0, len(extremesfstrips)):
if sortedextremesfstrips[i] == extremesfstrips[j]:
sortedindices.append(j)
break
# Order fstrips in list
project.collections.fstrips = [project.collections.fstrips[sortedindex] for sortedindex in sortedindices]
# If addSlab:
# A new slab is created based on the outline of the existing strips
# Else:
# In each iteration, mergedstrip and second fstrip are merged, the second strip is removed
# mergedstrip thus 'absorbs' all other strips
# Iterate through fstrips
for iterationcounter in range(0, len(project.collections.fstrips) - 1):
# Select strip in list
if add_slab:
# Slab is added, original strips are not removed, therefore shift in list
fstrip1 = deepcopy(project.collections.fstrips[iterationcounter + 1])
else:
# No slab is added, original strips are merged, take second strip in list in each iteration
fstrip1 = deepcopy(project.collections.fstrips[1])
# Remove openings
for i in range(1, len(fstrip1.points)):
del fstrip1.points[i]
# Check if both strips are defined with the same orientation
nv0 = _math._viiaNormalVector(mergedstrip.points[0])
nv1 = _math._viiaNormalVector(fstrip1.points[0])
# Otherwise reverse direction of fstrip1
if _math._viiaDotProductVector(nv0, nv1) == -1:
fstrip1.points[0].reverse()
# In the coming procedure, points of fstrip1 are found that are closest to fstrip0. This is done by
# iterating through the points of fstrip1 and computing their minimum distances to edges of fstrip0.
p0 = [0.0, 0.0, 0.0]
closestpoints1 = [0, 0, 0, p0, 10 * stripsxmax - stripsxmin]
closestpoints2 = [0, 0, 0, p0, 10 * stripsxmax - stripsxmin]
# Iterate through points of fstrip1
for i1 in range(len(fstrip1.points[0])):
closestpoints = [0, 0, 0, p0, 10 * stripsxmax - stripsxmin]
p1i = fstrip1.points[0][i1]
# Iterate through edges of fstrip0
for i0 in range(len(mergedstrip.points[0])):
if i0 == len(mergedstrip.points[0]) - 1:
j0 = 0
else:
j0 = i0 + 1
# Select to points of fstrip0 that form the edge
p0i = mergedstrip.points[0][i0]
p0j = mergedstrip.points[0][j0]
# If point of fstrip1 equal to one of the points of fstrip0, closestpoint of this iteration found
if p1i == p0i:
closestpoints = [i0, j0, i1, p0i, 0.0]
break
elif p1i == p0j:
closestpoints = [i0, j0, i1, p0j, 0.0]
break
# Else, compute closest distance and intersection of point of fstrip1 to edge of fstrip0
else:
line = [p0i, p0j]
distance, vector, intersection = _math._viiaDistancePointToLine3DSegment(p1i, line)
# Update closestpoints if distance lower than found until now
# NOTE: closestpoints only holds the closest point for current point of fstrip1
if fem_smaller(distance, closestpoints[4]):
if intersection == p0i:
closestpoints = [i0, j0, i1, p0i, distance]
elif intersection == p0j:
closestpoints = [i0, j0, i1, p0j, distance]
else:
closestpoints = [i0, j0, i1, intersection, distance]
# Iteration for current point of fstrip1 finished
# Now check if it also closest to fstrip0 of all points of fstrip1 that have yet been considered
# Then update closestpoints1 or closestpoints2
if fem_greater(closestpoints1[4], closestpoints[4]):
closestpoints2 = closestpoints1
closestpoints1 = closestpoints
elif fem_greater(closestpoints2[4], closestpoints[4]):
closestpoints2 = closestpoints
# If both distances zero, cannot find any closer points, break from iteration
if closestpoints1[4] == 0 and closestpoints2[4] == 0:
break
closestpointslist = []
# Check if the intersections are exactly the same, then only add the one with the shortest distance to list
# This seems extremely rare, the behaviour in this case has NOT been tested!
if closestpoints1[3] == closestpoints2[3]:
if fem_smaller(closestpoints1[4], closestpoints2[4]):
closestpointslist.append(closestpoints1)
else:
closestpointslist.append(closestpoints2)
# Check if the intersections are both in between the same points of strip0, then check order
elif closestpoints1[0] == closestpoints2[0] and closestpoints1[1] == closestpoints2[1]:
# Compute distance from first point of edge to intersections
distance1 = _math._viiaDistanceCoordinates(mergedstrip.points[0][closestpoints1[0]], closestpoints1[3])
distance2 = _math._viiaDistanceCoordinates(mergedstrip.points[0][closestpoints2[0]], closestpoints2[3])
# Put intersection with biggest distance first in list
# Points can namely be inserted and therefore points with the highest indices must be inserted first
if fem_smaller(distance1, distance2):
closestpointslist.append(closestpoints2)
closestpointslist.append(closestpoints1)
else:
closestpointslist.append(closestpoints1)
closestpointslist.append(closestpoints2)
else:
# Put intersection with highest index first in list, because these must be inserted first
if fem_smaller(closestpoints1[1], closestpoints2[1]):
closestpointslist = [closestpoints2, closestpoints1]
else:
closestpointslist = [closestpoints1, closestpoints2]
for closestpoints in closestpointslist:
i0 = closestpoints[0]
j0 = closestpoints[1]
i1 = closestpoints[2]
intersection = closestpoints[3]
p1i = fstrip1.points[0][i1]
p0i = mergedstrip.points[0][i0]
p0j = mergedstrip.points[0][j0]
# If intersections are not yet in points of strips, add them
if intersection != p1i:
fstrip1.points[0][i1] = intersection
if intersection != p0i and intersection != p0j:
mergedstrip.points[0].insert(j0, intersection)
# Now iterate through points of both strips, to compose a new list of points that forms the merged strip
# Initiate variables
pointindex0 = 0
pointindex1 = 0
mergedstrippoints = []
# Start iterating through points of fstrip0 at pointindex0 = 0
# For each point, check if the same point can also be found in the points of fstrip1
# If so, the first duplicate point is found, the current point is then added after which the loop is left
duplicate = False
while duplicate == False:
try:
pointindex1 = fstrip1.points[0].index(mergedstrip.points[0][pointindex0])
duplicate = True
except:
pass
mergedstrippoints.append(mergedstrip.points[0][pointindex0])
# Update counter
pointindex0 += 1
# pointindex1 now gives the duplicate point, add 1 to go to the next point in list
pointindex1 += 1
if pointindex1 == len(fstrip1.points[0]):
pointindex1 = 0
# Now perform a similar loop through the points of fstrip1
# When the second duplicate point is found, add current point and exit loop
duplicate = False
while duplicate == False:
try:
pointindex0 = mergedstrip.points[0].index(fstrip1.points[0][pointindex1])
duplicate = True
except:
pass
mergedstrippoints.append(fstrip1.points[0][pointindex1])
# Update counter
pointindex1 += 1
# If pointindex1 exceeds number of points, reset to 0
if pointindex1 == len(fstrip1.points[0]):
pointindex1 = 0
# pointindex0 now gives the duplicate point, add 1 to go to the next point in list
pointindex0 += 1
if pointindex0 == len(mergedstrip.points[0]):
pointindex0 = 0
# Iterate trough remaining points of fstrip0 and add them to fstrippoints
while pointindex0 != 0:
mergedstrippoints.append(mergedstrip.points[0][pointindex0])
# Update counter
pointindex0 += 1
# If pointindex0 exceeds number of points, reset to 0
# This effectively means that the loop is left
if pointindex0 == len(mergedstrip.points[0]):
pointindex0 = 0
# Update the points of mergedstrip
mergedstrip.points[0] = mergedstrippoints
if not add_slab:
# Remove second strip (that was merged with the first) from all lists and dictionaries
for floor in project.collections.floors:
if floor.name == project.collections.fstrips[1].name:
project.collections.floors.remove(floor)
break
for surfaceSupport in project.collections.surfaceSupports:
if surfaceSupport.connectingShape.name == project.collections.fstrips[1].name:
project.collections.surfaceSupports.remove(surfaceSupport)
project.collections.supports.remove(surfaceSupport)
break
for shape in project.collections.shapes:
if shape.name == project.collections.fstrips[1].name:
project.collections.shapes.remove(shape)
break
for geometryObject in project.collections.geometriesObjects:
if geometryObject.name == project.collections.fstrips[1].geometry:
for i in range(len(project.collections.geometries[geometryObject.name])):
item = project.collections.geometries[geometryObject.name][i]
if item == project.collections.fstrips[1].name:
del project.collections.geometries[geometryObject.name][i]
break
break
for dataObject in project.collections.datasObjects:
if dataObject.name == project.collections.fstrips[1].data:
for i in range(len(project.collections.datas[dataObject.name])):
item = project.collections.datas[dataObject.name][i]
if item == project.collections.fstrips[1].name:
del project.collections.datas[dataObject.name][i]
break
break
for materialObject in project.collections.materialsObjects:
if materialObject.name == project.collections.fstrips[1].material:
for i in range(len(project.collections.materials[materialObject.name])):
item = project.collections.materials[materialObject.name][i]
if item == project.collections.fstrips[1].name:
del project.collections.materials[materialObject.name][i]
break
break
# Finally, remove from foundation strips
del project.collections.fstrips[1]
if add_slab:
# Change orientation of points if necessary, so that normal vector points upward
nv0 = _math._viiaNormalVector(mergedstrip.points[0])
if fem_smaller(nv0[2], 0):
for i in range(0, len(mergedstrip.points)):
mergedstrip.points[i].reverse()
nv0 = _math._viiaNormalVector(mergedstrip.points[0])
# Compute slab eccentricity
stripthickness = project.collections.fstrips[0].geometry.split('-')[1]
slabeccentricityshift = float(stripthickness) / 2000 +\
project.project_specific['strengthening_measures']['L6-J']['thickness'] / 2
slabeccentricity = [nv0[0] * slabeccentricityshift, nv0[1] * slabeccentricityshift,
nv0[2] * slabeccentricityshift]
# Define slab geometry name with eccentricity
mergedstripGeometryNamesplit = mergedstrip.geometry.split('-')
mergedstripGeometryNamesplit[1] = \
str(int(project.project_specific['strengthening_measures']['L6-J']['thickness'] * 1000))
floorGeometryNameNew = '-'.join(mergedstripGeometryNamesplit)
floorGeometryNameNew += '-(' + str(slabeccentricity[0]) + ',' + str(slabeccentricity[1]) + ',' + str(
slabeccentricity[2]) + ')'
# Define slab name
floorNameNew = \
'F1-VLOEREN-L6J-' + project.project_specific['strengthening_measures']['L6-J']['concrete'] + '-' +\
str(int(project.project_specific['strengthening_measures']['L6-J']['thickness'] * 1000)) + '-1'
# Create slab
project.create_floor(
floorNameNew, project.project_specific['strengthening_measures']['L6-J']['concrete'],
floorGeometryNameNew, mergedstrip.points)
# Compute reinforcement eccentricities
reinforcementeccentricitydown = [0.0, 0.0, 0.0]
reinforcementeccentricityup = [0.0, 0.0, 0.0]
for i in range(0, 3):
reinforcementeccentricitydown[i] = slabeccentricity[i] - nv0[i] * (
project.project_specific['strengthening_measures']['L6-J']['thickness'] / 2 -
project.project_specific['strengthening_measures']['L6-J']['coverage'])
reinforcementeccentricityup[i] = slabeccentricity[i] + nv0[i] * (
project.project_specific['strengthening_measures']['L6-J']['thickness'] / 2 -
project.project_specific['strengthening_measures']['L6-J']['coverage'])
# Define reinforcement geometry names WITHOUT eccentricities, the eccentricity is accounted for in the points
reinforcementNameDown = floorNameNew.split('-')[0] + "-VLOEREN-L6J-WAP-DOWN-B500-" + floorNameNew[-1]
reinforcementNameUp = floorNameNew.split('-')[0] + "-VLOEREN-L6J-WAP-UP-B500-" + floorNameNew[-1]
materialNameReinforcement = "WAP-B500"
geometryNameReinforcementDown = "L6J-WAP-1x2R12-150-Down-(" + str(nv0[0]) + ',' + str(nv0[1]) + ',' + str(
nv0[2]) + ')'
geometryNameReinforcementUp = "L6J-WAP-1x2R12-150-Up-(" + str(nv0[0]) + ',' + str(nv0[1]) + ',' + str(
nv0[2]) + ')'
# Compute points for reinforcements with eccentricities
newPointsDown = deepcopy(mergedstrip.points)
for i in range(len(newPointsDown)):
for j in range(len(newPointsDown[i])):
newPointsDown[i][j][0] = newPointsDown[i][j][0] + reinforcementeccentricitydown[0]
newPointsDown[i][j][1] = newPointsDown[i][j][1] + reinforcementeccentricitydown[1]
newPointsDown[i][j][2] = newPointsDown[i][j][2] + reinforcementeccentricitydown[2]
newPointsUp = deepcopy(mergedstrip.points)
for i in range(len(newPointsUp)):
for j in range(len(newPointsUp[i])):
newPointsUp[i][j][0] = newPointsUp[i][j][0] + reinforcementeccentricityup[0]
newPointsUp[i][j][1] = newPointsUp[i][j][1] + reinforcementeccentricityup[1]
newPointsUp[i][j][2] = newPointsUp[i][j][2] + reinforcementeccentricityup[2]
# Create reinforcements
reinf_down = project.create_surface_reinforcement(
reinforcementNameDown, newPointsDown, materialNameReinforcement, geometryNameReinforcementDown)
reinf_up = project.create_surface_reinforcement(
reinforcementNameUp, newPointsUp, materialNameReinforcement, geometryNameReinforcementUp)
# Find floor object and append strengthening and strengtheningShapes
for floor in project.collections.floors:
if floor.name == floorNameNew:
break
if floor.name == floorNameNew:
floor.add_meta_data({'strengthening': measure_sub_type})
add_strengthening_shape(shape=floor, strengthening_shape=reinf_down)
add_strengthening_shape(shape=floor, strengthening_shape=reinf_up)
else:
# Assign points of mergedstrip to first fstrip
project.collections.fstrips[0].points = mergedstrip.points
# Update name geometry, material etc.
# Here it is possible to set different material or geometrical properties
# Also possible to set different thickness, without removing the original foundation strips
fstripMaterialNameNew = project.collections.fstrips[0].material
fstripGeometryNameNew = project.collections.fstrips[0].geometry
fstripDataNameNew = project.collections.fstrips[0].data
thickness = fstripGeometryNameNew.split('-')[1]
fstripNameNew = project.collections.fstrips[0].name.split('-')[0] + "-" + fstripMaterialNameNew + "-" + thickness + "-1"
# Update dictionaries
_renewMaterialDictionary(fstripMaterialNameNew, project.collections.fstrips[0].material,
project.collections.fstrips[0].name, project.collections.fstrips[0].name)
_renewGeometryDictionary(fstripGeometryNameNew, project.collections.fstrips[0].geometry,
project.collections.fstrips[0].name, project.collections.fstrips[0].name)
_renewDataDictionary(fstripDataNameNew, project.collections.fstrips[0].data, project.collections.fstrips[0].name,
project.collections.fstrips[0].name)
# Update strip
project.collections.fstrips[0].material = fstripMaterialNameNew
project.collections.fstrips[0].geometry = fstripGeometryNameNew
project.collections.fstrips[0].data = fstripDataNameNew
# Assign new properties to strip
project.collections.fstrips[0].assignMaterial()
project.collections.fstrips[0].assignGeometry()
project.collections.fstrips[0].assignData()
# Update name, this is generally unnecessary
if project.collections.fstrips[0].name != fstripNameNew:
project.collections.fstrips[0].setName(fstripNameNew)
# Notifications for user
project.write_log("L6-J measure applied on building.")
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================