Esempio n. 1
0
 def getProperty(self, propID, time, objectID=0):
     if (propID == PropertyID.PID_Demo_Value):
         return Property.ConstantProperty(self.count,
                                          PropertyID.PID_Demo_Value,
                                          ValueType.Scalar,
                                          PQ.getDimensionlessUnit())
     else:
         raise APIError.APIError('Unknown property ID')
Esempio n. 2
0
    def _copyPreviousSolution(self):
        if self._curTStep == 0:
            return

        # Function for finding closest timestep to current time
        def closest_floor(arr):
            tstep = arr.index.get_level_values('tstep')
            t = self._curTStep - tstep > 0
            # print(t)
            return (tstep[t].min())

        # Find closest time and copy fields to current time
        g = self.fields.groupby(level='fieldID').apply(closest_floor)
        for fID in g.index:
            key = (fID, g[fID])
            newKey = (fID, self._curTStep)
            f = self.fields[key]

            newField = Field.Field(f.getMesh(),
                                   f.getFieldID(),
                                   f.getValueType(),
                                   units=f.getUnits(),
                                   values=f.values,
                                   time=self._curTStep,
                                   fieldType=f.fieldType)
            self.fields.set_value(newKey, newField)

        # Find closest time and copy properties to current time
        g = self.properties.groupby(level=('propertyID',
                                           'objectID')).apply(closest_floor)
        for pID in g.index:
            key = (pID[0], pID[1], g[pID])
            newKey = (pID[0], pID[1], self._curTStep)
            p = self.properties[key]
            newProp = Property.Property(value=p.getValue(),
                                        propID=p.getPropertyID(),
                                        valueType=p.valueType,
                                        time=self._curTStep,
                                        units=p.getUnits(),
                                        objectID=p.getObjectID())
            self.properties.set_value(newKey, newProp)
