def swarmMinMax():
    fn_swarmX = fn.view.min_max(fn.coord()[0])
    fn_swarmY = fn.view.min_max(fn.coord()[1])
    fn_swarmX.reset()
    fn_swarmX.evaluate(swarm)
    fn_swarmY.reset()
    fn_swarmY.evaluate(swarm)
    sxmin = fn_swarmX.min_global()
    sxmax = fn_swarmX.max_global()
    symin = fn_swarmY.min_global()
    symax = fn_swarmY.max_global()
    return sxmin, sxmax, symin, symax
def swarmMinMax():
    fn_swarmX = fn.view.min_max( fn.coord()[0] )
    fn_swarmY = fn.view.min_max( fn.coord()[1] )
    fn_swarmX.reset()
    fn_swarmX.evaluate( swarm )
    fn_swarmY.reset()
    fn_swarmY.evaluate( swarm )
    sxmin = fn_swarmX.min_global()
    sxmax = fn_swarmX.max_global()
    symin = fn_swarmY.min_global()
    symax = fn_swarmY.max_global()
    return sxmin, sxmax, symin, symax
def pop_or_perish(tectModel, fCollect, masterSwarm, maskFn, ds):

    """
    Adds particles from a 'template' array; assumed to be a uniform layout near the surface
    Akin to adding more `weak crust` on the subducting plate
    Need to be careful to properly catch empty arrays,
    Otherwise parallel becomes a problem
    masterSwarm is the surface layout of the faults.
    """

    #build the main plate ID function, including the plate boundary mask.
    #we need to flip the mask function before handing to plate_id_fn

    maskFn_ = tectModel.t2f(maskFn)
    pIdFn = tectModel.plate_id_fn(maskFn=maskFn_)
    #evaluate on the master swarm (local proc)
    iDs = pIdFn.evaluate(masterSwarm)
    #loop through faults
    for f in fCollect:
        #mask for the plate, inclusing the specified plate boundary mask
        mask1 = np.where(iDs == f.ID)[0]


        plateParticles = masterSwarm.particleCoordinates.data[mask1,:]
        #this is hopefully the only parallel safeguard we need. But be afaid.

        #initially I was using a KDTree query to apply the new fault particles.
        #But this is really very unstable
        #if not f.empty:
        #    mask3 = (f.kdtree.query(plateParticles)[0] > ds)
        #    dataToAdd = masterSwarm.particleCoordinates.data[mask1,:][mask3]
            #now we can add these in
        #    f.swarm.add_particles_with_coordinates(dataToAdd)

        #Now I'm using the global extent of the interface2D swarm,
        #To define where NOT to add new particles
        minmax_coordx = fn.view.min_max(fn.coord()[0])
        ignore = minmax_coordx.evaluate(f.swarm)
        leftExt = minmax_coordx.min_global()
        rightExt = minmax_coordx.max_global()
        #print("fault extent", leftExt , rightExt)

        if not f.empty:
            mask3 = np.logical_or(plateParticles[:,0] < (leftExt - ds),  plateParticles[:,0] > (rightExt + ds))
            dataToAdd = masterSwarm.particleCoordinates.data[mask1,:][mask3]
            f.swarm.add_particles_with_coordinates(dataToAdd)
            #print("adding data", dataToAdd.shape)

        f.rebuild() #10/02/18
Exemple #4
0
    def __init__(
        self,
        pert=1e-6,
        freq=1e6,
        iterations=6,
        seed=1066,
    ):

        randTerms = []
        coordFns = fn.coord()
        x, y = coordFns[0], coordFns[1]
        radii = (fn.misc.constant(0.), fn.misc.constant(1.))
        radFn = (fn.math.sqrt(x**2 + y**2) - radii[0]) \
            / (radii[1] - radii[0])
        angFn = fn.math.atan2(y, x)
        for i in range(iterations):
            randPhase = fn.misc.constant(1.)
            phase = randPhase * math.pi
            partFn = pert * fn.math.sin(freq * (angFn + phase))
            randTerms.extend([
                randPhase,
            ])
            freq *= 2.
            pert /= 2.
            if i == 0: combFn = partFn
            else: combFn += partFn
        depthEaser = fn.math.sin(math.pi * radFn)
        waveFn = fn.misc.constant(1.) + depthEaser * combFn
        self.seed = seed
        self.radii = radii
        self.waveFn = waveFn
        self.randTerms = randTerms
        self._preditherings = dict()
        self._system = None

        super().__init__()
