Beispiel #1
0
    def setUp(self):
        """
    Setup mesh and associated field.
    """
        from spatialdata.geocoords.CSCart import CSCart
        cs = CSCart()
        cs.inventory.spaceDim = 2
        cs._configure()

        from spatialdata.units.Nondimensional import Nondimensional
        normalizer = Nondimensional()
        normalizer._configure()

        from pylith.meshio.MeshIOAscii import MeshIOAscii
        importer = MeshIOAscii()
        importer.inventory.filename = "data/tri3.mesh"
        importer.inventory.coordsys = cs
        importer._configure()
        self.mesh = importer.read(debug=False, interpolate=False)

        from pylith.topology.SolutionFields import SolutionFields
        fields = SolutionFields(self.mesh)
        fields.add("disp t+dt", "displacement")
        fields.solutionName("disp t+dt")
        solution = fields.solution()
        solution.newSection(solution.VERTICES_FIELD, self.mesh.dimension())
        solution.allocate()
        solution.zero()

        self.fields = fields
        self.jacobian = Jacobian(solution)
        return
    def setUp(self):
        from pylith.meshio.MeshIOAscii import MeshIOAscii
        iohandler = MeshIOAscii()
        filename = "data/twohex8.txt"

        from spatialdata.units.Nondimensional import Nondimensional
        normalizer = Nondimensional()
        normalizer._configure()

        from spatialdata.geocoords.CSCart import CSCart
        iohandler.inventory.filename = filename
        iohandler.inventory.coordsys = CSCart()
        iohandler._configure()
        mesh = iohandler.read(debug=False, interpolate=False)

        from pylith.topology.SolutionFields import SolutionFields
        fields = SolutionFields(mesh)

        name = "disp(t)"
        fields.add(name, "displacement")
        fields.solutionName(name)
        field = fields.get(name)
        field.subfieldAdd("displacement", mesh.dimension(), field.VECTOR)
        field.subfieldsSetup()
        field.newSection(field.VERTICES_FIELD, mesh.dimension())
        field.allocate()

        self.mesh = mesh
        self.fields = fields
        self.normalizer = normalizer
        return
Beispiel #3
0
  def setUp(self):
    """
    Setup mesh and associated field.
    """
    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()    

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    self.mesh = importer.read(debug=False, interpolate=False)

    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(self.mesh)
    fields.add("disp t+dt", "displacement")
    fields.solutionName("disp t+dt")
    solution = fields.solution()
    solution.newSection(solution.VERTICES_FIELD, self.mesh.dimension())
    solution.allocate()
    solution.zero()

    self.fields = fields
    self.jacobian = Jacobian(solution)
    return
  def setUp(self):
    from pylith.meshio.MeshIOAscii import MeshIOAscii
    iohandler = MeshIOAscii()
    filename = "data/twohex8.txt"
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    from spatialdata.geocoords.CSCart import CSCart
    iohandler.inventory.filename = filename
    iohandler.inventory.coordsys = CSCart()
    iohandler._configure()
    mesh = iohandler.read(debug=False, interpolate=False)

    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)

    name = "disp(t)"
    fields.add(name, "displacement")
    fields.solutionName(name)
    field = fields.get(name)
    field.subfieldAdd("displacement", mesh.dimension(), field.VECTOR)
    field.subfieldsSetup()
    field.newSection(field.VERTICES_FIELD, mesh.dimension())
    field.allocate()

    self.mesh = mesh
    self.fields = fields
    self.normalizer = normalizer
    return
Beispiel #5
0
  def setUp(self):
    """
    Setup mesh and associated field.
    """
    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()    

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    self.mesh = importer.read(debug=False, interpolate=False)
    
    self.fields = SolutionFields(self.mesh)
    return
  def setUp(self):
    """
    Setup mesh and associated field.
    """
    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()    

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    self.mesh = importer.read(debug=False, interpolate=False)
    
    self.fields = SolutionFields(self.mesh)
    return
