示例#1
0
def minimizeUtilization(vessel,
                        layerNumber,
                        bounds,
                        dropIndicies,
                        puckProperties,
                        burstPressure,
                        targetFunction=getMaxFibreFailureByAngle,
                        verbose=False):
    """Minimizes puck fibre failure criterion in a certain region of angles

    """
    tol = 1e-2
    args = [
        vessel, layerNumber, puckProperties, burstPressure, dropIndicies,
        verbose
    ]
    if 0:
        popt = minimize_scalar(
            targetFunction,
            method='bounded',
            bounds=bounds,  # bounds of the angle
            args=args,
            options={
                "maxiter": 1000,
                'disp': 1,
                "xatol": tol
            })
    else:
        popt = differential_evolution(targetFunction,
                                      bounds=(bounds, ),
                                      args=[args],
                                      atol=tol * 10)
    if not popt.success:
        raise Tankoh2Error('Could not finde optimal solution')
    x, funVal, iterations = popt.x, popt.fun, popt.nfev
    if hasattr(x, '__iter__'):
        x = x[0]
    if targetFunction is getMaxFibreFailureByAngle:
        windLayer(vessel, layerNumber, x)
    else:
        windHoopLayer(vessel, layerNumber, x)
    return x, funVal, iterations
示例#2
0
def optimizeAngle(vessel,
                  targetPolarOpening,
                  layerNumber,
                  minAngle,
                  verbose=False,
                  targetFunction=getPolarOpeningDiffByAngle):
    """optimizes the angle of the actual layer to realize the desired polar opening

    :param vessel: vessel object
    :param targetPolarOpening: polar opening radius that should be realized
    :param layerNumber: number of the actual layer
    :param verbose: flag if more output should be given
    :return: 3-tuple (resultAngle, polar opening, number of runs)
    """
    tol = 1e-2
    popt = minimize_scalar(
        targetFunction,
        method='bounded',
        bounds=[minAngle, 75],  # bounds of the angle
        args=[vessel, layerNumber, targetPolarOpening, verbose],
        options={
            "maxiter": 1000,
            'disp': 1,
            "xatol": tol
        })
    if not popt.success:
        raise Tankoh2Error('Could not finde optimal solution')
    angle, funVal, iterations = popt.x, popt.fun, popt.nfev
    if popt.fun > 1 and targetFunction is getPolarOpeningDiffByAngle:
        # desired polar opening not met. This happens, when polar opening is near fitting.
        # There is a discontinuity at this point. Switch target function to search from the fitting side.
        angle, funVal, iterations = optimizeAngle(
            vessel, targetPolarOpening, layerNumber, verbose,
            getNegAngleAndPolarOpeningDiffByAngle)
    else:
        windLayer(vessel, layerNumber, angle)
    #angle2 = vessel.estimateCylinderAngle(layerNumber, targetPolarOpening)
    #r = angle / angle2
    return angle, funVal, iterations
示例#3
0
def getMaxFibreFailureByAngle(angle, args):
    """Returns the maximum puck fibre failure index after setting and winding the given angle"""
    vessel, layerNumber, puckProperties, burstPressure, dropIndicies, verbose = args
    if hasattr(angle, '__iter__'):
        angle = angle[0]
    if angle is not None:
        actualPolarOpening = windLayer(vessel, layerNumber, angle, verbose)
        if actualPolarOpening is np.inf:
            return np.inf
    maxFF, maxIndex = _getMaxFibreFailure(args)
    if verbose:
        log.info(f'angle {angle}, max fibre failure {maxFF}, index {maxIndex}')
    return maxFF
示例#4
0
def getMaxFibreFailureByShift(shift, args):
    """Returns the maximum puck fibre failure index after setting and winding the given hoop layer shift"""
    if hasattr(shift, '__iter__'):
        shift = shift[0]
    vessel, layerNumber, puckProperties, burstPressure, dropIndicies, verbose = args
    vessel.setHoopLayerShift(layerNumber, shift, True)
    actualPolarOpening = windLayer(vessel, layerNumber, verbose=verbose)
    if actualPolarOpening is np.inf:
        return np.inf
    maxFF, maxIndex = _getMaxFibreFailure(args)
    if verbose:
        log.info(
            f'hoop shift {shift}, max fibre failure {maxFF}, index {maxIndex}')
    return maxFF