Exemple #5
0
def build(
    res=32,
    ratio=0.5,
    aspect=1.,
    length=1.,
    isoviscous=False,
    Ra=1e7,
    maxVisc=3e4,
    tau0=4e5,
    tau1=1e7,
):

    ### HOUSEKEEPING: IMPORTANT! ###

    inputs = locals().copy()
    script = __file__

    ### MESH & MESH VARIABLES ###

    outerRad = length / (1. - min(0.99999, max(0.00001, ratio)))
    radii = (outerRad - length, outerRad)
    width = length**2 * aspect * 2. / (radii[1]**2 - radii[0]**2)
    midpoint = math.pi / 2.
    angExtentRaw = (midpoint - 0.5 * width, midpoint + 0.5 * width)
    angularExtent = [item * 180. / math.pi for item in angExtentRaw]
    angLen = angExtentRaw[1] - angExtentRaw[0]
    radRes = res
    angRes = 4 * int(angLen * (int(radRes * radii[1] / length)) / 4.)
    elementRes = (radRes, angRes)

    mesh = uw.mesh.FeMesh_Annulus(elementRes=elementRes,
                                  radialLengths=radii,
                                  angularExtent=angularExtent,
                                  periodic=[False, False])

    temperatureField = uw.mesh.MeshVariable(mesh, 1)
    temperatureDotField = uw.mesh.MeshVariable(mesh, 1)
    pressureField = uw.mesh.MeshVariable(mesh.subMesh, 1)
    velocityField = uw.mesh.MeshVariable(mesh, 2)

    varsOfState = [((("temperatureField", temperatureField), ), ("mesh", mesh))
                   ]

    ### BOUNDARIES ###

    inner = mesh.specialSets["inner"]
    outer = mesh.specialSets["outer"]
    sides = mesh.specialSets["MaxJ_VertexSet"] + mesh.specialSets[
        "MinJ_VertexSet"]

    velBC = uw.conditions.RotatedDirichletCondition(
        variable=velocityField,
        indexSetsPerDof=(inner + outer, sides),
        basis_vectors=(mesh.bnd_vec_normal, mesh.bnd_vec_tangent))

    tempBC = uw.conditions.DirichletCondition(variable=temperatureField,
                                              indexSetsPerDof=(inner +
                                                               outer, ))

    ### RHEOLOGY ###

    vc = uw.mesh.MeshVariable(mesh=mesh, nodeDofCount=2)
    vc_eqNum = uw.systems.sle.EqNumber(vc, False)
    vcVec = uw.systems.sle.SolutionVector(vc, vc_eqNum)

    invDensityFn = temperatureField * Ra
    buoyancyFn = invDensityFn * mesh.unitvec_r_Fn

    if isoviscous:
        viscosityFn = creepViscFn = plasticViscFn = 1.
    else:
        magnitude = fn.math.sqrt(fn.coord()[0]**2 + fn.coord()[1]**2)
        depthFn = mesh.radialLengths[1] - magnitude
        yieldStressFn = tau0 + (tau1 * depthFn)
        secInvFn = fn.tensor.second_invariant(
            fn.tensor.symmetric(vc.fn_gradient))
        plasticViscFn = yieldStressFn / (2. * secInvFn + 1e-18)
        creepViscFn = fn.math.pow(fn.misc.constant(maxVisc),
                                  -1. * (temperatureField - 1.))
        viscosityFn = fn.misc.min(
            maxVisc, fn.misc.max(1., fn.misc.min(creepViscFn, plasticViscFn)))

    ### SYSTEMS ###

    stokes = uw.systems.Stokes(
        velocityField=velocityField,
        pressureField=pressureField,
        conditions=[
            velBC,
        ],
        fn_viscosity=viscosityFn,
        fn_bodyforce=buoyancyFn,
        _removeBCs=False,
    )

    solver = uw.systems.Solver(stokes)

    advDiff = uw.systems.AdvectionDiffusion(phiField=temperatureField,
                                            phiDotField=temperatureDotField,
                                            velocityField=vc,
                                            fn_diffusivity=1.,
                                            conditions=[
                                                tempBC,
                                            ])

    ### SOLVING ###

    def postSolve():
        # realign solution using the rotation matrix on stokes
        uw.libUnderworld.Underworld.AXequalsY(stokes._rot._cself,
                                              stokes._velocitySol._cself,
                                              vcVec._cself, False)
        # remove null space - the solid body rotation velocity contribution
        uw.libUnderworld.StgFEM.SolutionVector_RemoveVectorSpace(
            stokes._velocitySol._cself, stokes._vnsVec._cself)

    def solve():
        velocityField.data[:] = 0.
        solver.solve(
            nonLinearIterate=not isoviscous,
            callback_post_solve=postSolve,
        )
        uw.libUnderworld.Underworld.AXequalsX(stokes._rot._cself,
                                              stokes._velocitySol._cself,
                                              False)

    def integrate():
        dt = advDiff.get_max_dt()
        advDiff.integrate(dt)
        return dt

    def iterate():
        solve()
        return integrate()

    ### HOUSEKEEPING: IMPORTANT! ###
    return Grouper(locals())