class TestSolutionFields(unittest.TestCase):
  """
  Unit testing of SolutionFields object.
  """

  def setUp(self):
    """
    Setup mesh and associated field.
    """
    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()    

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    self.mesh = importer.read(debug=False, interpolate=False)
    
    self.fields = SolutionFields(self.mesh)
    return


  def test_constructor(self):
    """
    Test constructor.
    """
    return


  def test_solutionName(self):
    """
    Test mesh().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");
    fields.add("field C", "C");
    
    fields.solutionName("field B")
    return


  def test_solution(self):
    """
    Test solution().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");
    fields.add("field C", "C");
    
    fields.solutionName("field B")
    solution = self.fields.solution()
    return


  def test_fieldAdd(self):
    """
    Test fieldAdd().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");

    helper_fieldAdd(fields)
    fieldA = fields.get("field A")
    fieldB = fields.get("field B")
    fieldA.allocate()
    fieldB.allocate()
    fieldA.copy(fieldB)
    return
  def _initialize(self):
    """
    Initialize fault.
    """
    dt = 2.4
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    # Setup mesh
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    mesh = importer.read(debug=False, interpolate=False)

    # Setup quadrature
    from pylith.feassemble.FIATSimplex import FIATSimplex
    cell = FIATSimplex()
    cell.inventory.dimension = 1
    cell.inventory.degree = 1
    cell.inventory.order = 1
    cell._configure()
    from pylith.feassemble.Quadrature import Quadrature
    quadrature = Quadrature()
    quadrature.inventory.cell = cell
    quadrature._configure()

    # Setup earthquake source
    from spatialdata.spatialdb.SimpleDB import SimpleDB
    from spatialdata.spatialdb.SimpleIOAscii import SimpleIOAscii
    ioFinalSlip = SimpleIOAscii()
    ioFinalSlip.inventory.filename = "data/tri3_finalslip.spatialdb"
    ioFinalSlip._configure()
    dbFinalSlip = SimpleDB()
    dbFinalSlip.inventory.iohandler = ioFinalSlip
    dbFinalSlip.inventory.label = "final slip"
    dbFinalSlip._configure()
    
    ioSlipTime = SimpleIOAscii()
    ioSlipTime.inventory.filename = "data/tri3_sliptime.spatialdb"
    ioSlipTime._configure()
    dbSlipTime = SimpleDB()
    dbSlipTime.inventory.iohandler = ioSlipTime
    dbSlipTime.inventory.label = "slip time"
    dbSlipTime._configure()
    
    from pylith.faults.StepSlipFn import StepSlipFn
    slipfn = StepSlipFn()
    slipfn.inventory.dbSlip = dbFinalSlip
    slipfn.inventory.dbSlipTime = dbSlipTime
    slipfn._configure()

    # Setup fault
    fault = FaultCohesiveKin()
    fault.inventory.output.inventory.writer._configure()
    fault.inventory.output._configure()
    fault.inventory.matId = 10
    fault.inventory.faultLabel = "fault"
    fault.inventory.upDir = [0, 0, 1]
    fault.inventory.faultQuadrature = quadrature
    fault._configure()
    eqsrc = fault.eqsrcs.components()[0]
    eqsrc.inventory.originTime = 1.23*second
    eqsrc.inventory.slipfn = slipfn
    eqsrc._configure()

    nvertices = fault.numVerticesNoMesh(mesh)
    firstFaultVertex = 0
    firstLagrangeVertex = nvertices
    firstFaultCell      = 2*nvertices
    fault.adjustTopology(mesh, firstFaultVertex, firstLagrangeVertex,
                         firstFaultCell)
    fault.preinitialize(mesh)
    fault.timeStep(dt)
    fault.verifyConfiguration()
    from pyre.units.time import s
    fault.initialize(totalTime=0.0*s, numTimeSteps=1, normalizer=normalizer)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("dispIncr(t->t+dt)", "displacement_increment")
    fields.add("disp(t)", "displacement")
    fields.solutionName("dispIncr(t->t+dt)")

    residual = fields.get("residual")
    residual.subfieldAdd("displacement", cs.spaceDim(), residual.VECTOR)
    residual.subfieldAdd("lagrange_multiplier", cs.spaceDim(), residual.VECTOR)
    residual.subfieldsSetup()
    residual.setupSolnChart()
    residual.setupSolnDof(cs.spaceDim())
    fault.setupSolnDof(residual)
    residual.allocate()
    residual.zero()

    fields.copyLayout("residual")
    
    return (mesh, fault, fields)
Beispiel #9
0
class Formulation(PetscComponent, ModuleFormulation):
  """
  Python abstract base class for formulations of solving equations.

  In general, we use some explicit or implicit formulation of the PDEs
  to create a linear form, [A]{u}={b} that we can solve.

  Factory: pde_formulation.
  """

  # INVENTORY //////////////////////////////////////////////////////////

  class Inventory(PetscComponent.Inventory):
    """
    Python object for managing Formulation facilities and properties.
    """

    ## @class Inventory
    ## Python object for managing Formulation facilities and properties.
    ##
    ## \b Properties
    ## @li \b matrix_type Type of PETSc sparse matrix.
    ## @li \b split_fields Split solution fields into displacements and Lagrange constraints.
    ## @li \b use_custom_constraint_pc Use custom preconditioner for Lagrange constraints.
    ## @li \b view_jacobian Flag to output Jacobian matrix when it is reformed.
    ##
    ## \b Facilities
    ## @li \b time_step Time step size manager.
    ## @li \b solver Algebraic solver.
    ## @li \b output Output manager associated with solution.
    ## @li \b jacobian_viewer Writer for Jacobian sparse matrix.

    import pyre.inventory

    matrixType = pyre.inventory.str("matrix_type", default="unknown")
    matrixType.meta['tip'] = "Type of PETSc sparse matrix."

    useSplitFields = pyre.inventory.bool("split_fields", default=False)
    useSplitFields.meta['tip'] = "Split solution fields into displacements "\
        "and Lagrange multipliers for separate preconditioning."

    useCustomConstraintPC = pyre.inventory.bool("use_custom_constraint_pc",
                                                default=False)
    useCustomConstraintPC.meta['tip'] = "Use custom preconditioner for " \
                                        "Lagrange constraints."

    viewJacobian = pyre.inventory.bool("view_jacobian", default=False)
    viewJacobian.meta['tip'] = "Write Jacobian matrix to binary file."
    
    from TimeStepUniform import TimeStepUniform
    timeStep = pyre.inventory.facility("time_step", family="time_step",
                                       factory=TimeStepUniform)
    timeStep.meta['tip'] = "Time step size manager."

    from SolverLinear import SolverLinear
    solver = pyre.inventory.facility("solver", family="solver",
                                     factory=SolverLinear)
    solver.meta['tip'] = "Algebraic solver."

    from pylith.meshio.SingleOutput import SingleOutput
    output = pyre.inventory.facilityArray("output",
                                          itemFactory=outputFactory,
                                          factory=SingleOutput)
    output.meta['tip'] = "Output managers associated with solution."

    from pylith.topology.JacobianViewer import JacobianViewer
    jacobianViewer = pyre.inventory.facility("jacobian_viewer", 
                                             family="jacobian_viewer",
                                             factory=JacobianViewer)
    jacobianViewer.meta['tip'] = "Writer for Jacobian sparse matrix."

    from pylith.perf.MemoryLogger import MemoryLogger
    perfLogger = pyre.inventory.facility("perf_logger", family="perf_logger",
                                         factory=MemoryLogger)
    perfLogger.meta['tip'] = "Performance and memory logging."


  # PUBLIC METHODS /////////////////////////////////////////////////////

  def __init__(self, name="formulation"):
    """
    Constructor.
    """
    PetscComponent.__init__(self, name, facility="formulation")
    # ModuleFormulation constructor called in base clase
    self.integrators = None
    self.constraints = None
    self.jacobian = None
    self.fields = None
    return


  def preinitialize(self, mesh, materials, boundaryConditions,
                    interfaceConditions, gravityField):
    """
    Create integrator for each element family.
    """
    self._setupLogging()
    logEvent = "%spreinit" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.preinitialize()

    import weakref
    self.mesh = weakref.ref(mesh)
    self.integrators = []
    self.constraints = []
    self.gravityField = gravityField

    self.solver.preinitialize()
    self._setupMaterials(materials)
    self._setupBC(boundaryConditions)
    self._setupInterfaces(interfaceConditions)

    if 0 == comm.rank:
      self._info.log("Pre-initializing output.")
    for output in self.output.components():
      output.preinitialize()

    self._eventLogger.eventEnd(logEvent)
    return


  def verifyConfiguration(self):
    """
    Verify compatibility of configuration.
    """
    logEvent = "%sverify" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self.timeStep.verifyConfiguration()

    for integrator in self.integrators:
      integrator.verifyConfiguration()
    for constraint in self.constraints:
      constraint.verifyConfiguration()
    for output in self.output.components():
      output.verifyConfiguration(self.mesh())

    self._eventLogger.eventEnd(logEvent)
    return


  def initialize(self, dimension, normalizer):
    """
    Initialize formulation.
    """
    raise NotImplementedError("Please implement 'initialize' in derived class.")
  

  def getStartTime(self):
    """
    Get start time for simulation.
    """
    return self.timeStep.startTimeN


  def getTotalTime(self):
    """
    Get total time for simulation.
    """
    return self.timeStep.totalTimeN # Nondimensionalized total time


  def getTimeStep(self):
    """
    Get stable time step for advancing forward in time.
    """
    logEvent = "%stimestep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    dt = self.timeStep.timeStep(self.mesh(), self.integrators)

    self._eventLogger.eventEnd(logEvent)
    return dt
  

  def prestep(self, t, dt):
    """
    Hook for doing stuff before advancing time step.
    """
    logEvent = "%sprestep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self._eventLogger.eventEnd(logEvent)
    return


  def step(self, t, dt):
    """
    Advance to next time step.
    """
    logEvent = "%sstep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self._eventLogger.eventEnd(logEvent)
    return


  def poststep(self, t, dt):
    """
    Hook for doing stuff after advancing time step.
    """
    logEvent = "%spoststep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    for integrator in self.integrators:
      integrator.poststep(t, dt, self.fields)
    for constraint in self.constraints:
      constraint.poststep(t, dt, self.fields)

    self._eventLogger.eventEnd(logEvent)
    return


  def finalize(self):
    """
    Cleanup after time stepping.
    """
    logEvent = "%sfinalize" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Formulation finalize.")
    self._debug.log(resourceUsageString())
    for integrator in self.integrators:
      integrator.finalize()
    for constraint in self.constraints:
      constraint.finalize()
    for output in self.output.components():
      output.close()
      output.finalize()
    self._debug.log(resourceUsageString())
    
    self._modelMemoryUse()

    self._eventLogger.eventEnd(logEvent)
    return
  

  # PRIVATE METHODS ////////////////////////////////////////////////////

  def _configure(self):
    """
    Set members based using inventory.
    """
    PetscComponent._configure(self)
    self.matrixType = self.inventory.matrixType
    self.timeStep = self.inventory.timeStep
    self.solver = self.inventory.solver
    self.output = self.inventory.output
    self.viewJacobian = self.inventory.viewJacobian
    self.jacobianViewer = self.inventory.jacobianViewer
    self.perfLogger = self.inventory.perfLogger

    import journal
    self._debug = journal.debug(self.name)

    if self.inventory.useCustomConstraintPC and \
           not self.inventory.useSplitFields:
      print "WARNING: Request to use custom preconditioner for Lagrange " \
            "constraints without splitting fields. " \
            "Setting split fields flag to 'True'."
      self.inventory.useSplitFields = True

    ModuleFormulation.splitFields(self, self.inventory.useSplitFields)
    ModuleFormulation.useCustomConstraintPC(self, self.inventory.useCustomConstraintPC)

    return


  def _setJacobianMatrixType(self):
    """
    Determine appropriate PETSc matrix type for Jacobian matrix.
    """
    # Mapping from symmetric matrix type to nonsymmetric matrix type
    matrixMap = {'sbaij': 'baij',
                 'seqsbaij': 'seqbaij',
                 'mpisbaij': 'mpibaij',
                 'unknown': 'aij'}
    isJacobianSymmetric = True
    for integrator in self.integrators:
      if not integrator.isJacobianSymmetric():
        isJacobianSymmetric = False
    if not isJacobianSymmetric:
      if self.matrixType in matrixMap.keys():
        print "WARNING: Jacobian matrix will not be symmetric.\n" \
              "         Switching matrix type from '%s' to '%s'." % \
              (self.matrixType, matrixMap[self.matrixType])
        self.matrixType = matrixMap[self.matrixType]
    self.blockMatrixOkay = True
    if self.matrixType == "unknown" and self.solver.useCUDA:
      self.matrixType = "aijcusp"
    for constraint in self.constraints:
      numDimConstrained = constraint.numDimConstrained()
      if numDimConstrained > 0 and self.mesh().dimension() != numDimConstrained:
        self.blockMatrixOkay = False
    return


  def _setupMaterials(self, materials):
    """
    Setup materials as integrators.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing materials.")
    self._debug.log(resourceUsageString())
    for material in materials.components():
      integrator = self.elasticityIntegrator()
      if not implementsIntegrator(integrator):
        raise TypeError, \
              "Could not use '%s' as an integrator for material '%s'. " \
              "Functionality missing." % (integrator.name, material.label())
      integrator.preinitialize(self.mesh(), material)
      self.integrators.append(integrator)
      self._debug.log(resourceUsageString())

      if 0 == comm.rank:
        self._info.log("Added elasticity integrator for material '%s'." % material.label())
    return


  def _setupBC(self, boundaryConditions):
    """
    Setup boundary conditions as integrators or constraints.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    from pylith.feassemble.Constraint import implementsConstraint
    from pylith.bc.PointForce import PointForce

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing boundary conditions.")
    self._debug.log(resourceUsageString())
    for bc in boundaryConditions.components():
      bc.preinitialize(self.mesh())
      foundType = False
      if implementsIntegrator(bc):
        foundType = True
        self.integrators.append(bc)
        if 0 == comm.rank:
          self._info.log("Added boundary condition '%s' as an integrator." % \
                           bc.label())
      if implementsConstraint(bc):
        foundType = True
        self.constraints.append(bc)
        if 0 == comm.rank:
          self._info.log("Added boundary condition '%s' as a constraint." % \
                           bc.label())
      if not foundType:
        raise TypeError, \
              "Could not determine whether boundary condition '%s' is an " \
              "integrator or a constraint." % bc.name
    self._debug.log(resourceUsageString())    
    return


  def _setupInterfaces(self, interfaceConditions):
    """
    Setup interfaces as integrators or constraints.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    from pylith.feassemble.Constraint import implementsConstraint

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing interior interfaces.")
    for ic in interfaceConditions.components():
      ic.preinitialize(self.mesh())
      foundType = False
      if implementsIntegrator(ic):
        foundType = True
        self.integrators.append(ic)
        if 0 == comm.rank:
          self._info.log("Added interface condition '%s' as an integrator." % \
                           ic.label())
      if implementsConstraint(ic):
        foundType = True
        self.constraints.append(ic)
        if 0 == comm.rank:
          self._info.log("Added interface condition '%s' as a constraint." % \
                           ic.label())
      if not foundType:
        raise TypeError, \
              "Could not determine whether interface condition '%s' is an " \
              "integrator or a constraint." % ic.name
    self._debug.log(resourceUsageString())    
    return
  

  def _initialize(self, dimension, normalizer):
    """
    Create integrators for each element family.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.initialize(normalizer)

    numTimeSteps = self.timeStep.numTimeSteps()
    totalTime = self.timeStep.totalTime

    from pylith.topology.SolutionFields import SolutionFields
    self.fields = SolutionFields(self.mesh())
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing integrators.")
    for integrator in self.integrators:
      if not self.gravityField is None:
        integrator.gravityField(self.gravityField)
      integrator.initialize(totalTime, numTimeSteps, normalizer)
    ModuleFormulation.integrators(self, self.integrators)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing constraints.")
    for constraint in self.constraints:
      constraint.initialize(totalTime, numTimeSteps, normalizer)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Setting up solution output.")
    for output in self.output.components():
      output.initialize(self.mesh(), normalizer)
      output.writeInfo()
      output.open(totalTime, numTimeSteps)
    self._debug.log(resourceUsageString())

    # Setup fields
    if 0 == comm.rank:
      self._info.log("Creating solution field.")
    #from pylith.utils.petsc import MemoryLogger
    #memoryLogger = MemoryLogger.singleton()
    #memoryLogger.setDebug(0)
    #memoryLogger.stagePush("Problem")
    self.fields.add("dispIncr(t->t+dt)", "displacement_increment")
    self.fields.add("disp(t)", "displacement")
    self.fields.add("residual", "residual")
    self.fields.solutionName("dispIncr(t->t+dt)")

    lengthScale = normalizer.lengthScale()
    pressureScale = normalizer.pressureScale()

    solution = self.fields.get("dispIncr(t->t+dt)")
    solution.subfieldAdd("displacement", dimension, solution.VECTOR, lengthScale.value)
    solution.subfieldAdd("lagrange_multiplier", dimension, solution.VECTOR, pressureScale.value)
    solution.subfieldsSetup()
    solution.setupSolnChart()
    solution.setupSolnDof(dimension)
    # Loop over integrators to adjust DOF layout
    for integrator in self.integrators:
      integrator.setupSolnDof(solution)
    solution.vectorFieldType(solution.VECTOR)
    solution.scale(lengthScale.value)

    for constraint in self.constraints:
      constraint.setConstraintSizes(solution)
    solution.allocate()
    solution.zeroAll()
    for constraint in self.constraints:
      constraint.setConstraints(solution)
    for integrator in self.integrators:
      integrator.checkConstraints(solution)

    #memoryLogger.stagePop()

    # This also creates a global order.
    solution.createScatter(solution.mesh())

    #memoryLogger.stagePush("Problem")
    dispT = self.fields.get("disp(t)")
    dispT.vectorFieldType(dispT.VECTOR)
    dispT.scale(lengthScale.value)

    residual = self.fields.get("residual")
    residual.vectorFieldType(residual.VECTOR)
    residual.scale(lengthScale.value)

    #memoryLogger.stagePop()
    #memoryLogger.setDebug(0)
    self._debug.log(resourceUsageString())

    return


  def _reformJacobian(self, t, dt):
    """
    Reform Jacobian matrix for operator.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self._debug.log(resourceUsageString())
    if 0 == comm.rank:
      self._info.log("Integrating Jacobian operator.")
    self._eventLogger.stagePush("Reform Jacobian")

    self.updateSettings(self.jacobian, self.fields, t, dt)
    self.reformJacobian()

    self._eventLogger.stagePop()

    if self.viewJacobian:
      from pylith.mpi.Communicator import Communicator
      comm = Communicator(self.mesh().comm())
      self.jacobianViewer.view(self.jacobian, t, comm)

    self._debug.log(resourceUsageString())
    return


  def _collectNeedNewJacobian(self, flagLocal):
    """
    Aggregate needNewJacobian results across processors.
    """
    if flagLocal:
      countLocal = 1
    else:
      countLocal = 0
    import pylith.mpi.mpi as mpi
    comm = self.mesh().comm()
    countAll = mpi.allreduce_scalar_int(countLocal, mpi.mpi_max(), comm.handle)
    
    return countAll > 0


  def _reformResidual(self, t, dt):
    """
    Reform residual vector for operator.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Integrating residual term in operator.")
    self._eventLogger.stagePush("Reform Residual")

    self.updateSettings(self.jacobian, self.fields, t, dt)
    self.reformResidual()

    self._eventLogger.stagePop()
    self._debug.log(resourceUsageString())
    return


  def _writeData(self, t):
    """
    Write data for time t.
    """
    logEvent = "%swrite" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    for integrator in self.integrators:
      integrator.writeData(t, self.fields)
    for constraint in self.constraints:
      constraint.writeData(t, self.fields)

    self._eventLogger.eventEnd(logEvent)
    return


  def _setupLogging(self):
    """
    Setup event logging.
    """
    if not "_loggingPrefix" in dir(self):
      self._loggingPrefix = ""

    from pylith.utils.EventLogger import EventLogger
    logger = EventLogger()
    logger.className("PDE Formulation")
    logger.initialize()

    events = ["preinit",
              "verify",
              "init",
              "timestep",
              "prestep",
              "step",
              "poststep",
              "write",
              "finalize"]
    for event in events:
      logger.registerEvent("%s%s" % (self._loggingPrefix, event))

    stages = ["Reform Jacobian",
              "Reform Residual",
              "Solve"]
    for stage in stages:
      logger.registerStage(stage)

    self._eventLogger = logger
    return


  def _modelMemoryUse(self):
    """
    Model memory allocation.
    """
    self.perfLogger.logFields('Problem', self.fields)
    self.perfLogger.logJacobian('Jacobian', 'dummy')
    self.perfLogger.logGlobalOrder('GlobalOrder', 'VectorOrder',
                                   self.fields.get('residual'))
    for integrator in self.integrators:
      self.perfLogger.logQuadrature('Quadrature', integrator.quadrature())
    return


  def _cleanup(self):
    """
    Deallocate PETSc and local data structures.
    """
    if not self.jacobian is None:
      self.jacobian.cleanup()
    if not self.fields is None:
      self.fields.cleanup()
    if not self.integrators is None:
      for integrator in self.integrators:
        integrator.cleanup()
    return
  def _initialize(self):
    """
    Initialize fault.
    """
    dt = 2.4
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    # Setup mesh
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    mesh = importer.read(debug=False, interpolate=False)

    # Setup quadrature
    from pylith.feassemble.FIATSimplex import FIATSimplex
    cell = FIATSimplex()
    cell.inventory.dimension = 1
    cell.inventory.degree = 1
    cell.inventory.order = 1
    cell._configure()
    from pylith.feassemble.Quadrature import Quadrature
    quadrature = Quadrature()
    quadrature.inventory.cell = cell
    quadrature._configure()

    # Setup rupture info
    from spatialdata.spatialdb.SimpleDB import SimpleDB
    from spatialdata.spatialdb.SimpleIOAscii import SimpleIOAscii
    ioTractions = SimpleIOAscii()
    ioTractions.inventory.filename = "data/tri3_initialtractions.spatialdb"
    ioTractions._configure()
    dbTractions = SimpleDB()
    dbTractions.inventory.iohandler = ioTractions
    dbTractions.inventory.label = "initial tractions"
    dbTractions._configure()
    from pylith.faults.TractPerturbation import TractPerturbation
    tract = TractPerturbation()
    tract.inventory.dbInitial = dbTractions
    tract._configure()

    ioFriction = SimpleIOAscii()
    ioFriction.inventory.filename = "data/tri3_staticfriction.spatialdb"
    ioFriction._configure()
    dbFriction = SimpleDB()
    dbFriction.inventory.iohandler = ioFriction
    dbFriction.inventory.label = "friction"
    dbFriction._configure()
    
    from pylith.friction.StaticFriction import StaticFriction
    friction = StaticFriction()
    friction.inventory.label = "Static friction"
    friction.inventory.dbProperties = dbFriction
    friction._configure()

    # Setup fault
    fault = FaultCohesiveDyn()
    fault.inventory.output.inventory.writer._configure()
    fault.inventory.output._configure()
    fault.inventory.matId = 10
    fault.inventory.faultLabel = "fault"
    fault.inventory.upDir = [0, 0, 1]
    fault.inventory.faultQuadrature = quadrature
    fault.inventory.tract = tract
    fault.inventory.friction = friction
    fault._configure()

    nvertices = fault.numVerticesNoMesh(mesh)
    firstFaultVertex = 0
    firstLagrangeVertex = nvertices
    firstFaultCell      = 2*nvertices
    fault.adjustTopology(mesh, firstFaultVertex, firstLagrangeVertex,
                         firstFaultCell)
    from pylith.topology.topology import MeshOps_nondimensionalize
    MeshOps_nondimensionalize(mesh, normalizer)

    fault.preinitialize(mesh)
    fault.timeStep(dt)
    fault.verifyConfiguration()
    from pyre.units.time import s
    fault.initialize(totalTime=0.0*s, numTimeSteps=1, normalizer=normalizer)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("dispIncr(t->t+dt)", "displacement_increment")
    fields.add("disp(t)", "displacement")
    fields.add("velocity(t)", "velocity")
    fields.solutionName("dispIncr(t->t+dt)")

    residual = fields.get("residual")
    residual.subfieldAdd("displacement", cs.spaceDim(), residual.VECTOR)
    residual.subfieldAdd("lagrange_multiplier", cs.spaceDim(), residual.VECTOR)
    residual.subfieldsSetup()
    residual.setupSolnChart()
    residual.setupSolnDof(cs.spaceDim())
    fault.setupSolnDof(residual)
    residual.allocate()
    residual.zero()

    fields.copyLayout("residual")
    
    return (mesh, fault, fields)
Beispiel #11
0
  def _initialize(self, dimension, normalizer):
    """
    Create integrators for each element family.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.initialize(normalizer)

    numTimeSteps = self.timeStep.numTimeSteps()
    totalTime = self.timeStep.totalTime

    from pylith.topology.SolutionFields import SolutionFields
    self.fields = SolutionFields(self.mesh())
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing integrators.")
    for integrator in self.integrators:
      if not self.gravityField is None:
        integrator.gravityField(self.gravityField)
      integrator.initialize(totalTime, numTimeSteps, normalizer)
    ModuleFormulation.integrators(self, self.integrators)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing constraints.")
    for constraint in self.constraints:
      constraint.initialize(totalTime, numTimeSteps, normalizer)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Setting up solution output.")
    for output in self.output.components():
      output.initialize(self.mesh(), normalizer)
      output.writeInfo()
      output.open(totalTime, numTimeSteps)
    self._debug.log(resourceUsageString())

    # Setup fields
    if 0 == comm.rank:
      self._info.log("Creating solution field.")
    #from pylith.utils.petsc import MemoryLogger
    #memoryLogger = MemoryLogger.singleton()
    #memoryLogger.setDebug(0)
    #memoryLogger.stagePush("Problem")
    self.fields.add("dispIncr(t->t+dt)", "displacement_increment")
    self.fields.add("disp(t)", "displacement")
    self.fields.add("residual", "residual")
    self.fields.solutionName("dispIncr(t->t+dt)")

    lengthScale = normalizer.lengthScale()
    pressureScale = normalizer.pressureScale()

    solution = self.fields.get("dispIncr(t->t+dt)")
    solution.subfieldAdd("displacement", dimension, solution.VECTOR, lengthScale.value)
    solution.subfieldAdd("lagrange_multiplier", dimension, solution.VECTOR, pressureScale.value)
    solution.subfieldsSetup()
    solution.setupSolnChart()
    solution.setupSolnDof(dimension)
    # Loop over integrators to adjust DOF layout
    for integrator in self.integrators:
      integrator.setupSolnDof(solution)
    solution.vectorFieldType(solution.VECTOR)
    solution.scale(lengthScale.value)

    for constraint in self.constraints:
      constraint.setConstraintSizes(solution)
    solution.allocate()
    solution.zeroAll()
    for constraint in self.constraints:
      constraint.setConstraints(solution)
    for integrator in self.integrators:
      integrator.checkConstraints(solution)

    #memoryLogger.stagePop()

    # This also creates a global order.
    solution.createScatter(solution.mesh())

    #memoryLogger.stagePush("Problem")
    dispT = self.fields.get("disp(t)")
    dispT.vectorFieldType(dispT.VECTOR)
    dispT.scale(lengthScale.value)

    residual = self.fields.get("residual")
    residual.vectorFieldType(residual.VECTOR)
    residual.scale(lengthScale.value)

    #memoryLogger.stagePop()
    #memoryLogger.setDebug(0)
    self._debug.log(resourceUsageString())

    return
  def _initialize(self, mesh, integrator):
    """
    Initialize integrator.
    """
    dt = 2.3
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    from pyre.units.time import s
    integrator.initialize(totalTime=0.0*s, numTimeSteps=1,
                          normalizer=normalizer)
    integrator.timeStep(dt)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("disp(t+dt)", "displacement")
    fields.add("disp(t)", "displacement")
    fields.add("disp(t-dt)", "displacement")
    fields.add("velocity(t)", "velocity")
    fields.add("acceleration(t)", "acceleration")
    fields.solutionName("disp(t+dt)")

    residual = fields.get("residual")
    residual.newSection(residual.VERTICES_FIELD, mesh.coordsys().spaceDim())
    residual.allocate()
    fields.copyLayout("residual")

    residual.zero()
    return fields
  def _initialize(self):
    """
    Initialize fault.
    """
    dt = 2.4
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    # Setup mesh
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    mesh = importer.read(debug=False, interpolate=False)

    # Setup quadrature
    from pylith.feassemble.FIATSimplex import FIATSimplex
    cell = FIATSimplex()
    cell.inventory.dimension = 1
    cell.inventory.degree = 1
    cell.inventory.order = 1
    cell._configure()
    from pylith.feassemble.Quadrature import Quadrature
    quadrature = Quadrature()
    quadrature.inventory.cell = cell
    quadrature._configure()

    # Setup impulses
    from spatialdata.spatialdb.SimpleDB import SimpleDB
    from spatialdata.spatialdb.SimpleIOAscii import SimpleIOAscii
    ioImpulseAmp = SimpleIOAscii()
    ioImpulseAmp.inventory.filename = "data/tri3_impulses.spatialdb"
    ioImpulseAmp._configure()
    dbImpulseAmp = SimpleDB()
    dbImpulseAmp.inventory.iohandler = ioImpulseAmp
    dbImpulseAmp.inventory.label = "impulse amplitude"
    dbImpulseAmp._configure()
    
    # Setup fault
    fault = FaultCohesiveImpulses()
    fault.inventory.output.inventory.writer._configure()
    fault.inventory.output._configure()
    fault.inventory.matId = 10
    fault.inventory.faultLabel = "fault"
    fault.inventory.upDir = [0, 0, 1]
    fault.inventory.faultQuadrature = quadrature
    fault.inventory.dbImpulseAmp = dbImpulseAmp
    fault._configure()

    nvertices = fault.numVerticesNoMesh(mesh)
    firstFaultVertex = 0
    firstLagrangeVertex = nvertices
    firstFaultCell      = 2*nvertices
    fault.adjustTopology(mesh, firstFaultVertex, firstLagrangeVertex,
                         firstFaultCell)
    fault.preinitialize(mesh)
    fault.timeStep(dt)
    fault.verifyConfiguration()
    from pyre.units.time import s
    fault.initialize(totalTime=0.0*s, numTimeSteps=1, normalizer=normalizer)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("dispIncr(t->t+dt)", "displacement_increment")
    fields.add("disp(t)", "displacement")
    fields.solutionName("dispIncr(t->t+dt)")

    residual = fields.get("residual")
    residual.subfieldAdd("displacement", cs.spaceDim(), residual.VECTOR)
    residual.subfieldAdd("lagrange_multiplier", cs.spaceDim(), residual.VECTOR)
    residual.subfieldsSetup()
    residual.setupSolnChart()
    residual.setupSolnDof(cs.spaceDim())
    fault.setupSolnDof(residual)
    residual.allocate()
    residual.zero()

    fields.copyLayout("residual")
    
    return (mesh, fault, fields)
    def _initialize(self, mesh, integrator):
        """
    Initialize integrator.
    """
        dt = 2.3

        from spatialdata.units.Nondimensional import Nondimensional
        normalizer = Nondimensional()
        normalizer._configure()

        from pyre.units.time import s
        integrator.initialize(totalTime=0.0 * s,
                              numTimeSteps=1,
                              normalizer=normalizer)
        integrator.timeStep(dt)

        # Setup fields
        from pylith.topology.SolutionFields import SolutionFields
        fields = SolutionFields(mesh)
        fields.add("residual", "residual")
        fields.add("disp(t)", "displacement")
        fields.add("dispIncr(t->t+dt)", "displacement_increment")
        fields.solutionName("dispIncr(t->t+dt)")

        residual = fields.get("residual")
        spaceDim = mesh.coordsys().spaceDim()
        lengthScale = normalizer.lengthScale()
        residual.subfieldAdd("displacement", spaceDim, residual.VECTOR,
                             lengthScale.value)
        residual.subfieldAdd("lagrange_multiplier", spaceDim, residual.VECTOR)

        residual.subfieldsSetup()
        residual.setupSolnChart()
        residual.setupSolnDof(spaceDim)
        residual.allocate()
        residual.zeroAll()
        fields.copyLayout("residual")

        return fields
