Exemplo n.º 1
0
def optimizeHelical(vessel, layerNumber, puckProperties, burstPressure,
                    minPolarOpening, dropIndicies, verbose):
    if verbose:
        log.info('Add helical layer')
    # get location of critical element
    minAngle, _, _ = optimizeAngle(
        vessel,
        minPolarOpening,
        layerNumber,
        1.,
        False,
        targetFunction=getAngleAndPolarOpeningDiffByAngle)
    bounds = [minAngle, 70]

    layerOk = False
    while not layerOk:
        angle, funcVal, loopIt = minimizeUtilization(vessel,
                                                     layerNumber,
                                                     bounds,
                                                     dropIndicies,
                                                     puckProperties,
                                                     burstPressure,
                                                     verbose=verbose)
        layerOk, bounds = checkThickness(vessel, angle, bounds)

    mandrel = vessel.getVesselLayer(layerNumber).getOuterMandrel1()
    newDesignIndex = np.argmin(
        np.abs(mandrel.getRArray() -
               vessel.getPolarOpeningR(layerNumber, True)))
    return angle, funcVal, loopIt, newDesignIndex
Exemplo n.º 2
0
def applySettings(filename=None):
    """reads settings from the settingsfile"""
    from tankoh2 import log
    defaultSettingsFileName = 'settings.json'
    searchDirs = ['.', os.path.dirname(__file__), os.path.dirname(os.path.dirname(os.path.dirname(__file__)))]
    if filename is None:
        for searchDir in searchDirs:
            if defaultSettingsFileName in os.listdir(searchDir):
                # look for settings file in actual folder
                filename = os.path.join(searchDir, defaultSettingsFileName)
    if filename is None:
        writeSettingsExample()
        raise Tankoh2Error(
            f'Could not find the settings file "{defaultSettingsFileName}" in the following folders: {searchDirs}.\n'
            f'An example settings file is written to ./{exampleFileName}.\n'
            f'Please add the requried settings and rename the file to {exampleFileName.replace("_example","")}.')

    with open(filename, 'r') as f:
        settings = json.load(f)
    major, minor = str(sys.version_info.major), str(sys.version_info.minor)
    pyVersionString = major+minor
    # v 0.90c
    pythonApiPath = os.path.join(settings['mycropychainPath'], f'pythonAPI\python{pyVersionString}_x64')
    if not os.path.exists(pythonApiPath):
        # v 0.95.2
        pythonApiPath = os.path.join(settings['mycropychainPath'], f'pythonAPI\python{pyVersionString}')
        if not os.path.exists(pythonApiPath):
            # v0.95.3
            pyVersionString = f'{major}_{minor}'
            pythonApiPath = os.path.join(settings['mycropychainPath'], f'pythonAPI\{pyVersionString}')
    #abaqusPythonLibPath = os.path.join(settings['mycropychainPath'], 'abaqus_interface_0_89')
    abaqusPythonLibPath = os.path.join(settings['mycropychainPath'], 'abaqus_interface_0_95')

    log.info(f'Append mycropychain path to sys path: {pythonApiPath}')
    sys.path.append(pythonApiPath)
    
    # import API - MyCrOChain GUI with activiated TCP-Connector needed
    try:
        import mycropychain as pychain
    except ModuleNotFoundError:
        try:
            if minor == '6':
                import mycropychain36 as pychain
            else: # minor == '8'
                import mycropychain38 as pychain
        except ModuleNotFoundError:

            raise Tankoh2Error('Could not find package "mycropychain". Please check the path to mycropychain in the '
                               'settings file.')
        else:
            if len(pychain.__dict__) < 10:
                # len(pychain.__dict__) was 8 on failure and 17 on success
                raise Tankoh2Error('Could not connect to mycropychain GUI. Did you start the GUI and activated "TCP Conn."?')

        # set general path information
        global myCrOSettings
        myCrOSettings = pychain.utility.MyCrOSettings()
        myCrOSettings.abaqusPythonLibPath = abaqusPythonLibPath
Exemplo n.º 3
0
def writeSettingsExample():
    """writes an example for settings"""
    from tankoh2 import log
    log.info(f'write file {exampleFileName}')
    with open('settings_example.json', 'w') as f:
        json.dump({'comment': "Please rename this example file to 'settings.json' and include the required settings. "
                              "For paths, please use '\\' or '/'",
                   'mycropychainPath': ''},
                  f, indent=2)
Exemplo n.º 4
0
def getPolarOpeningDiffByAngle(angle, args):
    vessel, layerNumber, targetPolarOpening, verbose = args
    if verbose:
        log.info(f'angle {angle}')
    actualPolarOpening = windLayer(vessel, layerNumber, angle, verbose)
    if verbose:
        log.info(
            f'angle {angle}, actualPolarOpening {actualPolarOpening}, targetPolarOpening {targetPolarOpening}'
        )
    return abs(targetPolarOpening - actualPolarOpening)