Exemple #6
0
# In[12]:

# dissipation RMS
diss_rms = dissipationIntegral[0] / ( boxLength * boxHeight * boxWidth)


# In[55]:

print 'Dissipation, Total = {0:.3e}; min = {1:.3e}; max = {2:.3e}; v_rms = {3:.3e}'.format(dissipationIntegral[0], diss_min, diss_max, diss_rms)


# In[ ]:

# define region with slab, z > 0.4
# define the volume
fn_conditional_slab_vol   = fn.branching.conditional(  ( (fn.coord()[2] >= 0.5, 1.),
                                                         (                True, 0.) ) )
fn_conditional_craton_vol = fn.branching.conditional(  ( (fn.coord()[2] <  0.5, 1.),
                                                (                     True, 0.) ) )


# In[49]:

slab_vol   = mesh.integrate(fn_conditional_slab_vol)[0]


# In[50]:

craton_vol = mesh.integrate(fn_conditional_craton_vol)[0]

# In[12]:

# dissipation RMS
diss_rms = dissipationIntegral[0] / (boxLength * boxHeight * boxWidth)

# In[55]:

print 'Dissipation, Total = {0:.3e}; min = {1:.3e}; max = {2:.3e}; v_rms = {3:.3e}'.format(
    dissipationIntegral[0], diss_min, diss_max, diss_rms)

# In[ ]:

# define region with slab, z > 0.4
# define the volume
fn_conditional_slab_vol = fn.branching.conditional(
    ((fn.coord()[2] >= 0.5, 1.), (True, 0.)))
fn_conditional_craton_vol = fn.branching.conditional(
    ((fn.coord()[2] < 0.5, 1.), (True, 0.)))

# In[49]:

slab_vol = mesh.integrate(fn_conditional_slab_vol)[0]

# In[50]:

craton_vol = mesh.integrate(fn_conditional_craton_vol)[0]

# In[51]:

print slab_vol, craton_vol, slab_vol + craton_vol
Exemple #8
0
swarm.populate_using_layout( layout=swarmLayout )
add_timing("Swarm.populate_using_layout()", time()-ts)


# define these for convience. 
denseIndex = 0
lightIndex = 1

# material perturbation from van Keken et al. 1997
wavelength = 2.0
amplitude  = 0.02
offset     = 0.2
k = 2. * math.pi / wavelength

# Create function to return particle's coordinate
coord = fn.coord()

# Define the material perturbation, a function of the x coordinate (accessed by `coord[0]`).
perturbationFn = offset + amplitude*fn.math.cos( k*coord[0] )

# Setup the conditions list. 
# If z is less than the perturbation, set to lightIndex.
conditions = [ ( perturbationFn > coord[1] , lightIndex ),
               (                      True , denseIndex ) ]