示例#5
0
def designLayers(vessel, maxLayers, minPolarOpening, puckProperties,
                 burstPressure, runDir, composite, compositeArgs, verbose):
    """
    Strategy:
    #. Start with hoop layer
    #. Second layer:
        #. Maximize layer angle that still attaches to the fitting
        #. add layer with this angle
    #. Iteratively perform the following
    #. Get puck fibre failures
    #. Check if puck reserve factors are satisfied - if yes end iteration
    #. Reduce relevant locations to
        #. 1 element at cylindrical section and
        #. every element between polar opening radii of 0 and of 70° angle layers
    #. identify critical element
    #. if critical element is in cylindrical section
        #. add hoop layer
        #. next iteration step
    #. if most loaded element is in dome area:
        #. Define Optimization bounds [minAngle, 70°] and puck result bounds
        #. Minimize puck fibre failue:
            #. Set angle
            #. Use analytical linear solver
            #. return max puck fibre failure
        #. Apply optimal angle to actual layer
        #. next iteration step
    """

    vessel.resetWindingSimulation()

    anglesShifts = []  # list of 2-tuple with angle and shift for each layer
    show = False
    save = True
    layerNumber = 0
    iterations = 0
    liner = vessel.getLiner()
    dome = liner.getDome1()

    radiusDropThreshold = windLayer(vessel, layerNumber, 70)
    mandrel = vessel.getVesselLayer(layerNumber).getOuterMandrel1()
    dropRadiusIndex = np.argmin(
        np.abs(mandrel.getRArray() - radiusDropThreshold))
    elementCount = mandrel.getRArray().shape[0] - 1
    minAngle, _, _ = optimizeAngle(
        vessel,
        minPolarOpening,
        layerNumber,
        1.,
        False,
        targetFunction=getAngleAndPolarOpeningDiffByAngle)

    rMax = mandrel.getRArray()[0]
    dropHoopIndexStart = np.argmax(
        (-mandrel.getRArray() + rMax) > rMax * 1e-4) - 10
    dropHoopIndexEnd = np.argmin(
        np.abs(mandrel.getRArray() - dome.cylinderRadius * 0.98))
    hoopOrHelicalIndex = np.argmin(
        np.abs(mandrel.getRArray() - dome.cylinderRadius * 0.99))
    maxHoopShift = mandrel.getLArray(
    )[dropHoopIndexEnd] - liner.cylinderLength / 2
    dropHoopIndicies = list(range(0, dropHoopIndexStart)) + list(
        range(dropHoopIndexEnd, elementCount))
    dropHelicalIndicies = range(0, hoopOrHelicalIndex)

    # introduce layer up to the fitting. Optimize required angle
    printLayer(layerNumber, verbose)
    angle, _, _ = optimizeAngle(
        vessel,
        minPolarOpening,
        layerNumber,
        minAngle,
        False,
        targetFunction=getNegAngleAndPolarOpeningDiffByAngle)
    anglesShifts.append((angle, 0))
    layerNumber += 1

    # add hoop layer
    resHoop = optimizeHoop(vessel, layerNumber, puckProperties, burstPressure,
                           dropHoopIndicies, maxHoopShift, verbose)
    shift, funcVal, loopIt, newDesignIndex = resHoop
    windHoopLayer(vessel, layerNumber, shift)
    anglesShifts.append((90, shift))

    #printLayer(layerNumber, verbose)
    #windLayer(vessel, layerNumber, 90)
    #anglesShifts.append((90.,0))

    # create other layers
    for layerNumber in range(layerNumber + 1, maxLayers):
        printLayer(layerNumber, verbose)
        elemIdxmax, puckFF = getCriticalElementIdxAndPuckFF(
            vessel, puckProperties, None, burstPressure)

        if puckFF.max().max() < 1:
            if verbose:
                log.info('End Iteration')
            # stop criterion reached
            columns = [
                'lay{}_{:04.1f}'.format(i, angle)
                for i, (angle, _) in enumerate(anglesShifts)
            ]
            puckFF.columns = columns
            plotDataFrame(False, os.path.join(runDir,
                                              f'puck_{layerNumber}.png'),
                          puckFF)
            layerNumber -= 1
            break
        elif layerNumber > maxLayers:
            raise Tankoh2Error(
                'Reached max layers. You need to specify more initial layers')

        # add one layer
        composite = getComposite([a for a, _ in anglesShifts] + [90],
                                 [compositeArgs[2]] * (layerNumber + 1),
                                 *compositeArgs[1:])
        vessel.setComposite(composite)
        resetVesselAnglesShifts(anglesShifts, vessel)

        #  check zone of highest puck values
        if elemIdxmax < hoopOrHelicalIndex:
            resHoop = optimizeHoop(vessel, layerNumber, puckProperties,
                                   burstPressure, dropHoopIndicies,
                                   maxHoopShift, verbose)
            resHelical = optimizeHelical(vessel, layerNumber, puckProperties,
                                         burstPressure, minPolarOpening,
                                         dropHoopIndicies, verbose)
            if resHoop[1] < resHelical[
                    1] * 1.25:  #  puck result with helical layer must be 1.25 times better
                # add hoop layer
                shift, funcVal, loopIt, newDesignIndex = resHoop
                windHoopLayer(vessel, layerNumber, shift)
                anglesShifts.append((90, shift))
            else:
                angle, funcVal, loopIt, newDesignIndex = resHelical
                windLayer(vessel, layerNumber, angle)
                anglesShifts.append((angle, 0))
        else:
            angle, funcVal, loopIt, newDesignIndex = optimizeHelical(
                vessel, layerNumber, puckProperties, burstPressure,
                minPolarOpening, dropHelicalIndicies, verbose)

            anglesShifts.append((angle, 0))
        iterations += loopIt
        columns = [
            'lay{}_{:04.1f}'.format(i, angle)
            for i, (angle, _) in enumerate(anglesShifts[:-1])
        ]
        puckFF.columns = columns
        plotDataFrame(False,
                      os.path.join(runDir, f'puck_{layerNumber}.png'),
                      puckFF,
                      None,
                      vlines=[elemIdxmax, hoopOrHelicalIndex, newDesignIndex],
                      vlineColors=['red', 'black', 'green'],
                      title='puck fibre failure')

    vessel.finishWinding()
    results = getLinearResults(vessel, puckProperties, layerNumber,
                               burstPressure)
    if show or save:
        plotStressEpsPuck(
            show,
            os.path.join(runDir, f'sig_eps_puck_{layerNumber}.png')
            if save else '', *results)
        thicknesses = getLayerThicknesses(vessel)
        columns = [
            'lay{}_{:04.1f}'.format(i, angle)
            for i, (angle, _) in enumerate(anglesShifts)
        ]
        thicknesses.columns = columns
        plotDataFrame(show,
                      os.path.join(runDir,
                                   f'thicknesses_{getTimeString()}.png'),
                      thicknesses,
                      title='layer thicknesses')

    # get volume and surface area
    stats = vessel.calculateVesselStatistics()
    frpMass = stats.overallFRPMass  # in [kg]

    volume = liner.getVolume()  # [l]
    r, x = dome.getRCoords(), dome.getXCoords()
    areaDome = np.pi * (r[:-1] + r[1:]) * np.sqrt((r[:-1] - r[1:])**2 +
                                                  (x[:-1] - x[1:])**2)
    area = 2 * np.pi * liner.cylinderRadius * liner.cylinderLength + 2 * np.sum(
        areaDome)  # [mm**2]
    area *= 1e-6  # [m**2]
    return frpMass, volume, area, composite, iterations, anglesShifts
示例#6
0
def resetVesselAnglesShifts(anglesShifts, vessel):
    for layerNumber, (angle, shift) in enumerate(anglesShifts):
        if abs(angle - 90) < 1e-2:
            windHoopLayer(vessel, layerNumber, shift)
        else:
            windLayer(vessel, layerNumber, angle)