Beispiel #15
0
class Formulation(PetscComponent, ModuleFormulation):
  """
  Python abstract base class for formulations of solving equations.

  In general, we use some explicit or implicit formulation of the PDEs
  to create a linear form, [A]{u}={b} that we can solve.

  Factory: pde_formulation.
  """

  # INVENTORY //////////////////////////////////////////////////////////

  class Inventory(PetscComponent.Inventory):
    """
    Python object for managing Formulation facilities and properties.
    """

    ## @class Inventory
    ## Python object for managing Formulation facilities and properties.
    ##
    ## \b Properties
    ## @li \b matrix_type Type of PETSc sparse matrix.
    ## @li \b split_fields Split solution fields into displacements and Lagrange constraints.
    ## @li \b use_custom_constraint_pc Use custom preconditioner for Lagrange constraints.
    ## @li \b view_jacobian Flag to output Jacobian matrix when it is reformed.
    ##
    ## \b Facilities
    ## @li \b time_step Time step size manager.
    ## @li \b solver Algebraic solver.
    ## @li \b output Output manager associated with solution.
    ## @li \b jacobian_viewer Writer for Jacobian sparse matrix.

    import pyre.inventory

    matrixType = pyre.inventory.str("matrix_type", default="unknown")
    matrixType.meta['tip'] = "Type of PETSc sparse matrix."

    useSplitFields = pyre.inventory.bool("split_fields", default=False)
    useSplitFields.meta['tip'] = "Split solution fields into displacements "\
        "and Lagrange multipliers for separate preconditioning."

    useCustomConstraintPC = pyre.inventory.bool("use_custom_constraint_pc",
                                                default=False)
    useCustomConstraintPC.meta['tip'] = "Use custom preconditioner for " \
                                        "Lagrange constraints."

    viewJacobian = pyre.inventory.bool("view_jacobian", default=False)
    viewJacobian.meta['tip'] = "Write Jacobian matrix to binary file."
    
    from TimeStepUniform import TimeStepUniform
    timeStep = pyre.inventory.facility("time_step", family="time_step",
                                       factory=TimeStepUniform)
    timeStep.meta['tip'] = "Time step size manager."

    from SolverLinear import SolverLinear
    solver = pyre.inventory.facility("solver", family="solver",
                                     factory=SolverLinear)
    solver.meta['tip'] = "Algebraic solver."

    from pylith.meshio.SingleOutput import SingleOutput
    output = pyre.inventory.facilityArray("output",
                                          itemFactory=outputFactory,
                                          factory=SingleOutput)
    output.meta['tip'] = "Output managers associated with solution."

    from pylith.topology.JacobianViewer import JacobianViewer
    jacobianViewer = pyre.inventory.facility("jacobian_viewer", 
                                             family="jacobian_viewer",
                                             factory=JacobianViewer)
    jacobianViewer.meta['tip'] = "Writer for Jacobian sparse matrix."

    from pylith.perf.MemoryLogger import MemoryLogger
    perfLogger = pyre.inventory.facility("perf_logger", family="perf_logger",
                                         factory=MemoryLogger)
    perfLogger.meta['tip'] = "Performance and memory logging."


  # PUBLIC METHODS /////////////////////////////////////////////////////

  def __init__(self, name="formulation"):
    """
    Constructor.
    """
    PetscComponent.__init__(self, name, facility="formulation")
    # ModuleFormulation constructor called in base clase
    self.integrators = None
    self.constraints = None
    self.jacobian = None
    self.fields = None
    return


  def preinitialize(self, mesh, materials, boundaryConditions,
                    interfaceConditions, gravityField):
    """
    Create integrator for each element family.
    """
    self._setupLogging()
    logEvent = "%spreinit" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.preinitialize()

    import weakref
    self.mesh = weakref.ref(mesh)
    self.integrators = []
    self.constraints = []
    self.gravityField = gravityField

    self.solver.preinitialize()
    self._setupMaterials(materials)
    self._setupBC(boundaryConditions)
    self._setupInterfaces(interfaceConditions)

    if 0 == comm.rank:
      self._info.log("Pre-initializing output.")
    for output in self.output.components():
      output.preinitialize()

    self._eventLogger.eventEnd(logEvent)
    return


  def verifyConfiguration(self):
    """
    Verify compatibility of configuration.
    """
    logEvent = "%sverify" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self.timeStep.verifyConfiguration()

    for integrator in self.integrators:
      integrator.verifyConfiguration()
    for constraint in self.constraints:
      constraint.verifyConfiguration()
    for output in self.output.components():
      output.verifyConfiguration(self.mesh())

    self._eventLogger.eventEnd(logEvent)
    return


  def initialize(self, dimension, normalizer):
    """
    Initialize formulation.
    """
    raise NotImplementedError("Please implement 'initialize' in derived class.")
  

  def getStartTime(self):
    """
    Get start time for simulation.
    """
    return self.timeStep.startTimeN


  def getTotalTime(self):
    """
    Get total time for simulation.
    """
    return self.timeStep.totalTimeN # Nondimensionalized total time


  def getTimeStep(self):
    """
    Get stable time step for advancing forward in time.
    """
    logEvent = "%stimestep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    dt = self.timeStep.timeStep(self.mesh(), self.integrators)

    self._eventLogger.eventEnd(logEvent)
    return dt
  

  def prestep(self, t, dt):
    """
    Hook for doing stuff before advancing time step.
    """
    logEvent = "%sprestep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self._eventLogger.eventEnd(logEvent)
    return


  def step(self, t, dt):
    """
    Advance to next time step.
    """
    logEvent = "%sstep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    self._eventLogger.eventEnd(logEvent)
    return


  def poststep(self, t, dt):
    """
    Hook for doing stuff after advancing time step.
    """
    logEvent = "%spoststep" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    for integrator in self.integrators:
      integrator.poststep(t, dt, self.fields)
    for constraint in self.constraints:
      constraint.poststep(t, dt, self.fields)

    self._eventLogger.eventEnd(logEvent)
    return


  def finalize(self):
    """
    Cleanup after time stepping.
    """
    logEvent = "%sfinalize" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Formulation finalize.")
    self._debug.log(resourceUsageString())
    for integrator in self.integrators:
      integrator.finalize()
    for constraint in self.constraints:
      constraint.finalize()
    for output in self.output.components():
      output.close()
      output.finalize()
    self._debug.log(resourceUsageString())
    
    self._modelMemoryUse()

    self._eventLogger.eventEnd(logEvent)
    return
  

  # PRIVATE METHODS ////////////////////////////////////////////////////

  def _configure(self):
    """
    Set members based using inventory.
    """
    PetscComponent._configure(self)
    self.matrixType = self.inventory.matrixType
    self.timeStep = self.inventory.timeStep
    self.solver = self.inventory.solver
    self.output = self.inventory.output
    self.viewJacobian = self.inventory.viewJacobian
    self.jacobianViewer = self.inventory.jacobianViewer
    self.perfLogger = self.inventory.perfLogger

    import journal
    self._debug = journal.debug(self.name)

    if self.inventory.useCustomConstraintPC and \
           not self.inventory.useSplitFields:
      print "WARNING: Request to use custom preconditioner for Lagrange " \
            "constraints without splitting fields. " \
            "Setting split fields flag to 'True'."
      self.inventory.useSplitFields = True

    ModuleFormulation.splitFields(self, self.inventory.useSplitFields)
    ModuleFormulation.useCustomConstraintPC(self, self.inventory.useCustomConstraintPC)

    return


  def _setJacobianMatrixType(self):
    """
    Determine appropriate PETSc matrix type for Jacobian matrix.
    """
    # Mapping from symmetric matrix type to nonsymmetric matrix type
    matrixMap = {'sbaij': 'baij',
                 'seqsbaij': 'seqbaij',
                 'mpisbaij': 'mpibaij',
                 'unknown': 'aij'}
    isJacobianSymmetric = True
    for integrator in self.integrators:
      if not integrator.isJacobianSymmetric():
        isJacobianSymmetric = False
    if not isJacobianSymmetric:
      if self.matrixType in matrixMap.keys():
        print "WARNING: Jacobian matrix will not be symmetric.\n" \
              "         Switching matrix type from '%s' to '%s'." % \
              (self.matrixType, matrixMap[self.matrixType])
        self.matrixType = matrixMap[self.matrixType]
    self.blockMatrixOkay = True
    if self.matrixType == "unknown" and self.solver.useCUDA:
      self.matrixType = "aijcusp"
    for constraint in self.constraints:
      numDimConstrained = constraint.numDimConstrained()
      if numDimConstrained > 0 and self.mesh().dimension() != numDimConstrained:
        self.blockMatrixOkay = False
    return


  def _setupMaterials(self, materials):
    """
    Setup materials as integrators.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing materials.")
    self._debug.log(resourceUsageString())
    for material in materials.components():
      integrator = self.elasticityIntegrator()
      if not implementsIntegrator(integrator):
        raise TypeError, \
              "Could not use '%s' as an integrator for material '%s'. " \
              "Functionality missing." % (integrator.name, material.label())
      integrator.preinitialize(self.mesh(), material)
      self.integrators.append(integrator)
      self._debug.log(resourceUsageString())

      if 0 == comm.rank:
        self._info.log("Added elasticity integrator for material '%s'." % material.label())
    return


  def _setupBC(self, boundaryConditions):
    """
    Setup boundary conditions as integrators or constraints.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    from pylith.feassemble.Constraint import implementsConstraint
    from pylith.bc.PointForce import PointForce

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing boundary conditions.")
    self._debug.log(resourceUsageString())
    for bc in boundaryConditions.components():
      bc.preinitialize(self.mesh())
      foundType = False
      if implementsIntegrator(bc):
        foundType = True
        self.integrators.append(bc)
        if 0 == comm.rank:
          self._info.log("Added boundary condition '%s' as an integrator." % \
                           bc.label())
      if implementsConstraint(bc):
        foundType = True
        self.constraints.append(bc)
        if 0 == comm.rank:
          self._info.log("Added boundary condition '%s' as a constraint." % \
                           bc.label())
      if not foundType:
        raise TypeError, \
              "Could not determine whether boundary condition '%s' is an " \
              "integrator or a constraint." % bc.name
    self._debug.log(resourceUsageString())    
    return


  def _setupInterfaces(self, interfaceConditions):
    """
    Setup interfaces as integrators or constraints.
    """
    from pylith.feassemble.Integrator import implementsIntegrator
    from pylith.feassemble.Constraint import implementsConstraint

    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Pre-initializing interior interfaces.")
    for ic in interfaceConditions.components():
      ic.preinitialize(self.mesh())
      foundType = False
      if implementsIntegrator(ic):
        foundType = True
        self.integrators.append(ic)
        if 0 == comm.rank:
          self._info.log("Added interface condition '%s' as an integrator." % \
                           ic.label())
      if implementsConstraint(ic):
        foundType = True
        self.constraints.append(ic)
        if 0 == comm.rank:
          self._info.log("Added interface condition '%s' as a constraint." % \
                           ic.label())
      if not foundType:
        raise TypeError, \
              "Could not determine whether interface condition '%s' is an " \
              "integrator or a constraint." % ic.name
    self._debug.log(resourceUsageString())    
    return
  

  def _initialize(self, dimension, normalizer):
    """
    Create integrators for each element family.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.initialize(normalizer)

    numTimeSteps = self.timeStep.numTimeSteps()
    totalTime = self.timeStep.totalTime

    from pylith.topology.SolutionFields import SolutionFields
    self.fields = SolutionFields(self.mesh())
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing integrators.")
    for integrator in self.integrators:
      if not self.gravityField is None:
        integrator.gravityField(self.gravityField)
      integrator.initialize(totalTime, numTimeSteps, normalizer)
    ModuleFormulation.integrators(self, self.integrators)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing constraints.")
    for constraint in self.constraints:
      constraint.initialize(totalTime, numTimeSteps, normalizer)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Setting up solution output.")
    for output in self.output.components():
      output.initialize(self.mesh(), normalizer)
      output.writeInfo()
      output.open(totalTime, numTimeSteps)
    self._debug.log(resourceUsageString())

    # Setup fields
    if 0 == comm.rank:
      self._info.log("Creating solution field.")
    #from pylith.utils.petsc import MemoryLogger
    #memoryLogger = MemoryLogger.singleton()
    #memoryLogger.setDebug(0)
    #memoryLogger.stagePush("Problem")
    self.fields.add("dispIncr(t->t+dt)", "displacement_increment")
    self.fields.add("disp(t)", "displacement")
    self.fields.add("residual", "residual")
    self.fields.solutionName("dispIncr(t->t+dt)")

    lengthScale = normalizer.lengthScale()
    pressureScale = normalizer.pressureScale()

    solution = self.fields.get("dispIncr(t->t+dt)")
    solution.subfieldAdd("displacement", dimension, solution.VECTOR, lengthScale.value)
    solution.subfieldAdd("lagrange_multiplier", dimension, solution.VECTOR, pressureScale.value)
    solution.subfieldsSetup()
    solution.setupSolnChart()
    solution.setupSolnDof(dimension)
    # Loop over integrators to adjust DOF layout
    for integrator in self.integrators:
      integrator.setupSolnDof(solution)
    solution.vectorFieldType(solution.VECTOR)
    solution.scale(lengthScale.value)

    for constraint in self.constraints:
      constraint.setConstraintSizes(solution)
    solution.allocate()
    solution.zeroAll()
    for constraint in self.constraints:
      constraint.setConstraints(solution)
    for integrator in self.integrators:
      integrator.checkConstraints(solution)

    #memoryLogger.stagePop()

    # This also creates a global order.
    solution.createScatter(solution.mesh())

    #memoryLogger.stagePush("Problem")
    dispT = self.fields.get("disp(t)")
    dispT.vectorFieldType(dispT.VECTOR)
    dispT.scale(lengthScale.value)

    residual = self.fields.get("residual")
    residual.vectorFieldType(residual.VECTOR)
    residual.scale(lengthScale.value)

    #memoryLogger.stagePop()
    #memoryLogger.setDebug(0)
    self._debug.log(resourceUsageString())

    return


  def _reformJacobian(self, t, dt):
    """
    Reform Jacobian matrix for operator.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self._debug.log(resourceUsageString())
    if 0 == comm.rank:
      self._info.log("Integrating Jacobian operator.")
    self._eventLogger.stagePush("Reform Jacobian")

    self.updateSettings(self.jacobian, self.fields, t, dt)
    self.reformJacobian()

    self._eventLogger.stagePop()

    if self.viewJacobian:
      from pylith.mpi.Communicator import Communicator
      comm = Communicator(self.mesh().comm())
      self.jacobianViewer.view(self.jacobian, t, comm)

    self._debug.log(resourceUsageString())
    return


  def _reformResidual(self, t, dt):
    """
    Reform residual vector for operator.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    if 0 == comm.rank:
      self._info.log("Integrating residual term in operator.")
    self._eventLogger.stagePush("Reform Residual")

    self.updateSettings(self.jacobian, self.fields, t, dt)
    self.reformResidual()

    self._eventLogger.stagePop()
    self._debug.log(resourceUsageString())
    return


  def _writeData(self, t):
    """
    Write data for time t.
    """
    logEvent = "%swrite" % self._loggingPrefix
    self._eventLogger.eventBegin(logEvent)

    for integrator in self.integrators:
      integrator.writeData(t, self.fields)
    for constraint in self.constraints:
      constraint.writeData(t, self.fields)

    self._eventLogger.eventEnd(logEvent)
    return


  def _setupLogging(self):
    """
    Setup event logging.
    """
    if not "_loggingPrefix" in dir(self):
      self._loggingPrefix = ""

    from pylith.utils.EventLogger import EventLogger
    logger = EventLogger()
    logger.className("PDE Formulation")
    logger.initialize()

    events = ["preinit",
              "verify",
              "init",
              "timestep",
              "prestep",
              "step",
              "poststep",
              "write",
              "finalize"]
    for event in events:
      logger.registerEvent("%s%s" % (self._loggingPrefix, event))

    stages = ["Reform Jacobian",
              "Reform Residual",
              "Solve"]
    for stage in stages:
      logger.registerStage(stage)

    self._eventLogger = logger
    return


  def _modelMemoryUse(self):
    """
    Model memory allocation.
    """
    self.perfLogger.logFields('Problem', self.fields)
    self.perfLogger.logJacobian('Jacobian', 'dummy')
    self.perfLogger.logGlobalOrder('GlobalOrder', 'VectorOrder',
                                   self.fields.get('residual'))
    for integrator in self.integrators:
      self.perfLogger.logQuadrature('Quadrature', integrator.quadrature())
    return


  def _cleanup(self):
    """
    Deallocate PETSc and local data structures.
    """
    if not self.jacobian is None:
      self.jacobian.cleanup()
    if not self.fields is None:
      self.fields.cleanup()
    if not self.integrators is None:
      for integrator in self.integrators:
        integrator.cleanup()
    return
  def _initialize(self):
    """
    Initialize AbsorbingDampers boundary condition.
    """
    from spatialdata.spatialdb.SimpleDB import SimpleDB
    db = SimpleDB()
    db.inventory.label = "TestAbsorbingDampers tri3"
    db.inventory.iohandler.inventory.filename = \
        "data/elasticplanestrain.spatialdb"
    db.inventory.iohandler._configure()
    db._configure()

    from pylith.feassemble.FIATSimplex import FIATSimplex
    cell = FIATSimplex()
    cell.inventory.dimension = 1
    cell.inventory.degree = 1
    cell.inventory.order = 1
    cell._configure()
    from pylith.feassemble.Quadrature import Quadrature
    quadrature = Quadrature()
    quadrature.inventory.cell = cell
    quadrature._configure()

    from pylith.bc.AbsorbingDampers import AbsorbingDampers
    bc = AbsorbingDampers()
    bc.inventory.quadrature = quadrature
    bc.inventory.db = db
    bc.inventory.id = 0
    bc.inventory.label = "bc"
    bc._configure()

    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    mesh = importer.read(debug=False, interpolate=False)
    
    bc.preinitialize(mesh)
    bc.initialize(totalTime=0.0, numTimeSteps=1, normalizer=normalizer)
    bc.timeStep(0.01)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("dispIncr(t->t+dt)", "displacement")
    fields.add("disp(t)", "displacement")
    fields.add("disp(t-dt)", "displacement")
    fields.add("velocity(t)", "velocity")
    fields.solutionName("dispIncr(t->t+dt)")

    residual = fields.get("residual")
    residual.newSection(residual.VERTICES_FIELD, cs.spaceDim())
    residual.allocate()
    residual.zero()

    fields.copyLayout("residual")
    
    return (mesh, bc, fields)
  def _initialize(self):
    """
    Initialize fault.
    """
    dt = 2.4
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    # Setup mesh
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    mesh = importer.read(debug=False, interpolate=False)

    # Setup quadrature
    from pylith.feassemble.FIATSimplex import FIATSimplex
    cell = FIATSimplex()
    cell.inventory.dimension = 1
    cell.inventory.degree = 1
    cell.inventory.order = 1
    cell._configure()
    from pylith.feassemble.Quadrature import Quadrature
    quadrature = Quadrature()
    quadrature.inventory.cell = cell
    quadrature._configure()

    # Setup impulses
    from spatialdata.spatialdb.SimpleDB import SimpleDB
    from spatialdata.spatialdb.SimpleIOAscii import SimpleIOAscii
    ioImpulseAmp = SimpleIOAscii()
    ioImpulseAmp.inventory.filename = "data/tri3_impulses.spatialdb"
    ioImpulseAmp._configure()
    dbImpulseAmp = SimpleDB()
    dbImpulseAmp.inventory.iohandler = ioImpulseAmp
    dbImpulseAmp.inventory.label = "impulse amplitude"
    dbImpulseAmp._configure()
    
    # Setup fault
    fault = FaultCohesiveImpulses()
    fault.inventory.output.inventory.writer._configure()
    fault.inventory.output._configure()
    fault.inventory.matId = 10
    fault.inventory.faultLabel = "fault"
    fault.inventory.upDir = [0, 0, 1]
    fault.inventory.faultQuadrature = quadrature
    fault.inventory.dbImpulseAmp = dbImpulseAmp
    fault._configure()

    nvertices = fault.numVerticesNoMesh(mesh)
    firstFaultVertex = 0
    firstLagrangeVertex = nvertices
    firstFaultCell      = 2*nvertices
    fault.adjustTopology(mesh, firstFaultVertex, firstLagrangeVertex,
                         firstFaultCell)
    fault.preinitialize(mesh)
    fault.timeStep(dt)
    fault.verifyConfiguration()
    from pyre.units.time import s
    fault.initialize(totalTime=0.0*s, numTimeSteps=1, normalizer=normalizer)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("dispIncr(t->t+dt)", "displacement_increment")
    fields.add("disp(t)", "displacement")
    fields.solutionName("dispIncr(t->t+dt)")
    residual = fields.get("residual")
    residual.newSection(residual.VERTICES_FIELD, cs.spaceDim())
    residual.allocate()
    residual.zero()
    fields.copyLayout("residual")
    
    return (mesh, fault, fields)
Beispiel #18
0
    def _initialize(self):
        """
    Initialize AbsorbingDampers boundary condition.
    """
        from spatialdata.spatialdb.SimpleDB import SimpleDB
        db = SimpleDB()
        db.inventory.label = "TestAbsorbingDampers tri3"
        db.inventory.iohandler.inventory.filename = \
            "data/elasticplanestrain.spatialdb"
        db.inventory.iohandler._configure()
        db._configure()

        from pylith.feassemble.FIATSimplex import FIATSimplex
        cell = FIATSimplex()
        cell.inventory.dimension = 1
        cell.inventory.degree = 1
        cell.inventory.order = 1
        cell._configure()
        from pylith.feassemble.Quadrature import Quadrature
        quadrature = Quadrature()
        quadrature.inventory.cell = cell
        quadrature._configure()

        from pylith.bc.AbsorbingDampers import AbsorbingDampers
        bc = AbsorbingDampers()
        bc.inventory.quadrature = quadrature
        bc.inventory.db = db
        bc.inventory.id = 0
        bc.inventory.label = "bc"
        bc._configure()

        from spatialdata.geocoords.CSCart import CSCart
        cs = CSCart()
        cs.inventory.spaceDim = 2
        cs._configure()

        from spatialdata.units.Nondimensional import Nondimensional
        normalizer = Nondimensional()
        normalizer._configure()

        from pylith.meshio.MeshIOAscii import MeshIOAscii
        importer = MeshIOAscii()
        importer.inventory.filename = "data/tri3.mesh"
        importer.inventory.coordsys = cs
        importer._configure()
        mesh = importer.read(debug=False, interpolate=False)

        bc.preinitialize(mesh)
        bc.initialize(totalTime=0.0, numTimeSteps=1, normalizer=normalizer)
        bc.timeStep(0.01)

        # Setup fields
        from pylith.topology.SolutionFields import SolutionFields
        fields = SolutionFields(mesh)
        fields.add("residual", "residual")
        fields.add("dispIncr(t->t+dt)", "displacement")
        fields.add("disp(t)", "displacement")
        fields.add("disp(t-dt)", "displacement")
        fields.add("velocity(t)", "velocity")
        fields.solutionName("dispIncr(t->t+dt)")

        residual = fields.get("residual")
        residual.newSection(residual.VERTICES_FIELD, cs.spaceDim())
        residual.allocate()
        residual.zero()

        fields.copyLayout("residual")

        return (mesh, bc, fields)
Beispiel #19
0
  def _initialize(self, dimension, normalizer):
    """
    Create integrators for each element family.
    """
    from pylith.mpi.Communicator import mpi_comm_world
    comm = mpi_comm_world()

    self.timeStep.initialize(normalizer)

    numTimeSteps = self.timeStep.numTimeSteps()
    totalTime = self.timeStep.totalTime

    from pylith.topology.SolutionFields import SolutionFields
    self.fields = SolutionFields(self.mesh())
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing integrators.")
    for integrator in self.integrators:
      if not self.gravityField is None:
        integrator.gravityField(self.gravityField)
      integrator.initialize(totalTime, numTimeSteps, normalizer)
    ModuleFormulation.integrators(self, self.integrators)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Initializing constraints.")
    for constraint in self.constraints:
      constraint.initialize(totalTime, numTimeSteps, normalizer)
    self._debug.log(resourceUsageString())

    if 0 == comm.rank:
      self._info.log("Setting up solution output.")
    for output in self.output.components():
      output.initialize(self.mesh(), normalizer)
      output.writeInfo()
      output.open(totalTime, numTimeSteps)
    self._debug.log(resourceUsageString())

    # Setup fields
    if 0 == comm.rank:
      self._info.log("Creating solution field.")
    #from pylith.utils.petsc import MemoryLogger
    #memoryLogger = MemoryLogger.singleton()
    #memoryLogger.setDebug(0)
    #memoryLogger.stagePush("Problem")
    self.fields.add("dispIncr(t->t+dt)", "displacement_increment")
    self.fields.add("disp(t)", "displacement")
    self.fields.add("residual", "residual")
    self.fields.solutionName("dispIncr(t->t+dt)")

    lengthScale = normalizer.lengthScale()
    pressureScale = normalizer.pressureScale()

    solution = self.fields.get("dispIncr(t->t+dt)")
    solution.subfieldAdd("displacement", dimension, solution.VECTOR, lengthScale.value)
    solution.subfieldAdd("lagrange_multiplier", dimension, solution.VECTOR, pressureScale.value)
    solution.subfieldsSetup()
    solution.setupSolnChart()
    solution.setupSolnDof(dimension)
    # Loop over integrators to adjust DOF layout
    for integrator in self.integrators:
      integrator.setupSolnDof(solution)
    solution.vectorFieldType(solution.VECTOR)
    solution.scale(lengthScale.value)

    for constraint in self.constraints:
      constraint.setConstraintSizes(solution)
    solution.allocate()
    solution.zeroAll()
    for constraint in self.constraints:
      constraint.setConstraints(solution)
    for integrator in self.integrators:
      integrator.checkConstraints(solution)

    #memoryLogger.stagePop()

    # This also creates a global order.
    solution.createScatter(solution.mesh())

    #memoryLogger.stagePush("Problem")
    dispT = self.fields.get("disp(t)")
    dispT.vectorFieldType(dispT.VECTOR)
    dispT.scale(lengthScale.value)

    residual = self.fields.get("residual")
    residual.vectorFieldType(residual.VECTOR)
    residual.scale(lengthScale.value)

    #memoryLogger.stagePop()
    #memoryLogger.setDebug(0)
    self._debug.log(resourceUsageString())

    return
  def _initialize(self, mesh, integrator):
    """
    Initialize integrator.
    """
    dt = 2.3
    
    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()

    from pyre.units.time import s
    integrator.initialize(totalTime=0.0*s, numTimeSteps=1,
                          normalizer=normalizer)
    integrator.timeStep(dt)

    # Setup fields
    from pylith.topology.SolutionFields import SolutionFields
    fields = SolutionFields(mesh)
    fields.add("residual", "residual")
    fields.add("disp(t)", "displacement")
    fields.add("dispIncr(t->t+dt)", "displacement_increment")
    fields.solutionName("dispIncr(t->t+dt)")

    residual = fields.get("residual")
    spaceDim = mesh.coordsys().spaceDim()
    lengthScale = normalizer.lengthScale()
    residual.subfieldAdd("displacement", spaceDim, residual.VECTOR, lengthScale.value);
    residual.subfieldAdd("lagrange_multiplier", spaceDim, residual.VECTOR);
    
    residual.subfieldsSetup();
    residual.setupSolnChart();
    residual.setupSolnDof(spaceDim);
    residual.allocate();
    residual.zeroAll();
    fields.copyLayout("residual")

    return fields
Beispiel #21
0
class TestSolutionFields(unittest.TestCase):
  """
  Unit testing of SolutionFields object.
  """

  def setUp(self):
    """
    Setup mesh and associated field.
    """
    from spatialdata.geocoords.CSCart import CSCart
    cs = CSCart()
    cs.inventory.spaceDim = 2
    cs._configure()

    from spatialdata.units.Nondimensional import Nondimensional
    normalizer = Nondimensional()
    normalizer._configure()    

    from pylith.meshio.MeshIOAscii import MeshIOAscii
    importer = MeshIOAscii()
    importer.inventory.filename = "data/tri3.mesh"
    importer.inventory.coordsys = cs
    importer._configure()
    self.mesh = importer.read(debug=False, interpolate=False)
    
    self.fields = SolutionFields(self.mesh)
    return


  def test_constructor(self):
    """
    Test constructor.
    """
    return


  def test_solutionName(self):
    """
    Test mesh().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");
    fields.add("field C", "C");
    
    fields.solutionName("field B")
    return


  def test_solution(self):
    """
    Test solution().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");
    fields.add("field C", "C");
    
    fields.solutionName("field B")
    solution = self.fields.solution()
    return


  def test_fieldAdd(self):
    """
    Test fieldAdd().
    """
    fields = self.fields
    fields.add("field A", "A");
    fields.add("field B", "B");

    helper_fieldAdd(fields)
    fieldA = fields.get("field A")
    fieldB = fields.get("field B")
    fieldA.allocate()
    fieldB.allocate()
    fieldA.copy(fieldB)
    return