# The swarm is passed as an argument to the evaluation, providing evaluation on each particle.
# Results are written to the materialIndex swarm variable.
fnc = fn.branching.conditional( conditions )
ts = time()
matdat = fnc.evaluate(swarm)
add_timing("Function.evaluate()", time()-ts)
Exemple #9
0
def build(
    res=32,
    isoviscous=False,
    aspect=1.,
    length=1.,
    Ra=1e7,
    maxVisc=3e4,
    tau0=4e5,
    tau1=1e7,
):

    ### HOUSEKEEPING: IMPORTANT! ###

    inputs = locals().copy()
    script = __file__

    ### MESH & MESH VARIABLES ###

    elementRes = (res, int(int(4. * res * aspect) / 4))
    maxCoord = (aspect, length)

    mesh = uw.mesh.FeMesh_Cartesian(elementRes=elementRes, maxCoord=maxCoord)

    temperatureField = uw.mesh.MeshVariable(mesh, 1)
    temperatureDotField = uw.mesh.MeshVariable(mesh, 1)
    pressureField = uw.mesh.MeshVariable(mesh.subMesh, 1)
    velocityField = uw.mesh.MeshVariable(mesh, 2)

    varsOfState = [((("temperatureField", temperatureField), ), ("mesh", mesh))
                   ]

    ### BOUNDARIES ###

    inner = mesh.specialSets["MinJ_VertexSet"]
    outer = mesh.specialSets["MaxJ_VertexSet"]
    sides = mesh.specialSets["MaxI_VertexSet"] + mesh.specialSets[
        "MinI_VertexSet"]

    velBC = uw.conditions.DirichletCondition(
        variable=velocityField,
        indexSetsPerDof=(sides, inner + outer),
    )

    tempBC = uw.conditions.DirichletCondition(variable=temperatureField,
                                              indexSetsPerDof=(inner +
                                                               outer, ))

    ### RHEOLOGY ###

    invDensityFn = temperatureField * Ra
    buoyancyFn = invDensityFn * (0., 1.)

    if isoviscous:
        viscosityFn = creepViscFn = plasticViscFn = 1.
    else:
        magnitude = fn.math.sqrt(fn.coord()[0]**2 + fn.coord()[1]**2)
        depthFn = mesh.maxCoord[1] - magnitude
        yieldStressFn = tau0 + (tau1 * depthFn)
        secInvFn = fn.tensor.second_invariant(
            fn.tensor.symmetric(velocityField.fn_gradient))
        plasticViscFn = yieldStressFn / (2. * secInvFn + 1e-18)
        creepViscFn = fn.math.pow(fn.misc.constant(maxVisc),
                                  -1. * (temperatureField - 1.))
        viscosityFn = fn.misc.min(
            maxVisc, fn.misc.max(1., fn.misc.min(creepViscFn, plasticViscFn)))

    ### SYSTEMS ###

    stokes = uw.systems.Stokes(
        velocityField=velocityField,
        pressureField=pressureField,
        conditions=[
            velBC,
        ],
        fn_viscosity=viscosityFn,
        fn_bodyforce=buoyancyFn,
        _removeBCs=False,
    )

    solver = uw.systems.Solver(stokes)

    advDiff = uw.systems.AdvectionDiffusion(phiField=temperatureField,
                                            phiDotField=temperatureDotField,
                                            velocityField=velocityField,
                                            fn_diffusivity=1.,
                                            conditions=[
                                                tempBC,
                                            ])

    ### SOLVING ###

    def solve():
        velocityField.data[:] = 0.
        solver.solve(nonLinearIterate=not isoviscous, )

    def integrate():
        dt = advDiff.get_max_dt()
        advDiff.integrate(dt)
        return dt

    def iterate():
        solve()
        return integrate()

    ### HOUSEKEEPING: IMPORTANT! ###
    return Grouper(locals())
Exemple #10
0
fieldDict = OrderedDict()  # important to avoid racing conditions
fieldDict["mvar"] = mvar

swarm = uw.swarm.Swarm(mesh=mesh)
svar = swarm.add_variable('int', 1)

swarmLayout = uw.swarm.layouts.PerCellSpaceFillerLayout(swarm=swarm,
                                                        particlesPerCell=20)
if restartFlag is False:
    swarm.populate_using_layout(layout=swarmLayout)

swarmDict = OrderedDict()  # important to avoid racing conditions
swarmDict["tcoords"] = svar
svar.data[:] = 0
svar.data[fn.coord()[0].evaluate(swarm) > 0.5] = 1
outputDirName = "t3d_960_llr"

outputDir = os.path.join(os.path.abspath("."), outputDirName + "/")
if restartFlag is False:
    checkpoint(mesh, fieldDict, swarm, swarmDict, index=0, prefix=outputDir)

if restartFlag is True:
    checkpoint(mesh,
               fieldDict,
               swarm,
               swarmDict,
               index=0,
               prefix=outputDir,
               load=True)
