def _set_mesh(self): minCoord = tuple([nd(val) for val in self.minCoord]) maxCoord = tuple([nd(val) for val in self.maxCoord]) self.mesh = uw.mesh.FeMesh_Cartesian(elementType=self.elementType, elementRes=self.elementRes, minCoord=minCoord, maxCoord=maxCoord, periodic=self.periodic)
def __init__(self, name="User defined", func=None): self.name = name if not isinstance(func, dict): self.fn = fn.misc.constant(nd(func)) else: dictVals = func self.coefs = dictVals["coefficients"] self._nd_coefs = { key: nd(val) for key, val in self.coefs.iteritems() } self.fn = rheology.Functions[dictVals["Type"]]
def _set_density(self): densityMap = {} for material in self.materials: if self.temperature: densityMap[material.index] = nd(material.density) * ( 1.0 - nd(material.thermalExpansivity) * (self.temperature - nd(self.Tref))) else: densityMap[material.index] = nd(material.density) self.densityFn = fn.branching.map(fn_key=self.material, mapping=densityMap)
def _set_viscosity(self): ViscosityMap = {} BGViscosityMap = {} for material in self.materials: backgroundViscosity = material.viscosity._get_effective_viscosity( self.pressure, self.strainRate, self.temperature, self.solutionExist) ViscosityMap[material.index] = self._viscosity_limiter( backgroundViscosity) BGViscosityMap[material.index] = ViscosityMap[material.index] if material.plasticity: eff_viscosity = material.plasticity._get_effective_viscosity( self.plasticStrain, self.pressure, self.strainRate_2ndInvariant, nd(self.strainRate_default)) ViscosityMap[material.index] = self._viscosity_limiter( fn.misc.min(eff_viscosity, backgroundViscosity)) self.viscosityFn = fn.branching.map(fn_key=self.material, mapping=ViscosityMap) # Yielding backgroundViscosityFn = fn.branching.map(fn_key=self.material, mapping=BGViscosityMap) SYconditions = [(self.viscosityFn < backgroundViscosityFn, self.strainRate_2ndInvariant), (True, 0.0)] self.isYielding = fn.branching.conditional(SYconditions) return self.viscosityFn, self.isYielding
def set_temperatureBCs(self, left=None, right=None, top=None, bottom=None, indexSets=[]): self.temperature = uw.mesh.MeshVariable(mesh=self.mesh, nodeDofCount=1) self._temperatureDot = uw.mesh.MeshVariable(mesh=self.mesh, nodeDofCount=1) self.temperature.data[...] = nd(self.Tref) self._temperatureDot.data[...] = 0. indices = [self.mesh.specialSets["Empty"]] if left is not None: self.temperature.data[self.leftWall.data] = nd(left) indices[0] += self.leftWall if right is not None: self.temperature.data[self.rightWall.data] = nd(right) indices[0] += self.rightWall if top is not None: self.temperature.data[self.topWall.data] = nd(top) indices[0] += self.topWall if bottom is not None: self.temperature.data[self.bottomWall.data] = nd(bottom) indices[0] += self.bottomWall for indexSet, temp in indexSets: self.temperature.data[indexSet.data] = nd(temp) indices[0] += indexSet self._temperatureBCs = uw.conditions.DirichletCondition( variable=self.temperature, indexSetsPerDof=indices)
def add_material(self, vertices=None, reset=False, name="unknown", shape=None, top=None, bottom=None): if reset: self.materials = [] if vertices: vertices = [(nd(x), nd(y)) for x, y in vertices] mat = Material( name=name, vertices=vertices, diffusivity=self.global_thermal_diffusivity, capacity=self.global_thermal_capacity, thermalExpansivity=self.global_thermal_expansivity, radiogenicHeatProd=self.global_radiogenic_heat_production, shape=shape, minX=nd(self.minCoord[0]), maxX=nd(self.maxCoord[0]), top=nd(top), bottom=nd(bottom)) mat.indices = self._get_material_indices(mat) self.materials.reverse() self.materials.append(mat) self.materials.reverse() self._fill_model() return mat
def set_velocityBCs(self, left=None, right=None, top=None, bottom=None, indexSets=[]): indices = [self.mesh.specialSets["Empty"]] * self.mesh.dim if left is not None: for dim in range(self.mesh.dim): if left[dim] is not None: self.velocity.data[self.leftWall.data, dim] = nd(left[dim]) indices[dim] += self.leftWall if right is not None: for dim in range(self.mesh.dim): if right[dim] is not None: self.velocity.data[self.rightWall.data, dim] = nd(right[dim]) indices[dim] += self.rightWall if top is not None: for dim in range(self.mesh.dim): if top[dim] is not None: self.velocity.data[self.topWall.data, dim] = nd(top[dim]) indices[dim] += self.topWall if bottom is not None: for dim in range(self.mesh.dim): if bottom[dim] is not None: self.velocity.data[self.bottomWall.data, dim] = nd(bottom[dim]) indices[dim] += self.bottomWall for indexSet, temp in indexSets: for dim in range(self.mesh.dim): if indexSet[dim] is not None: self.velocity.data[indexSet.data, dim] = nd(indexSet[dim]) indices[dim] += indexSet self._velocityBCs = uw.conditions.DirichletCondition( variable=self.velocity, indexSetsPerDof=indices)
def _get_effective_viscosity(self, pressure, strainRate, temperature, solutionExist): if isinstance(self.fn, fn.misc.constant): return self.fn # Need to generalize that R = nd(8.3144621 * u.joule / u.mole / u.degK) return self.fn(R=R, strainRateFn=strainRate, pressureFn=pressure, temperatureFn=temperature, solutionExist=solutionExist, **self._nd_coefs)
def solve_temperature_steady_state(self): DiffusivityMap = {} for material in self.materials: DiffusivityMap[material.index] = nd(material.diffusivity) self.DiffusivityFn = fn.branching.map(fn_key=self.material, mapping=DiffusivityMap) HeatProdMap = {} for material in self.materials: HeatProdMap[material.index] = nd(material.radiogenicHeatProd) / ( nd(material.density) * nd(material.capacity)) self.HeatProdFn = fn.branching.map(fn_key=self.material, mapping=HeatProdMap) heatequation = uw.systems.SteadyStateHeat( temperatureField=self.temperature, fn_diffusivity=self.DiffusivityFn, fn_heating=self.HeatProdFn, conditions=self._temperatureBCs) heatsolver = uw.systems.Solver(heatequation) heatsolver.solve(nonLinearIterate=True)
def run_for(self, endTime=None, checkpoint=None): self.time = 0. units = endTime.units endTime = self.time + nd(endTime) step = 0 next_checkpoint = None if checkpoint: next_checkpoint = self.time + nd(checkpoint) while self.time < endTime: self.solve() if self.time == next_checkpoint: self.checkpointID += 1 self.checkpoint() next_checkpoint += nd(checkpoint) # Whats the longest we can run before reaching the end of the model # or a checkpoint? # Need to generalize that dt = self.swarm_advector.get_max_dt() if self.temperature: dt = min(dt, self.advdiffSystem.get_max_dt()) if checkpoint: dt = min(dt, next_checkpoint - self.time) self._dt = min(dt, endTime - self.time) uw.barrier() self.update() step += 1 if checkpoint or step % 1 == 0: print "Time: ", str(sca.Dimensionalize(self.time, units))
def init_advection_diffusion(self): DiffusivityMap = {} for material in self.materials: DiffusivityMap[material.index] = nd(material.diffusivity) self.DiffusivityFn = fn.branching.map(fn_key=self.material, mapping=DiffusivityMap) HeatProdMap = {} for material in self.materials: HeatProdMap[material.index] = ( nd(material.radiogenicHeatProd) / (nd(material.density) * nd(material.capacity))) self.HeatProdFn = fn.branching.map(fn_key=self.material, mapping=HeatProdMap) self.advdiffSystem = uw.systems.AdvectionDiffusion( self.temperature, self._temperatureDot, velocityField=self.velocity, fn_diffusivity=self.DiffusivityFn, fn_sourceTerm=self.HeatProdFn, conditions=[self._temperatureBCs])
velocity = 1. * u.centimeter / u.year KL = 1e3 * u.meter Kt = KL / velocity KT = tempMax KM = bodyforce * KL**2 * Kt**2 K = 1. * u.mole lengthScale = 1e3 sca.scaling["[length]"] = KL sca.scaling["[time]"] = Kt sca.scaling["[mass]"] = KM sca.scaling["[temperature]"] = KT sca.scaling["[substance]"] = K gravity = nd(9.81 * u.meter / u.second**2) R = nd(8.3144621 * u.joule / u.mole / u.degK) elementType = "Q1/dQ0" resX = 128 resY = 64 materialA = 0 materialB = 1 mesh = uw.mesh.FeMesh_Cartesian(elementType=(elementType), elementRes=(resX, resY), periodic=[False, False]) #if(LoadFromFile == False): minX = nd(-0.5 * u.kilometer) maxX = nd(0.5 * u.kilometer)
def __init__(self, elementRes, minCoord, maxCoord, gravity, periodic=(False, False), elementType="Q1/dQ0", swarmLayout=None, Tref=273.15 * u.degK, name="undefined", outputDir="outputs"): self.name = name self.outputDir = outputDir self.checkpointID = 0 self._checkpoint = None self.checkpoint = None self.minViscosity = 1e19 * u.pascal * u.second self.maxViscosity = 1e25 * u.pascal * u.second self.gravity = tuple([nd(val) for val in gravity]) self.Tref = Tref self.elementType = elementType self.elementRes = elementRes self.minCoord = minCoord self.maxCoord = maxCoord self.periodic = periodic self._set_mesh() # Add common fields self.temperature = None self.pressure = uw.mesh.MeshVariable(mesh=self.mesh.subMesh, nodeDofCount=1) self.velocity = uw.mesh.MeshVariable(mesh=self.mesh, nodeDofCount=self.mesh.dim) self.swarm = uw.swarm.Swarm(mesh=self.mesh, particleEscape=True) if swarmLayout is not None: self._swarmLayout = swarmLayout else: self._swarmLayout = uw.swarm.layouts.GlobalSpaceFillerLayout( swarm=self.swarm, particlesPerCell=25) self.swarm.populate_using_layout(layout=self._swarmLayout) self.swarm_population_control = uw.swarm.PopulationControl( self.swarm, aggressive=True, splitThreshold=0.15, maxDeletions=2, maxSplits=10, particlesPerCell=20) self.swarm_advector = uw.systems.SwarmAdvector( swarm=self.swarm, velocityField=self.velocity, order=self.mesh.dim) # symmetric component of the gradient of the flow velocity. self.strainRate_default = 1.0e-15 / u.second self.solutionExist = fn.misc.constant(False) self.strainRate = fn.tensor.symmetric(self.velocity.fn_gradient) self.strainRate_2ndInvariant = fn.tensor.second_invariant( self.strainRate) # Force initialisation to zero self.pressure.data[...] = 0. self.velocity.data[...] = 0. # Add Common Swarm Variables self.material = self.swarm.add_variable(dataType="int", count=1) self.plasticStrain = self.swarm.add_variable(dataType="double", count=1) self.plasticStrain.data[...] = 0.0 self.materials = [] self._defaultMaterial = 0 self.leftWall = self.mesh.specialSets["MinI_VertexSet"] self.topWall = self.mesh.specialSets["MaxJ_VertexSet"] self.bottomWall = self.mesh.specialSets["MinJ_VertexSet"] self.rightWall = self.mesh.specialSets["MaxI_VertexSet"] if self.mesh.dim > 2: self.frontWall = self.mesh.specialSets["MinK_VertexSet"] self.backWall = self.mesh.specialSets["MaxK_VertexSet"] self.time = 0.0 # global variables self.global_thermal_diffusivity = None self.global_thermal_capacity = None self.global_thermal_expansivity = None self.global_radiogenic_heat_production = None self._lecodeRefMaterial = None
def _viscosity_limiter(self, viscosityFn): maxViscosity = fn.misc.constant(nd(self.maxViscosity)) minViscosity = fn.misc.constant(nd(self.minViscosity)) maxBound = fn.misc.min(viscosityFn, maxViscosity) minMaxBound = fn.misc.max(maxBound, minViscosity) return minMaxBound
def _get_friction(self, plasticStrain): self.friction = self.frictionFn( plasticStrain, FrictionCoef=nd(self.coefs["FrictionCoef"]), FrictionCoefSw=nd(self.coefs["FrictionCoefSw"]))
def _get_cohesion(self, plasticStrain): self.cohesion = self.cohesionFn(plasticStrain, Cohesion=nd(self.coefs["Cohesion"]), CohesionSw=nd( self.coefs["CohesionSw"]))
def update(): # get timestep and advect particles dt = advector.get_max_dt() if (Elasticity == True): if dt > (dt_e / 3.): dt = dt_e / 3. print dt_e / time_factor print dt / time_factor print dt / time_factor advector.integrate(dt) adv_deform1.integrate(dt) adv_deform2.integrate(dt) ''' with mesh.deform_mesh( isRegular=True ): mesh.data[:,0] += mesh_vels[:]*dt newtime = time + dt # recalc mesh exten newminX = minX - meshV * newtime newmaxX = maxX + meshV * newtime ''' # particle population control pop_control.repopulate() # smoothed stress history for use in (t + 1) timestep if (Elasticity == True): phi = dt / dt_e stressDropUnit = [ nd(1e6 * u.pascal), nd(1e6 * u.pascal), nd(1e6 * u.pascal) ] stressMapFn_data = stressMapFn.evaluate(swarm) ## reduce stress by 1 MPa once it reaches yielding point #swarmYield = viscosityMapFn.evaluate(swarm) > viscosityFn.evaluate(swarm) #stressMapFn_data2 = np.where(swarmYield,stressMapFn_data-stressDropUnit, stressMapFn_data ) #previousStress.data[:] = ( phi*stressMapFn_data2[:] + ( 1.-phi )*previousStress.data[:] ) previousStress.data[:] = (phi * stressMapFn_data[:] + (1. - phi) * previousStress.data[:]) # update plastic strain swarmYield = viscosityMapFn.evaluate(swarm) > viscosityFn.evaluate(swarm) swarmStrainRateInv = strainRate_2ndInvariantFn.evaluate(swarm) plasticStrainIncrement = dt * np.where(swarmYield, swarmStrainRateInv, 0.0) plasticStrain.data[:] += plasticStrainIncrement plasticStrain0.data[:] = plasticStrainIncrement ''' for index, coord in enumerate(swarm.particleCoordinates.data): x = coord[0] if (x < minX+0.05 or x > maxX-0.05): plasticStrain.data[index] = 0. ''' #newmeshV = (math.sin(newtime/nd(10000*u.year)*3.1415926))*nd(1e-14/u.second)*newmaxX #newmeshV = nd(0*1e-14/u.second)*newmaxX #if step < 250: # newmeshV = nd(5e-14/u.second)*newmaxX return time + dt, step + 1