Exemplo n.º 5
0
def getAngleAndPolarOpeningDiffByAngle(angle, args):
    vessel, layerNumber, targetPolarOpening, verbose = args
    if verbose:
        log.info(f'angle {angle}')
    actualPolarOpening = windLayer(vessel, layerNumber, angle, verbose)
    funVal = angle + abs(targetPolarOpening - actualPolarOpening)
    if verbose:
        log.info(
            f'angle {angle}, target function val {funVal}, actualPolarOpening {actualPolarOpening}, targetPolarOpening {targetPolarOpening}'
        )
    return funVal
Exemplo n.º 6
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
Exemplo n.º 7
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
Exemplo n.º 8
0
def optimizeHoop(vessel, layerNumber, puckProperties, burstPressure,
                 dropIndicies, maxHoopShift, verbose):
    if verbose:
        log.info('Add hoop layer')
    bounds = [0, maxHoopShift]
    shift, funcVal, loopIt = minimizeUtilization(
        vessel,
        layerNumber,
        bounds,
        dropIndicies,
        puckProperties,
        burstPressure,
        targetFunction=getMaxFibreFailureByShift,
        verbose=verbose)
    newDesignIndex = 0
    return shift, funcVal, loopIt, newDesignIndex
Exemplo n.º 9
0
def optimze_winding_parameters_friction(vessel, wendekreisradius):
    # popt, pcov = curve_fit(winding_helical_layer, layerindex, wk_goal, bounds=([0.], [1.]))

    popt = minimize_scalar(winding_helical_layer,
                           tol=0.00001,
                           method='Golden',
                           args=[vessel, wendekreisradius],
                           options={
                               "maxiter": 1000,
                               'disp': True
                           })
    # popt  = minimize(winding_helical_layer, x0 = (1.), method = 'BFGS', args=[vessel, wendekreisradius],
    #                   options={'gtol': 1e-6, 'disp': True})

    friction = popt.x
    log.info(popt.success)

    return friction, winding_helical_layer(friction,
                                           [vessel, wendekreisradius])
Exemplo n.º 10
0
def getPolarOpeningDiffHelical(friction, args):
    vessel, wendekreisradius, layerindex, verbose = args
    vessel.setLayerFriction(layerindex, friction[0], True)
    try:
        vessel.runWindingSimulation(layerindex + 1)
        wk = vessel.getPolarOpeningR(layerindex, True)
    except (IOError, ValueError, IOError, ZeroDivisionError):
        raise
        log.info('I have to pass')

    if verbose:
        log.info(
            f"layer {layerindex}, friction {friction}, po actual {wk}, po target {wendekreisradius}, po diff {wk-wendekreisradius}"
        )
    # log.info('this helical layer shoud end at', wendekreisradius[layerindex], 'mm but is at', wk, 'mm so there is a
    # deviation of', wendekreisradius[layerindex]-wk, 'mm') if abs(wendekreisradius[layerindex]-wk) < 2.:
    # arr_fric.append(abs(friction)) arr_wk.append(wk)

    return abs(wk - wendekreisradius)
Exemplo n.º 11
0
def getPolarOpeningXDiffHoop(shift, args):
    vessel, polarOpeningX, layerindex, verbose = args
    vessel.setHoopLayerShift(layerindex, shift, True)
    try:
        vessel.runWindingSimulation(layerindex + 1)
        wk = vessel.getPolarOpeningX(layerindex, True)
    except (IOError, ValueError, IOError, ZeroDivisionError, RuntimeError):
        raise
        log.info('I have to pass')

    if verbose:
        log.info(
            f"layer {layerindex}, shift {shift}, po actual {wk}, po target {polarOpeningX}, po diff {wk - polarOpeningX}"
        )

    # log.info('this hoop layer shoud end at', krempenradius[layerindex], 'mm but is at', wk, 'mm so there is a
    # deviation of', krempenradius[layerindex]-wk, 'mm')

    return abs(wk - polarOpeningX)
Exemplo n.º 12
0
def main():
    sampleFile = ''  # + 'C:/PycharmProjects/tankoh2/tmp/doe_isotensoid_20201028_210108/sampleX.txt'
    numberOfSamples = 201

    startTime = datetime.datetime.now()
    names = list(lb.keys())
    runDir = getRunDir(f'doe_{dome}', basePath=os.path.join(programDir, 'tmp'))

    winder = TankWinder(lb, ub, runDir)
    if sampleFile:
        lcvt = DOEfromFile(sampleFile)
    else:
        lcvt = LatinizedCentroidalVoronoiTesselation(numberOfSamples,
                                                     len(names))

    sampleX = BoundsHandler.scaleToBoundsStatic(lcvt.sampleXNormalized,
                                                list(lb.values()),
                                                list(ub.values()))
    plotGeometryRange([lb['r'], ub['r']], [lb['lzylByR'], ub['lzylByR']],
                      plotDir=runDir,
                      samples=sampleX)
    return
    print(sampleX.shape)
    lcvt.xToFile(os.path.join(runDir, 'sampleX.txt'))
    lcvt.xToFileStatic(os.path.join(runDir, 'sampleX_bounds.txt'), sampleX)
    sampleY = getY(sampleX, winder, verbose=True, runDir=runDir)

    # store samples
    lcvt.yToFile(os.path.join(runDir, 'sampleY.txt'), winder, sampleY)
    # lcvt.xyToFile(os.path.join(runDir, 'full_doe2.txt'), winder, sampleY, True)

    allSamples = [names + winder.resultNames]
    for inputSample, outputSample in zip(sampleX.T, sampleY):
        if hasattr(outputSample, '__iter__'):
            allSamples.append(list(inputSample) + list(outputSample))
        else:
            allSamples.append(list(inputSample) + list([outputSample]))
    with open(os.path.join(runDir, 'full_doe.txt'), 'w') as f:
        f.write(indent(allSamples, hasHeader=True))

    duration = datetime.datetime.now() - startTime
    log.info(f'runtime {duration.seconds} seconds')