def initialProps(props, jsondata, pID=PropertyID):
    # Number of rays
    nr = Property.Property(value=jsondata['sources'][0]['rays'],
                           propID=pID.PID_NumberOfRays,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_CHIP_ACTIVE_AREA)

    key = (pID.PID_NumberOfRays, objID.OBJ_CHIP_ACTIVE_AREA, 0)
    props.set_value(key, nr)

    # Refractive index of silicone cone
    v = jsondata['materials'][3]['refractiveIndex']
    nr = Property.Property(value=v,
                           propID=pID.PID_RefractiveIndex,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_CONE)

    key = (pID.PID_RefractiveIndex, objID.OBJ_CONE, 0)
    props.set_value(key, nr)

    # LED spectrum
    nr = Property.Property(value={
        "wavelengths": np.array([450]),
        "intensities": np.array([0])
    },
                           propID=pID.PID_LEDSpectrum,
                           valueType="dict",
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_LED)

    key = (pID.PID_LEDSpectrum, objID.OBJ_LED, 0)
    props.set_value(key, nr)

    # Chip spectrum
    v1 = jsondata['sources'][0]['wavelengths']
    v2 = jsondata['sources'][0]['intensities']
    nr = Property.Property(value={
        "wavelengths": np.array(v1),
        "intensities": np.array(v2)
    },
                           propID=pID.PID_ChipSpectrum,
                           valueType="dict",
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_CHIP_ACTIVE_AREA)

    key = (pID.PID_ChipSpectrum, objID.OBJ_CHIP_ACTIVE_AREA, 0)
    props.set_value(key, nr)

    # Color X
    nr = Property.Property(value=0,
                           propID=pID.PID_LEDColor_x,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_LED)

    key = (pID.PID_LEDColor_x, objID.OBJ_LED, 0)
    props.set_value(key, nr)

    # Color Y
    nr = Property.Property(value=0,
                           propID=pID.PID_LEDColor_y,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_LED)

    key = (pID.PID_LEDColor_y, objID.OBJ_LED, 0)
    props.set_value(key, nr)

    # CCT
    nr = Property.Property(value=0,
                           propID=pID.PID_LEDCCT,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_LED)

    key = (pID.PID_LEDCCT, objID.OBJ_LED, 0)
    props.set_value(key, nr)

    # RadiantPower
    nr = Property.Property(value=0,
                           propID=pID.PID_LEDRadiantPower,
                           valueType=ValueType.Scalar,
                           time=0.0,
                           units=None,
                           objectID=objID.OBJ_LED)

    key = (pID.PID_LEDRadiantPower, objID.OBJ_LED, 0)
    props.set_value(key, nr)

    # Number of fluorescent particles:
    nr = Property.Property(
        value=jsondata['materials'][3]['numberOfFluorescentParticles'],
        valueType=ValueType.Scalar,
        propID=pID.PID_NumberOfFluorescentParticles,
        time=0.0,
        units=None,
        objectID=objID.OBJ_CONE)
    key = (pID.PID_NumberOfFluorescentParticles, objID.OBJ_CONE, 0)
    props.set_value(key, nr)

    # Phosphor efficiency for PARTICLE_TYPE_1:
    p_eff = Property.Property(
        value=jsondata['materials'][3]['phosphorEfficiencies'][0],
        valueType=ValueType.Scalar,
        propID=pID.PID_PhosphorEfficiency,
        time=0.0,
        units=None,
        objectID=objID.OBJ_PARTICLE_TYPE_1)
    key = (pID.PID_PhosphorEfficiency, objID.OBJ_PARTICLE_TYPE_1, 0)
    props.set_value(key, p_eff)
    tracerApp.setProperty(pScat)
    tracerApp.setProperty(pPhase)

    # Connect fields
    fTemp = comsolApp.getField(FieldID.FID_Temperature, 0)
    fHeat = comsolApp.getField(FieldID.FID_Thermal_absorption_volume, 0)

    tracerApp.setField(fTemp)
    tracerApp.setField(fHeat)

    # Connect properties
    # Particle density
    vDens = 0.00003400
    pDens = Property.Property(value=vDens,
                              propID=PropertyID.PID_ParticleNumberDensity,
                              valueType=ValueType.Scalar,
                              time=0.0,
                              units=None,
                              objectID=objID.OBJ_CONE)
    tracerApp.setProperty(pDens)

    # Number of rays to trace
    pRays = Property.Property(value=100000,
                              propID=PropertyID.PID_NumberOfRays,
                              valueType=ValueType.Scalar,
                              time=0.0,
                              units=None,
                              objectID=objID.OBJ_CONE)
    tracerApp.setProperty(pRays)
    # Emission spectrum
    em = Property.Property(value=ex_em_import.getEm(),
                           propID=PropertyID.PID_EmissionSpectrum,
    tracerApp.setProperty(pPhase, objID.OBJ_PARTICLE_TYPE_1)
    logger.info('Props connected')

    # Connect fields
    fTemp = comsolApp.getField(FieldID.FID_Temperature, 0)
    fHeat = comsolApp.getField(FieldID.FID_Thermal_absorption_volume, 0)

    tracerApp.setField(fTemp)
    tracerApp.setField(fHeat)

    # Connect properties
    # Particle density
    vDens = 0.00000003400
    pDens = Property.Property(value=vDens,
                              propID=PropertyID.PID_ParticleNumberDensity,
                              valueType=ValueType.Scalar,
                              time=0.0,
                              units=None,
                              objectID=objID.OBJ_CONE)
    tracerApp.setProperty(pDens)

    # Number of rays to trace
    pRays = Property.Property(value=100,
                              propID=PropertyID.PID_NumberOfRays,
                              valueType=ValueType.Scalar,
                              time=0.0,
                              units=None,
                              objectID=objID.OBJ_CONE)
    tracerApp.setProperty(pRays)

    # Emission spectrum
    import numpy as np
def interpolateProperty(properties,
                        time,
                        propertyID,
                        objectID,
                        method='linear'):
    """
    Function to interpolate fields in between solved timesteps.


    Parameters
    ----------
    properties : pandas.Series of Property.Property
                 Series of properties for consecutive timesteps.
    time : float
           Time to interpolate data

    propetyID : PropertyID
                Type of the property to interpolate

    objectID : float
               Object id the porperty is attached to.

    method : string, optional
             Method to be used in the interpolation. Only linear is currently
             supported


    Returns
    -------
    interPorp : Property.Property
            Interpolated property


    """
    if not isinstance(properties, pd.Series):
        raise TypeError("Properties should be in pandas Series -object")

    # Find closest timesteps
    idx_tstep = properties.loc[propertyID, objectID, :].index
    value_to_find = time
    Min = idx_tstep <= value_to_find
    Max = idx_tstep >= value_to_find

    p_min = properties[(propertyID, objectID, idx_tstep[Min].max())]
    p_max = properties[(propertyID, objectID, idx_tstep[Max].min())]

    # Dictinary not supported
    if type(p_max.getValue()) == dict:
        logger.warning('Interpolation of (dict) not supported! Returning max.')
        return (p_max)

    # Interpolate property getValue().
    if method == 'linear':
        newValue = p_min.getValue() + (p_max.getValue() -
                                       p_min.getValue()) / 2.0
    else:
        logger.warning(
            'Interpolation method (%s) not supported! Using linear.' % method)
        newValue = p_min.getValue() + (p_max.getValue() -
                                       p_min.getValue()) / 2.0

    # Create new property.
    newProp = Property.Property(value=newValue,
                                propID=propertyID,
                                valueType=p_min.getValueType(),
                                time=time,
                                units=p_min.getUnits(),
                                objectID=objectID)

    return (newProp)
Esempio n. 7
0
def runTestCase(xst, mic):
    """
    This method defines the test case procedure itself. It relies on the grid
    setting made in the main method (see parameter). No additional interface objects will be
    allocated here.
    
    First, the initialization of monitor files, lookup table (concentration -> emissivity),
    quality factor module, and a Mupif mesh representing the glass substrates surface is done.
    
    One time step of the overall simulation chain consists of a critical time step of X-Stream
    and a loop over the surface mesh node positions for microstructure analysis by MICRESS
    for the same simulation time. The temperature at each position will be given by 
    X-Stream and serves as a boundary property for MICRESS. After the complete microstructure
    analysis is done, the individual Se concentrations will be mapped by the lookup table to
    emissivity values and assembled to a 2D surface mesh which will serve as a boundary
    condition for the next X-Stream step. Additionally, some properties of the microstructure
    will be combined to a local quality factor, e.g. grain size.
    
    The average of the local quality factors after the last time step is the overall quality
    factor of the photovoltaic thin-film layer. However, there is only data for a few beginning
    time steps given in this example and the quality factor will remain zero.
    
    The main intention of this example is to present one way of implementing a
    simulation chain for Mupif, not to evaluate a CIGS photovoltaic component.
       
    :param Application xst: X-Stream interface handle
    :param tuple mic: A tuple MICRESS Application interface handles
    
  """

    try:

        # empty monitor files
        for i in range(len(cConf.monFilenames)):
            f = open(cConf.monFilenames[i], 'w')
            f.close()

        time = PQ.PhysicalQuantity(cConf.startTime, 's')

        # initialize TNO converter with lookup table
        lookup = LU.LU(cConf.qfactPrefix + '/' + cConf.qFactInputFiles[0])
        # initialize quality factor calculation
        qfactor = QFactor.QFact(cConf.qfactPrefix + '/' +
                                cConf.qFactInputFiles[1])

        # The background mesh for later interpolation determines the macro
        # location for which a microstructure analysis will be done.
        # These locations will be scheduled to the available application interfaces.
        # Schedule scheme: static
        # Chunk size = number of interfaces
        if cConf.debug:
            print ("define background mesh for interpolation",
              cConf.nbX,cConf.nbY, cConf.lenX,cConf.lenY, \
              cConf.originX, cConf.originY, cConf.originZ)
        if ((cConf.nbX > 0) and (cConf.nbY > 0)):
            nbX = cConf.nbX
            nbY = cConf.nbY
            lenX = cConf.lenX
            lenY = cConf.lenY
            origin = (cConf.originX, cConf.originY, cConf.originZ)
        elif ((cConf.nbX > 0) and (cConf.nbZ > 0)):
            print("transfer XZ slice to XY coordinates")
            nbX = cConf.nbX
            nbY = cConf.nbZ
            lenX = cConf.lenX
            lenY = cConf.lenZ
            origin = (cConf.originX, cConf.originZ, cConf.originY)
        elif ((cConf.nbY > 0) and (cConf.nbZ > 0)):
            print("transfer YZ slice to XY coordinates")
            nbX = cConf.nbY
            nbY = cConf.nbZ
            lenX = cConf.lenY
            lenY = cConf.lenZ
            origin = (cConf.originY, cConf.originZ, cConf.originX)
        else:
            raise APIError.APIError('no 2D slice recognized')

        bgMesh = util.generateBackgroundMesh(nbX, nbY, lenX, lenY, origin)

        # copy nodes for microstructure evaluation to an easy to handle list p
        p = []
        rd = 7
        for node in bgMesh.getVertices():
            if ((cConf.nbX > 0) and (cConf.nbY > 0)):  # XY
                pNode = (round(node[0], rd), round(node[1],
                                                   rd), round(node[2], rd))
            elif ((cConf.nbX > 0) and (cConf.nbZ > 0)):  # XZ
                pNode = (round(node[0], rd), round(node[2],
                                                   rd), round(node[1], rd))
            else:  # YZ
                pNode = (round(node[2], rd), round(node[0],
                                                   rd), round(node[1], rd))
            p.append(pNode)

        timeStepNumber = 0
        first = True
        profileFirst = True
        eps = 1.0E-8
        timing = []
        files = []

        tcStart = timeTime.time()

        # set constant start emissivity (will be modified in homogenization step)
        propEpsXstream = Property.ConstantProperty(cConf.startEmissivity,
                                                   XStPropertyID.PID_Emissivity,\
                                                   ValueType.Scalar, PQ.getDimensionlessUnit(),
                                                   time, 0 )
        if (cConf.debug):
            print("set uniform start emissivity: ", propEpsXstream.getValue())
        xst.setProperty(propEpsXstream)

        while ((time.inUnitsOf('s').getValue() + eps) < cConf.targetTime):

            print('Simulation Time: ' + str(time))
            print('---------------------------')
            # ---------------------------
            # macro step (X-stream)
            # ---------------------------
            # where the critical time step is given by the macro scale output interval,
            # i.e. get the next available output
            dt = xst.getCriticalTimeStep()  #.inUnitsOf(timeUnits).getValue()

            time = time + dt
            timeStepNumber = timeStepNumber + 1
            #we have units with Time
            istep = TimeStep.TimeStep(
                time, dt,
                PQ.PhysicalQuantity(cConf.targetTime, time.getUnitName()),
                None, timeStepNumber)

            timing.append(timeStepNumber)
            timing.append(time)
            timing.append(dt)

            monTempLine = "{0:13s}".format(str(time.getValue()))

            # ---------------------------
            # macro step (X-Stream)
            # ---------------------------
            xst.solveStep(istep, runInBackground=False)

            # get the macro temperature field
            fieldTemperature = xst.getField(FieldID.FID_Temperature, time)

            # ---------------------------
            # micro step (MICRESS)
            # for each macro RVE location defined in the vector p
            # ---------------------------
            vT = []
            concSE = []
            avgGrainSize = []
            thicknessCIG = []
            frac4 = []  # Cu(In,GA)3Se5
            frac5 = []  # Cu2-xSe
            frac2 = []  # CIGS
            vQF = []  # local quality factor

            timeMicroStep = 0
            pos = 0
            while (pos < len(p)):  # loop over macro locations
                usedInterfaces = len(mic)
                if ((pos + usedInterfaces - 1) >= len(p)):
                    # deactivate interfaces which will get no new location, resp. no work to do anymore
                    usedInterfaces = len(p) - pos

                for interface in range(usedInterfaces):

                    # get macro value for temperature, gradient always zero here

                    temp = fieldTemperature.evaluate(
                        p[pos + interface]).getValue()[0]
                    tcEnd = timeTime.time()
                    timing.append(tcEnd - tcStart)

                    tcStart = timeTime.time()

                    # generate Mupif property objects from values
                    propLocation = Property.ConstantProperty(
                        p[pos + interface], MICPropertyID.PID_RVELocation,
                        ValueType.Vector, 'm')
                    propT = Property.ConstantProperty(
                        temp, MICPropertyID.PID_Temperature, ValueType.Scalar,
                        'K', time, 0)
                    # z-gradient constant at 0.0 at the moment
                    propzG = Property.ConstantProperty(
                        0.0,
                        MICPropertyID.PID_zTemperatureGradient,
                        ValueType.Scalar,
                        'K/m',
                        time=None,
                        objectID=0)

                    ## set the properties for micro simulation
                    mic[interface].setProperty(propLocation)
                    mic[interface].setProperty(propT)
                    mic[interface].setProperty(propzG)

                    ## make a MICRESS step
                    mic[interface].solveStep(istep)

                for interface in range(usedInterfaces):

                    if cConf.debug:
                        print(str(pos + interface) + ' ')
                        sys.stdout.flush()

                    # the call to the solveStep is non-blocking
                    # here: wait for finishing time step at each voxel and grab phase fraction results
                    mic[interface].wait()

                    # grab the results and write them for each voxel in a table
                    if (first):
                        first = False
                        # get some general information from the Micress test case,
                        # i.e. see variable names
                        #pComponentNames = mic[interface].getProperty(MICPropertyID.PID_ComponentNames, time)
                        #pPhaseNames = mic[interface].getProperty(MICPropertyID.PID_PhaseNames, time)
                        pDimensions = mic[interface].getProperty(
                            MICPropertyID.PID_Dimensions,
                            istep.getTargetTime())
                        #componentNames = pComponentNames.getValue()
                        #phaseNames = pPhaseNames.getValue()
                        dimensions = pDimensions.getValue()
                        if cConf.debug:
                            print("Dimensions [um] = ", dimensions[0] * 1E6,
                                  dimensions[1] * 1E6, dimensions[2] * 1E6)

                    pT = mic[interface].getProperty(
                        MICPropertyID.PID_Temperature, istep.getTargetTime())
                    pPF = mic[interface].getProperty(
                        MICPropertyID.PID_PhaseFractions,
                        istep.getTargetTime())
                    pGS = mic[interface].getProperty(
                        MICPropertyID.PID_AvgGrainSizePerPhase,
                        istep.getTargetTime())

                    vT.append(pT.getValue())

                    # calculate se concentration [at%] from phase fractions in thin film (only!)
                    #   0 : initial matrix phase, ~ 0 %
                    #   2 : Cu (In,Ga) Se2 (CIGS), 1/2 %
                    #   4 : Cu (In,Ga)3 Se5, 5/9 %
                    #   5 : Cu2-x Se, 1/3 %
                    vPF = pPF.getValue(
                    )  # in %, full fraction means 100 % of complete RVE
                    cigsLayerFraction = vPF[0] + vPF[2] + vPF[4] + vPF[5]

                    frac4.append(vPF[4] / cigsLayerFraction *
                                 100)  # Cu(In,GA)3Se5
                    frac5.append(vPF[5] / cigsLayerFraction * 100)  # Cu2-xSe
                    frac2.append(vPF[2] / cigsLayerFraction * 100)  # CIGS

                    if (frac4[-1] == 0.0):
                        # trick applied because:
                        # a zero fraction of Cu(In,GA)3Se5 is the iqf minimum
                        # and leads to an overall qf of zero
                        # discuss with Jurjen
                        frac4[-1] = 1.E-06

                    c2 = frac2[-1] / 2.
                    c4 = frac4[-1] * 5. / 9.
                    c5 = frac5[-1] / 3.
                    concSE.append((c2 + c4 + c5))
                    if cConf.debug:
                        print("Phase fractions = ", vPF)
                        print("Se concentration = ", concSE[-1])

                    # average grain size of grains in the thin film layer
                    # the grain size of phase 0 (matrix or liquid) is not defined
                    # and not in the vector, i.e. indices have to be shifted left
                    vGS = pGS.getValue()
                    #avgGS = (vGS[1]+vGS[3]+vGS[4])/3.0  # see comment about indices !!!
                    avgGS = vGS[1]  # take only CIGS grains
                    avgGrainSize.append(avgGS)
                    if cConf.debug:
                        print("Average grain size = ", avgGS)

                    # heuristic for the thickness of the thin film layer
                    # homogeneously distributed in xy plane
                    # RVE extension in Z [um] * 1E6 * ( CIGS layer phase fractions (0,2,4,5) / 100 )
                    CIGSThickness = dimensions[2] * (
                        vPF[0] + vPF[2] + vPF[4] +
                        vPF[5]) * 1E4  # in micrometer
                    thicknessCIG.append(CIGSThickness)
                    if cConf.debug:
                        print("CIGS thickness [um] = ", CIGSThickness)

                    # calculating local quality factors
                    # frac4 = Cu(In,GA)3Se5
                    # frac5 = Cu2-xSe
                    vQF.append( qfactor.calc ( \
                        ( avgGrainSize[-1], thicknessCIG[-1], frac5[-1], frac4[-1] ) ) )
                    if cConf.debug:
                        print("Quality factor = ", vQF[-1])

                # go to next locations
                pos += usedInterfaces

            # ---------------------------
            # end of micro step loop
            # ---------------------------

            tcEnd = timeTime.time()  # take duration from micro step
            timing.append(tcEnd - tcStart)
            if cConf.debug:
                print
            sys.stdout.flush()

            # ----------------------------------
            # map Se concentration to emissivity
            # ----------------------------------
            vEm = lookup.convert(concSE)
            if cConf.debug:
                print("Emissivity values")
                print(vEm)

            # --------------------------
            # generate emissivity field
            # --------------------------
            emissivityValues = []
            for val in vEm:
                emissivityValues.append((val, ))
            fieldEmissivity = Field.Field( bgMesh, XStFieldID.FID_Emissivity, \
                                ValueType.Scalar, 'none', 0.0, emissivityValues )
            #if cConf.debug:
            #print "writing emissivity field"
            #sys.stdout.flush()

            #fieldEmissivity.field2VTKData('emissivity').tofile('Em_'+str(timing[-5]).zfill(4))

            # ------------------------------------------------------
            # set emissivity field as an X-Stream boundary condition
            # ------------------------------------------------------

            # set the emissivity field as a new macro boundary condition
            if cConf.debug:
                print("setField emissivity for X-Stream")
            tcStart = timeTime.time()  # see end above after xstream.solveStep
            xst.setField(fieldEmissivity)

            # write monitor files
            # first column: simulation time
            mon = []
            monLine = "{0:13s}".format(str(time))
            monRange = len(cConf.monFilenames)
            for i in range(monRange):
                mon.append(monLine)

            # write local properties:
            #  2nd column: average of local values
            #  3rd to nth column: local values

            for i in range(len(vT)):  # all vectors have the same length
                monLine = "{0:13s}".format(str(round(vT[i], 4)))
                mon[0] = mon[0] + monLine
                if (monRange > 1):
                    monLine = "{0:13s}".format(str(round(concSE[i], 6)))
                    mon[1] = mon[1] + monLine
                    monLine = "{0:13s}".format(str(round(avgGrainSize[i], 6)))
                    mon[2] = mon[2] + monLine
                    monLine = "{0:13s}".format(str(round(thicknessCIG[i], 6)))
                    mon[3] = mon[3] + monLine
                    monLine = "{0:13s}".format(str(round(frac5[i], 6)))
                    mon[4] = mon[4] + monLine
                    monLine = "{0:13s}".format(str(round(frac4[i], 6)))
                    mon[5] = mon[5] + monLine
                    monLine = "{0:13s}".format(str(round(vQF[i], 6)))
                    mon[6] = mon[6] + monLine
                    monLine = "{0:13s}".format(str(round(vEm[i], 6)))
                    mon[7] = mon[7] + monLine
                    monLine = "{0:13s}".format(str(round(frac2[i], 6)))
                    mon[8] = mon[8] + monLine
            for i in range(monRange):
                f = open(cConf.monFilenames[i], 'a')
                f.write(mon[i] + '\n')
                f.close()

            # ---------------------------
            # end of time loop
            # ---------------------------

    except Exception as e:
        print(e)
        log.exception(e)
        raise e

    return