Exemple #11
0
def spectral_integral(mesh,
                      fnToInt,
                      N,
                      axisIndex=0,
                      kernelFn=1.,
                      average=True,
                      integrationType="volume",
                      surfaceIndexSet=None,
                      returnCoeffs=False):
    """
    Returns a function that represents the spectral integral over one of the UW mesh axes.
    The axis over which the integration is performed is parallel to the provided axisIndex.
    (the sin & cosine modes are created orthogonal the axisIndex).

    Parameters
    ----------
    mesh: uw.mesh.FeMesh
        The mesh over which integration is performed.
    fnToInt: uw.function.Function
        Function to be integrated.
    N: int
       Total number of modes to use (inluding mode 0)
    axisIndex: int (0, or 1)
       Index of the mesh axis to integrate over
    kernelFn: uw.function.Function
        An additional scalar of vector valued function can be provided.
        For instance, the upward continuation kernel used in potential field reconstuction
    average: Bool
        If True, include the average (mode 0) component in the returned Fn
    integrationType : str
        Type of integration to perform.  Options are "volume" or "surface".
    surfaceIndexSet : uw.mesh.FeMesh_IndexSet
        Must be provided where integrationType is "surface".
    returnCoeffs: Bool
        If True, return a list of coefficient a_k, b_k in addition to the reconstructed function


    Notes
    ----------
    In the fourier synthesis, a factor of 2./W needs to be applied to all modes > 0. W is the total width of the spatial domain
    (the axis over which Fourier coeffients were generated). A factor of 1./W needs to be applied to the average/DC component.
    For more details on these normalizations see http://mathworld.wolfram.com/FourierSeries.html

    """

    if integrationType:
        if not isinstance(integrationType, str):
            raise TypeError("'integrationType' provided must be a string.")
        integrationType = integrationType.lower()
        if integrationType not in ["volume", "surface"]:
            raise ValueError(
                "'integrationType' string provided must be either 'volume' or 'surface'."
            )
    if integrationType == "surface":
        if not surfaceIndexSet:
            raise RuntimeError(
                "For surface integration, you must provide a 'surfaceIndexSet'."
            )

    if axisIndex == 0:
        modeaxes = 1
    elif axisIndex == 1:
        modeaxes = 0
    else:
        raise ValueError("axisIndex must either of 0 or 1")

    if N <= 2:
        raise ValueError(
            "N must be at least 2, otherwise you should use an integral (N=1)")

    # create set of wavenumbers / modes
    res = mesh.elementRes[modeaxes]
    width = abs(mesh.maxCoord[modeaxes] - mesh.minCoord[modeaxes])
    height = abs(mesh.maxCoord[axisIndex] - mesh.minCoord[axisIndex])
    ax_ = fn.coord()[modeaxes]
    modes = []
    #ks = []
    for i in range(1, N):
        factor = float(i) * 2. * np.pi / width
        modes.append(factor * ax_)
        #ks.append(factor)

    sinfns = fn.math.sin(modes)
    cosfns = fn.math.cos(modes)

    if average:
        #average_ = uw.utils.Integral((2./width)*fnToInt,mesh)
        average_ = uw.utils.Integral(fnToInt, mesh)

    else:
        average_ = fn.misc.constant(0.)

    if integrationType == "volume":
        sin_coeffs = uw.utils.Integral(fnToInt * kernelFn * sinfns, mesh)
        cos_coeffs = uw.utils.Integral(fnToInt * kernelFn * cosfns, mesh)

    else:
        sin_coeffs = uw.utils.Integral(fnToInt * kernelFn * sinfns,
                                       mesh,
                                       integrationType='surface',
                                       surfaceIndexSet=surfaceIndexSet)
        cos_coeffs = uw.utils.Integral(fnToInt * kernelFn * cosfns,
                                       mesh,
                                       integrationType='surface',
                                       surfaceIndexSet=surfaceIndexSet)

    synthFn = (2./width)*fn.math.dot(sin_coeffs.evaluate(),sinfns) + \
              (2./width)*fn.math.dot(cos_coeffs.evaluate(),cosfns) + \
                         (1./width)*average_.evaluate()[0]

    if not returnCoeffs:
        return synthFn
    else:
        return synthFn, [sin_coeffs, cos_coeffs]
Exemple #12
0
swarm.populate_using_layout( layout=swarmLayout )
add_timing("Swarm.populate_using_layout()", time()-ts)


# define these for convience. 
denseIndex = 0
lightIndex = 1

# material perturbation from van Keken et al. 1997
wavelength = 2.0
amplitude  = 0.02
offset     = 0.2
k = 2. * math.pi / wavelength

# Create function to return particle's coordinate
coord = fn.coord()

# Define the material perturbation, a function of the x coordinate (accessed by `coord[0]`).
perturbationFn = offset + amplitude*fn.math.cos( k*coord[0] )

# Setup the conditions list. 
# If z is less than the perturbation, set to lightIndex.
conditions = [ ( perturbationFn > coord[1] , lightIndex ),
               (                      True , denseIndex ) ]

# The swarm is passed as an argument to the evaluation, providing evaluation on each particle.
# Results are written to the materialIndex swarm variable.
fnc = fn.branching.conditional( conditions )
ts = time()
matdat = fnc.evaluate(swarm)
add_timing("Function.evaluate()", time()-ts)