Exemplo n.º 13
0
def main():
    # #########################################################################################
    # SET Parameters of vessel
    # #########################################################################################
    servicepressure = 700.  #bar
    saftyFactor = 1.
    layersToWind = 48
    optimizeWindingHelical = True
    optimizeWindingHoop = False

    tankname = 'NGT-BIT-2020-09-16'
    dataDir = os.path.join(programDir, 'data')
    dzyl = 400.  # mm
    polarOpening = 48. / 2.  # mm
    lzylinder = 500.  # mm
    dpoints = 4  # data points for liner contour
    defaultLayerthickness = 0.125
    hoopLayerThickness = 0.125
    helixLayerThickenss = 0.129
    rovingWidth = 3.175
    numberOfRovings = 10  #1
    bandWidth = rovingWidth * numberOfRovings
    log.info(
        f'winding using {numberOfRovings} robings with {rovingWidth}mm resulting in bandwith of {bandWidth}'
    )
    tex = 446  # g / km
    rho = 1.78  # g / cm^3
    sectionAreaFibre = tex / (1000. * rho)

    # input files
    layupDataFilename = os.path.join(dataDir, "Winding_" + tankname + ".txt")
    materialFilename = os.path.join(dataDir, "CFRP_HyMod.json")
    domeContourFilename = os.path.join(
        dataDir, "Dome_contour_" + tankname + "_48mm.txt")
    # output files
    runDir = getRunDir()
    fileNameReducedDomeContour = os.path.join(
        runDir, f"Dome_contour_{tankname}_reduced.dcon")
    linerFilename = os.path.join(runDir, tankname + ".liner")
    designFilename = os.path.join(runDir, tankname + ".design")
    windingFile = os.path.join(runDir, tankname + "_realised_winding.txt")
    vesselFilename = os.path.join(runDir, tankname + ".vessel")
    windingResultFilename = os.path.join(runDir, tankname + ".wresults")

    print('runDir', runDir)
    print('dataDir', dataDir)

    #print(getLengthContourPath(domeContourFilename, 24., 51.175/2., 1))

    # #########################################################################################
    # Create Liner
    # #########################################################################################
    x, r = getReducedDomePoints(domeContourFilename, dpoints,
                                fileNameReducedDomeContour)
    dome = getDome(dzyl / 2., polarOpening,
                   pychain.winding.DOME_TYPES.ISOTENSOID, x, r)
    liner = getLiner(dome, lzylinder, linerFilename, tankname)

    # ###########################################
    # Create material
    # ###########################################
    log.info(f'get material')
    material = getMaterial(materialFilename)

    angles, thicknesses, wendekreisradien, krempenradien = readLayupData(
        layupDataFilename)
    log.info(f'{angles[0:layersToWind]}')
    composite = getComposite(angles[0:layersToWind],
                             thicknesses[0:layersToWind], hoopLayerThickness,
                             helixLayerThickenss, material, sectionAreaFibre,
                             rovingWidth, numberOfRovings, tex, designFilename,
                             tankname)

    # create vessel and set liner and composite
    vessel = pychain.winding.Vessel()
    vessel.setLiner(liner)
    vessel.setComposite(composite)

    # #############################################################################
    # run winding simulation
    # #############################################################################

    # vessel.finishWinding()
    with open(windingFile, "w") as file:
        file.write('\t'.join(["Layer number", "Angle", "Polar opening"]) +
                   '\n')
    outArr = []
    vessel.resetWindingSimulation()
    anzHoop = 0.
    anzHelix = 0.
    for i, angle, krempenradius, wendekreisradius in zip(
            range(layersToWind), angles, krempenradien,
            wendekreisradien):  # len(angle_degree)
        log.info('--------------------------------------------------')
        layerindex = i
        # Hoop Layer
        if abs(angle - 90.) < 1e-8:
            #po_goal = krempenradius
            po_goal = lzylinder / 2. - anzHoop * rovingWidth
            anzHoop = anzHoop + 1
            #po_goal = wendekreisradius
            log.info(
                f'apply layer {i+1} with angle {angle}, Sollwendekreisradius {po_goal}'
            )
            if optimizeWindingHoop:

                shift, err_wk, iterations = optimizeHoopShiftForPolarOpeningX(
                    vessel, po_goal, layerindex)
                log.info(
                    f'{iterations} iterations. Shift is {shift} resulting in a polar opening error of {err_wk} '
                    f'as current polar opening is {vessel.getPolarOpeningR(layerindex, True)}'
                )
            else:
                # winding without optimization, but direct correction of shift
                vessel.setHoopLayerShift(layerindex, 0., True)
                vessel.runWindingSimulation(layerindex + 1)
                coor = po_goal - vessel.getPolarOpeningX(layerindex, True)
                vessel.setHoopLayerShift(layerindex, coor, True)
                vessel.runWindingSimulation(layerindex + 1)

        # Helix layer
        else:
            anzHelix = anzHelix + 1
            # global arr_fric, arr_wk
            # global arr_fric, arr_wk
            # arr_fric = []
            # arr_wk = []
            po_goal = wendekreisradius
            log.info(
                f'apply layer {i+1} with band mid path at polar opening of {po_goal}'
            )
            po_goal = getRadiusByShiftOnMandrel(
                vessel.getVesselLayer(layerindex - 1).getOuterMandrel1(),
                wendekreisradius, bandWidth)
            log.info(
                f'apply layer {i+1} with angle {angle} with band outer path at polar opening {po_goal}'
            )
            log.info(
                f'radius difference is {po_goal-wendekreisradius}, {bandWidth}'
            )

            # firts estimation with no frcition
            vessel.setLayerFriction(layerindex, 0., True)
            vessel.runWindingSimulation(layerindex + 1)
            log.info(
                f' polar opening with no friction is {vessel.getPolarOpeningR(layerindex, True)}'
            )
            diff = vessel.getPolarOpeningR(layerindex, True) - po_goal

            if optimizeWindingHelical and abs(diff) > 0.:
                log.info(f'using optimizeFriction')
                #friction, err_wk, iterations = optimizeFriction(vessel, wendekreisradius, layerindex, verbose=False)
                #log.info(f'{iterations} iterations. Friction is {friction} resulting in a polar opening error of {err_wk} '
                #     f'as current polar opening is {vessel.getPolarOpeningR(layerindex, True)}')
                #po_local = vessel.getPolarOpeningR(layerindex, True)

                if diff > 0:
                    log.info(
                        f' current polar opening is too large, frcition musst be negative'
                    )
                    log.info(
                        f'using optimizeFrictionGlobal_differential_evolution')
                    friction, err_wk, iterations = optimizeNegativeFrictionGlobal_differential_evolution(
                        vessel, po_goal, layerindex, verbose=False)

                if diff < 0:
                    log.info(
                        f' current polar opening is too small, frcition musst be positive'
                    )
                    log.info(
                        f'using optimizeFrictionGlobal_differential_evolution')

                    friction, err_wk, iterations = optimizeFrictionGlobal_differential_evolution(
                        vessel, po_goal, layerindex, verbose=False)

                log.info(
                    f'{iterations} iterations. Friction is {friction} resulting in a polar opening error of {err_wk} '
                    f'as current polar opening is {vessel.getPolarOpeningR(layerindex, True)}'
                )
                if err_wk > 1.:
                    log.info(
                        f'!!!!! ERROR FOR POLAR OPEING IS LARGER THAN 1mm !!!')

            # file = open("data.txt", "w")
            # for j in range(len(arr_fric)):
            #    file.write(str(arr_fric[j])+'\t'+str(arr_wk[j])+'\n')
            # file.close()
            # plt.plot(arr_fric, arr_wk, marker = 'o', linewidth = 0.)
            # m, n = fitting_linear(arr_fric,arr_wk)
            # log.info(m,n)
            # friction_corr = (wendekreisradius[i] - n) / m
            # vessel.setLayerFriction(layerindex, friction_corr, True)
            # vessel.runWindingSimulation(layerindex+1)
            # wk_korr = vessel.getPolarOpeningR(layerindex, True)
            # print (friction_corr, wk_korr)
            # y = linear(arr_fric, np.ones(len(arr_fric))*m, np.ones(len(arr_fric))*n)
            # plt.plot(arr_fric, y,'k--', lw = 1.)
            # plt.plot(friction_corr, wk_korr, 'ro')
            # plt.xlim((0., 0.0001))
            # plt.ylim((25., 27.))
            # plt.show()

        po = vessel.getPolarOpeningR(layerindex, True)
        outArr.append([i + 1, angle, po, po * 2, po_goal, abs(po - po_goal)])
        with open(windingFile, "a") as file:
            file.write('\t'.join([str(s) for s in outArr[-1]]) + '\n')

    with open(windingFile, "w") as file:
        file.write(
            indent([[
                "Layer \#", "Angle", "Polar opening", "Polar opening diameter",
                "Target Polar opening"
            ]] + outArr))

    # save vessel
    vessel.saveToFile(vesselFilename)  # save vessel
    updateName(vesselFilename, tankname, ['vessel'])

    # save winding results
    windingResults = pychain.winding.VesselWindingResults()
    windingResults.buildFromVessel(vessel)
    windingResults.saveToFile(windingResultFilename)

    # #############################################################################
    # run internal calculation
    # #############################################################################

    #    build shell model for internal calculation
    converter = pychain.mycrofem.VesselConverter()
    shellModel = converter.buildAxShellModell(vessel, 10)

    #    run linear solver
    linerSolver = pychain.mycrofem.LinearSolver(shellModel)
    linerSolver.run(True)

    #    get stresses in the fiber COS
    S11, S22, S12 = shellModel.calculateLayerStressesBottom()
    #    get  x coordinates (element middle)
    xCoords = shellModel.getElementCoordsX()

    # #############################################################################
    # run ABAQUS
    # #############################################################################

    # create model options for abaqus calculation
    modelOptions = pychain.mycrofem.VesselFEMModelOptions()
    modelOptions.modelName = tankname + "_Vessel"
    modelOptions.jobName = tankname + "_Job"
    modelOptions.windingResultsFileName = tankname
    modelOptions.useMaterialPhi = False  # false uses micromechanical estimations of fvg effect an porperties
    modelOptions.fittingContactWinding = pychain.mycrofem.CONTACT_TYPE.PENALTY
    modelOptions.frictionFitting = 0.3
    modelOptions.globalMeshSize = 2.0
    modelOptions.pressureInBar = servicepressure
    modelOptions.saveCAE = True
    modelOptions.buildMandrel1 = True
    modelOptions.buildMandrel2 = False

    # write abaqus scripts
    scriptGenerator = pychain.abaqus.AbaqusVesselScriptGenerator()
    scriptGenerator.writeVesselAxSolidBuildScript(
        os.path.join(runDir, tankname + "_Build.py"), settings, modelOptions)
    scriptGenerator.writeVesselAxSolidBuildScript(
        os.path.join(runDir, tankname + "_Eval.py"), settings, modelOptions)

    # create vessel model according to version 95_2 documentation 'Axis-Symmetric Vessel Model'

    #create vessel model
    vesselAxSolid = mymodels.myvesselAxSolidContacts
    model = vesselAxSolid.MyVesselAxSolid(modelName=tankname + "_Vessel",
                                          umat=True,
                                          buildFitting=True,
                                          saveCAE=True,
                                          useMaterialPhi=False,
                                          buildLiner=True)
    #load winding results
    model.loadData(tankname)
    #build mandrel 1
    model.buildOnlyMandrel1(
        servicepressure,
        1,
        friction=0.3,
        fittingContactWinding=pychain.mycrofem.CONTACT_TYPE.PENALT)
    #mesh model
    model.mesh(2.0)
    #export inp file
    model.exportInp(tankname + "_Job")

    import matplotlib.pylab as plt

    #    fig = plt.figure()
    #   ax = fig.gca()
    #   ax.plot(S11[:, 0])
    #   ax.plot(S11[:, 1])
    #   ax.plot(S11[:, 2])
    # plt.show()

    log.info('FINISHED')
