Source code for viiapackage.strengthening.l6.l6j

### ===================================================================================================================
###   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 ### ===================================================================================================================