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')
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)
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