Exemplo n.º 14
0
def winding_helical_layer(friction, args):
    vessel, wendekreisradius = args
    log.info('--------------------')
    log.info(f'use friction {friction}')
    vessel.setLayerFriction(layerindex, abs(friction), True)
    log.info(f'set friction {friction}')

    try:
        vessel.runWindingSimulation(layerindex + 1)  #
        log.info(f'apply layer {layerindex}')
        wk = vessel.getPolarOpeningR(layerindex, True)
        log.info(wk)
    except (IOError, ValueError, IOError, ZeroDivisionError):
        log.info('I have to pass')

    # log.info('this helical layer shoud end at', wendekreisradius[layerindex], 'mm but is at', wk, 'mm so there is a
    # deviation of', wendekreisradius[layerindex]-wk, 'mm') if abs(wendekreisradius[layerindex]-wk) < 2.:
    # arr_fric.append(abs(friction)) arr_wk.append(wk)

    return abs(wk - wendekreisradius[layerindex])
Exemplo n.º 15
0
def main():
    # #########################################################################################
    # SET Parameters of vessel
    # #########################################################################################

    tankname = 'NGT-BIT-2020-09-16'
    dataDir = os.path.join(programDir, 'data')
    dzyl = 400.  # mm
    polarOpening = 20.  # mm
    lzylinder = 500.  # mm
    dpoints = 4  # data points for liner contour
    defaultLayerthickness = 0.125
    hoopLayerThickness = 0.125
    helixLayerThickenss = 0.129
    bandWidth = 3.175
    numberOfRovings = 1
    rovingWidth = bandWidth / numberOfRovings
    tex = 446  # g / km
    rho = 1.78  # g / cm^3
    sectionAreaFibre = tex / (1000. * rho)

    # #########################################################################################
    # Create Liner
    # #########################################################################################

    # load contour from file
    fileNameReducedDomeContour = os.path.join(
        dataDir, "Dome_contour_" + tankname + "_modified.dcon")
    Data = np.loadtxt(
        os.path.join(dataDir, "Dome_contour_" + tankname + ".txt"))
    if 0:
        contourPoints = np.abs(Data)
        contourPoints[:, 0] -= contourPoints[0, 0]
        #reduce points
        redContourPoints = contourPoints[::dpoints, :]
        if not np.allclose(redContourPoints[-1, :], contourPoints[-1, :]):
            redContourPoints = np.append(redContourPoints,
                                         [contourPoints[-1, :]],
                                         axis=0)
        np.savetxt(fileNameReducedDomeContour, redContourPoints, delimiter=',')
        Xvec, rVec = redContourPoints[:, 0], redContourPoints[:, 1]

    else:
        Xvec = abs(Data[:, 0])
        Xvec = Xvec - Xvec[0]
        rVec = abs(Data[:, 1])

        # reduce data points
        log.info(len(Xvec) - 1)
        index = np.linspace(0,
                            dpoints * int((len(Xvec) / dpoints)),
                            int((len(Xvec) / dpoints)) + 1,
                            dtype=np.int16)

        arr = [len(Xvec) - 1]
        index = np.append(index, arr)

        Xvec = Xvec[index]
        rVec = rVec[index]

        # save liner contour for loading in mikroWind
        with open(fileNameReducedDomeContour, "w") as contour:
            for i in range(len(Xvec)):
                contour.write(str(Xvec[i]) + ',' + str(rVec[i]) + '\n')

    # build  dome
    dome = pychain.winding.Dome()
    dome.buildDome(dzyl / 2., polarOpening,
                   pychain.winding.DOME_TYPES.ISOTENSOID)
    dome.setPoints(Xvec, rVec)
    log.info(f'Build Dome with dome data {dome}')

    # create a symmetric liner with dome information and cylinder length
    liner = pychain.winding.Liner()
    # spline for winding calculation is left on default of 1.0
    liner.buildFromDome(dome, lzylinder, 1.0)

    # save liner for visualization with µChainWind
    linerFilename = os.path.join(dataDir, tankname + ".liner")
    liner.saveToFile(linerFilename)
    log.info('saved liner')

    # change name of liner in file
    with open(linerFilename) as jsonFile:
        data = json.load(jsonFile)
    data["liner"]["name"] = tankname
    with open(linerFilename, "w") as jsonFile:
        json.dump(data, jsonFile, indent=4)

    # copyfile(tankname+"_.liner", tankname+'_copy.liner')

    # fobj = open(tankname+"_copy.liner")
    # fobj_new = open(tankname+"_.liner", "w")

    # for line in fobj:
    #     if line[9:13]=='name':
    #         print ('change name from '+line+' to '+tankname)
    #         fobj_new.write('\t\t"name": "'+tankname+'", \n')
    #     else:
    #         fobj_new.write(line)
    # fobj.close()
    # fobj_new.close()
    # os.remove(tankname+"_copy.liner")

    # ###########################################
    # Create winding
    # ###########################################

    # create default material
    # t700 = pychain.material.OrthotropMaterial()
    # t700.setDefaultCFRP()

    # load material
    material = pychain.material.OrthotropMaterial()
    material.loadFromFile(os.path.join(dataDir, "CFRP_HyMod.json"))
    mat = pychain.material

    # read winding angles in cylindrical regime
    Data = np.loadtxt(os.path.join(dataDir, "Winding_" + tankname + ".txt"))
    angle_degree = abs(Data[:, 0])
    wendekreisdurchmesser = abs(Data[:, 1])
    wendekreisradius = wendekreisdurchmesser / 2.
    singlePlyThickenss = abs(Data[:, 2])
    krempendruchmesser = abs(Data[:, 3])
    krempenradius = krempendruchmesser / 2.

    # create composite with layers
    composite = pychain.material.Composite()

    for i in range(len(angle_degree)):  #
        angle = angle_degree[i]
        composite.appendLayer(angle, singlePlyThickenss[i], material,
                              pychain.material.LAYER_TYPES.BAP)
        fvg = sectionAreaFibre / (bandWidth * singlePlyThickenss[i])
        composite.getOrthotropLayer(i).phi = fvg

        if angle == 90.:
            # change winding properties
            composite.getOrthotropLayer(
                i).windingProperties.rovingWidth = rovingWidth
            composite.getOrthotropLayer(
                i).windingProperties.numberOfRovings = numberOfRovings
            composite.getOrthotropLayer(i).windingProperties.texNumber = tex
            composite.getOrthotropLayer(i).windingProperties.coverage = 1.
            composite.getOrthotropLayer(i).windingProperties.isHoop = True
            composite.getOrthotropLayer(
                i).windingProperties.cylinderThickness = hoopLayerThickness

        else:
            # change winding properties
            composite.getOrthotropLayer(
                i).windingProperties.rovingWidth = rovingWidth
            composite.getOrthotropLayer(
                i).windingProperties.numberOfRovings = numberOfRovings
            composite.getOrthotropLayer(i).windingProperties.texNumber = tex
            composite.getOrthotropLayer(i).windingProperties.coverage = 1.
            composite.getOrthotropLayer(
                i).windingProperties.cylinderThickness = helixLayerThickenss

    composite.updateThicknessFromWindingProperties()
    composite.saveToFile(tankname + ".design")

    # rename design
    with open(os.path.join(dataDir, tankname + ".design")) as jsonFile:
        data = json.load(jsonFile)
    data["designs"]["1"]["name"] = tankname
    with open(os.path.join(dataDir, tankname + ".design"), "w") as jsonFile:
        json.dump(data, jsonFile, indent=4)

    # create vessel and set liner and composite
    vessel = pychain.winding.Vessel()
    vessel.setLiner(liner)
    vessel.setComposite(composite)

    # #############################################################################
    # run winding simulation
    # #############################################################################

    # vessel.finishWinding()
    global layerindex
    with open(os.path.join(dataDir, tankname + "_realised_winding.txt"),
              "w") as file:
        file.write("Layer number" + '\t' + "Angle" + '\t' + "Polar opening" +
                   '\n')
        vessel.resetWindingSimulation()
        for i in range(3):  # len(angle_degree)
            log.info('--------------------------------------------------')
            log.info(f'apply layer {i + 1} with angle {angle_degree[i]}')
            layerindex = i
            # wk = winding_layer(i, 0.5)
            if angle_degree[i] == 90.:
                log.info(f'Sollwendekreisradius {krempenradius[i]}')
                shift, err_wk = optimze_winding_parameters_shift(
                    vessel, krempenradius, layerindex)
                log.info(
                    f'optimised shift is {shift} resulting in a polar opening error of {err_wk} '
                    f'as current polar opening is {vessel.getPolarOpeningR(layerindex, True)}'
                )
            else:
                # global arr_fric, arr_wk
                # global arr_fric, arr_wk
                # arr_fric = []
                # arr_wk = []
                log.info(f'Sollwendekreisradius {wendekreisradius[i]}')
                friction, err_wk = optimze_winding_parameters_friction(
                    vessel, wendekreisradius)
                log.info(
                    f'optimised friction is {friction} resulting in a polar opening error of {err_wk}'
                    f'as current polar opening is {vessel.getPolarOpeningR(layerindex, True)}'
                )
                # file = open("data.txt", "w")
                # for j in range(len(arr_fric)):
                #    file.write(str(arr_fric[j])+'\t'+str(arr_wk[j])+'\n')
                # file.close()
                # plt.plot(arr_fric, arr_wk, marker = 'o', linewidth = 0.)
                # m, n = fitting_linear(arr_fric,arr_wk)
                # log.info(m,n)
                # friction_corr = (wendekreisradius[i] - n) / m
                # vessel.setLayerFriction(layerindex, friction_corr, True)
                # vessel.runWindingSimulation(layerindex+1)
                # wk_korr = vessel.getPolarOpeningR(layerindex, True)
                # print (friction_corr, wk_korr)
                # y = linear(arr_fric, np.ones(len(arr_fric))*m, np.ones(len(arr_fric))*n)
                # plt.plot(arr_fric, y,'k--', lw = 1.)
                # plt.plot(friction_corr, wk_korr, 'ro')
                # plt.xlim((0., 0.0001))
                # plt.ylim((25., 27.))
                # plt.show()

            file.write(
                str(i + 1) + '\t' + str(angle_degree[i]) + '\t' +
                str(vessel.getPolarOpeningR(layerindex, True)) + '\n')

    # save vessel
    vessel.saveToFile(os.path.join(dataDir,
                                   tankname + ".vessel"))  # save vessel

    with open(os.path.join(dataDir, tankname + ".vessel")) as jsonFile:
        data = json.load(jsonFile)
    data["vessel"]["name"] = tankname
    with open(os.path.join(dataDir, tankname + ".vessel"), "w") as jsonFile:
        json.dump(data, jsonFile, indent=4)

    # rename vessel

    # save winding results
    windingResults = pychain.winding.VesselWindingResults()
    windingResults.buildFromVessel(vessel)
    windingResults.saveToFile(os.path.join(dataDir, tankname + ".wresults"))

    # build shell model for internal calculation
    converter = pychain.mycrofem.VesselConverter()
    shellModel = converter.buildAxShellModell(vessel, 10)

    # run linear solver
    linerSolver = pychain.mycrofem.LinearSolver(shellModel)
    linerSolver.run(True)

    # get stresses in the fiber COS
    S11, S22, S12 = shellModel.calculateLayerStressesBottom()
    # get  x coordinates (element middle)
    xCoords = shellModel.getElementCoordsX()

    # create model options for abaqus calculation
    modelOptions = pychain.mycrofem.VesselFEMModelOptions()
    modelOptions.modelName = tankname + "_Vessel"
    modelOptions.jobName = tankname + "_Job"
    modelOptions.windingResultsFileName = tankname
    modelOptions.useMaterialPhi = False
    modelOptions.fittingContactWinding = pychain.mycrofem.CONTACT_TYPE.PENALTY
    modelOptions.globalMeshSize = 0.25
    modelOptions.pressureInBar = 300.0

    # write abaqus scripts
    scriptGenerator = pychain.abaqus.AbaqusVesselScriptGenerator()
    scriptGenerator.writeVesselAxSolidBuildScript(
        os.path.join(dataDir, tankname + "_Build.py"), settings, modelOptions)
    scriptGenerator.writeVesselAxSolidBuildScript(
        os.path.join(dataDir, tankname + "_Eval.py"), settings, modelOptions)

    import matplotlib.pylab as plt

    fig = plt.figure()
    ax = fig.gca()
    ax.plot(S11[:, 0])
    ax.plot(S11[:, 1])
    ax.plot(S11[:, 2])
    plt.show()

    log.info('FINISHED')
Exemplo n.º 16
0
def printLayer(layerNumber, verbose=False):
    sep = '\n' + '=' * 80
    log.info((sep if verbose else '') + f'\nLayer {layerNumber}' +
             (sep if verbose else ''))
Exemplo n.º 17
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
Exemplo n.º 18
0
def createWindingDesign(**kwargs):
    startTime = datetime.datetime.now()
    verbose = False
    # #########################################################################################
    # SET Parameters of vessel
    # #########################################################################################

    log.info('=' * 100)
    log.info('createWindingDesign with these parameters: ' + str(kwargs))
    log.info('=' * 100)

    # design constants AND not recognized issues

    # band pattern not recognized

    layersToWind = 100
    tankname = 'exact_h2'
    dataDir = os.path.join(programDir, 'data')
    hoopLayerThickness = 0.125
    helixLayerThickenss = 0.129
    rovingWidth = 3.175
    numberOfRovings = 4
    bandWidth = rovingWidth * numberOfRovings
    tex = 446  # g / km
    rho = 1.78  # g / cm^3
    sectionAreaFibre = tex / (1000. * rho)
    pressure = 5.  # pressure in MPa (bar / 10.)
    safetyFactor = 2.25

    # potential external inputs
    burstPressure = kwargs.get('burstPressure', pressure * safetyFactor)
    dzyl = kwargs.get('dzyl', 400.)  # mm
    minPolarOpening = kwargs.get('minPolarOpening', 20)  # mm
    domeType = kwargs.get(
        'domeType',
        pychain.winding.DOME_TYPES.ISOTENSOID)  # CIRCLE; ISOTENSOID
    runDir = kwargs['runDir'] if 'runDir' in kwargs else getRunDir()
    if 'lzyl' in kwargs:
        lzylinder = kwargs.get('lzyl', 500.)  # mm
    else:
        lzylByR = kwargs.get('lzylByR', 2.5)  # mm
        lzylinder = lzylByR * dzyl / 2

    if 0:
        # test pressure vessel vs cryo vessel
        dzyl = 2000  #mm
        lzylinder = 4000  #mm
        minPolarOpening = dzyl / 2 / 10
        burstPressure = 25
        runDir = kwargs.get('runDir', getRunDir(f'_{burstPressure}MPa'))

    # input files
    materialFilename = os.path.join(dataDir, "CFRP_HyMod.json")
    # output files
    linerFilename = os.path.join(runDir, tankname + ".liner")
    designFilename = os.path.join(runDir, tankname + ".design")
    vesselFilename = os.path.join(runDir, tankname + ".vessel")
    windingResultFilename = os.path.join(runDir, tankname + ".wresults")

    # #########################################################################################
    # Create Liner
    # #########################################################################################
    dome = getDome(dzyl / 2., minPolarOpening, domeType)
    liner = getLiner(dome, lzylinder, linerFilename, tankname)

    # ###########################################
    # Create material
    # ###########################################
    material = getMaterial(materialFilename)
    puckProperties = material.puckProperties

    angles, thicknesses, = [90.] * 2, [helixLayerThickenss] * 2
    compositeArgs = [
        thicknesses, hoopLayerThickness, helixLayerThickenss, material,
        sectionAreaFibre, rovingWidth, numberOfRovings, tex, designFilename,
        tankname
    ]
    composite = getComposite(angles, *compositeArgs)
    # create vessel and set liner and composite
    vessel = pychain.winding.Vessel()
    vessel.setLiner(liner)
    vessel.setComposite(composite)

    # #############################################################################
    # run winding simulation
    # #############################################################################
    vessel.saveToFile(vesselFilename)  # save vessel
    frpMass, volume, area, composite, iterations, anglesShifts = designLayers(
        vessel, layersToWind, minPolarOpening, puckProperties, burstPressure,
        runDir, composite, compositeArgs, verbose)

    np.savetxt(os.path.join(runDir, 'angles_shifts.txt'), anglesShifts)
    # save vessel
    vessel.saveToFile(vesselFilename)  # save vessel
    updateName(vesselFilename, tankname, ['vessel'])
    updateName(vesselFilename,
               pressure, ['vessel'],
               attrName='operationPressure')
    updateName(vesselFilename,
               safetyFactor, ['vessel'],
               attrName='securityFactor')
    copyAsJson(vesselFilename, 'vessel')

    # save winding results
    windingResults = pychain.winding.VesselWindingResults()
    windingResults.buildFromVessel(vessel)
    windingResults.saveToFile(windingResultFilename)
    copyAsJson(windingResultFilename, 'wresults')

    # #############################################################################
    # run Evaluation
    # #############################################################################
    if 0:
        results = getLinearResults(vessel, puckProperties, layersToWind - 1,
                                   burstPressure)
        plotStressEpsPuck(True, None, *results)

    if verbose:
        # vessel.printSimulationStatus()
        composite.info()

    duration = datetime.datetime.now() - startTime
    log.info(f'iterations {iterations}, runtime {duration.seconds} seconds')

    log.info('FINISHED')

    resultNames = [
        'frpMass', 'volume', 'area', 'lzylinder', 'numberOfLayers', 'angles'
    ]
    results = frpMass, volume, area, liner.linerLength, composite.getNumberOfLayers(
    ), [a for a, _ in anglesShifts]
    with open(os.path.join(runDir, 'results.txt'), 'w') as f:
        f.write(indent([resultNames, results]))
    return results