From c61154f13c28b3e0fafcfd2cee486206a6878a85 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:11:54 -0600 Subject: [PATCH 01/18] FIX: Use arm64 architecture for macOS VSCode C/C++ settings. --- .vscode/c_cpp_properties.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 79e76a9d24..46d12694bd 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -23,7 +23,7 @@ ], "cStandard": "c11", "cppStandard": "c++14", - "intelliSenseMode": "macos-clang-x64" + "intelliSenseMode": "macos-clang-arm64" }, { "name": "linux-gcc", From 2a9d67b3b25e0373c8c4eaac59776816fc16d527 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Wed, 21 Aug 2024 08:08:09 -0600 Subject: [PATCH 02/18] FIX: Fix adding additional command line arguments to gmsh_utils.GenerateApp. --- pylith/meshio/gmsh_utils.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pylith/meshio/gmsh_utils.py b/pylith/meshio/gmsh_utils.py index 98f792f1d5..9ded3b6a06 100644 --- a/pylith/meshio/gmsh_utils.py +++ b/pylith/meshio/gmsh_utils.py @@ -101,7 +101,7 @@ def main(self): """ args = self._parse_command_line() - self.initialize(args.name) + self.initialize(args) if args.geometry: self.create_geometry() if args.mark: @@ -112,13 +112,12 @@ def main(self): self.write(args.filename, args.binary) self.finalize(args.gui) - def initialize(self, name: str): + def initialize(self, args): """Initialize Gmsh. :param name: Name for mesh. """ gmsh.initialize() - gmsh.model.add(name) def finalize(self, gui=False): """Finalize Gmsh. @@ -174,7 +173,7 @@ def _parse_command_line(self): parser.add_argument("--gui", action="store_true", dest="gui", help="Show GUI after running steps.") - GenerateMesh._add_arguments(parser) + self._add_arguments(parser) args = parser.parse_args() if args.write: args.generate = True From 413d1051eb9e3e0b56bdfa766785bbeb5f6e7ca5 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Sat, 11 Jan 2025 09:35:26 -0700 Subject: [PATCH 03/18] Cleanup comment. --- libsrc/pylith/topology/MeshOps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/pylith/topology/MeshOps.cc b/libsrc/pylith/topology/MeshOps.cc index 3da68afd20..bffe829aa8 100644 --- a/libsrc/pylith/topology/MeshOps.cc +++ b/libsrc/pylith/topology/MeshOps.cc @@ -113,7 +113,7 @@ pylith::topology::MeshOps::createSubdomainMesh(const pylith::topology::Mesh& mes throw std::runtime_error(msg.str()); } // if - /* TODO: Add creation of pointSF for submesh */ + /* :TODO: Add creation of pointSF for submesh */ PetscDMLabel dmLabel = NULL; err = DMGetLabel(dmDomain, labelName, &dmLabel);PYLITH_CHECK_ERROR(err);assert(dmLabel); PetscBool hasLabelValue = PETSC_FALSE; From 3bf89f52dcdba88b4611fde300bf5903e7699830 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Wed, 21 Aug 2024 12:28:54 -0600 Subject: [PATCH 04/18] Add RefineInterpolator object for interpolating field to refined mesh. --- libsrc/pylith/Makefile.am | 1 + libsrc/pylith/meshio/OutputObserver.cc | 41 ++++- libsrc/pylith/meshio/OutputObserver.hh | 15 ++ libsrc/pylith/meshio/OutputPhysics.cc | 28 +++- libsrc/pylith/meshio/OutputSubfield.cc | 121 ++++++++----- libsrc/pylith/meshio/OutputSubfield.hh | 23 ++- libsrc/pylith/topology/Distributor.cc | 3 +- libsrc/pylith/topology/Makefile.am | 1 + libsrc/pylith/topology/MeshOps.cc | 52 ++++-- libsrc/pylith/topology/MeshOps.hh | 9 + libsrc/pylith/topology/RefineInterpolator.cc | 168 +++++++++++++++++++ libsrc/pylith/topology/RefineInterpolator.hh | 73 ++++++++ libsrc/pylith/topology/topologyfwd.hh | 1 + modulesrc/meshio/OutputObserver.i | 6 + pylith/meshio/OutputObserver.py | 4 + 15 files changed, 477 insertions(+), 69 deletions(-) create mode 100644 libsrc/pylith/topology/RefineInterpolator.cc create mode 100644 libsrc/pylith/topology/RefineInterpolator.hh diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index d56d79d51f..b790dd9349 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -136,6 +136,7 @@ libpylith_la_SOURCES = \ topology/Distributor.cc \ topology/ReverseCuthillMcKee.cc \ topology/RefineUniform.cc \ + topology/RefineInterpolator.cc \ utils/EventLogger.cc \ utils/PyreComponent.cc \ utils/GenericComponent.cc \ diff --git a/libsrc/pylith/meshio/OutputObserver.cc b/libsrc/pylith/meshio/OutputObserver.cc index 6aeff61cff..25ae96a226 100644 --- a/libsrc/pylith/meshio/OutputObserver.cc +++ b/libsrc/pylith/meshio/OutputObserver.cc @@ -67,6 +67,7 @@ pylith::meshio::_OutputObserver::Events::init(void) { // Constructor pylith::meshio::OutputObserver::OutputObserver(void) : _timeScale(1.0), + _outputMesh(NULL), _writer(NULL), _trigger(NULL), _outputBasisOrder(1) { @@ -95,6 +96,7 @@ pylith::meshio::OutputObserver::deallocate(void) { delete iter->second;iter->second = NULL; } // for _subfields.clear(); + delete _outputMesh;_outputMesh = NULL; _writer = NULL; // :TODO: Use shared pointer _trigger = NULL; // :TODO: Use shared pointer @@ -152,6 +154,26 @@ pylith::meshio::OutputObserver::setOutputBasisOrder(const int value) { } // setOutputBasisOrder +// ------------------------------------------------------------------------------------------------ + +// Set number of refinement levels for output. +void +pylith::meshio::OutputObserver::setRefineLevels(const int value) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("OutputObserver::setRefineLevels(value="<setDM(dmOutput); + } // if + + PYLITH_METHOD_RETURN(_outputMesh); +} // _getOutputMesh + + // ------------------------------------------------------------------------------------------------ // Get output subfield, creating if necessary. pylith::meshio::OutputSubfield* @@ -176,7 +215,7 @@ pylith::meshio::OutputObserver::_getSubfield(const pylith::topology::Field& fiel _OutputObserver::Events::logger.eventBegin(_OutputObserver::Events::getSubfield); if (0 == _subfields.count(name) ) { - _subfields[name] = OutputSubfield::create(field, submesh, name, _outputBasisOrder); + _subfields[name] = OutputSubfield::create(field, submesh, name, _outputBasisOrder, _refineLevels); } // if _OutputObserver::Events::logger.eventEnd(_OutputObserver::Events::getSubfield); diff --git a/libsrc/pylith/meshio/OutputObserver.hh b/libsrc/pylith/meshio/OutputObserver.hh index c7279d3009..0a29fabf80 100644 --- a/libsrc/pylith/meshio/OutputObserver.hh +++ b/libsrc/pylith/meshio/OutputObserver.hh @@ -57,6 +57,12 @@ public: */ void setOutputBasisOrder(const int value); + /** Set number of mesh refinement levels for output. + * + * @param[in] value Number of mesh refinement levels for output. + */ + void setRefineLevels(const int value); + /** Set time scale. * * @param[in] value Time scale for dimensionalizing time. @@ -73,6 +79,13 @@ protected: */ void _setContext(const pylith::topology::Mesh & mesh); + /** Get mesh associated with subfield output. + * + * @param[in] subfield Subfield for output. + * @returns Mesh associated with output. + */ + pylith::topology::Mesh* _getOutputMesh(const pylith::meshio::OutputSubfield& subfield); + /** Get output subfield, creating if necessary. * * @param[in] field Field containing subfields. @@ -97,9 +110,11 @@ protected: PylithReal _timeScale; ///< Time scale for dimentionalizing time. std::map _subfields; ///< Subfields extracted for output. + pylith::topology::Mesh* _outputMesh; ///< Mesh associated with output.ß DataWriter* _writer; ///< Writer for data. OutputTrigger* _trigger; ///< Trigger for deciding how often to write output. int _outputBasisOrder; ///< Basis order for output. + int _refineLevels; ///< Number of mesh refinement levels for output. // NOT IMPLEMENTED //////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/meshio/OutputPhysics.cc b/libsrc/pylith/meshio/OutputPhysics.cc index 597f5a1c44..e28eb7a7cb 100644 --- a/libsrc/pylith/meshio/OutputPhysics.cc +++ b/libsrc/pylith/meshio/OutputPhysics.cc @@ -268,13 +268,11 @@ pylith::meshio::OutputPhysics::_writeInfo(void) { assert(_physics); const pylith::topology::Field* auxiliaryField = _physics->getAuxiliaryField(); const pylith::topology::Field* diagnosticField = _physics->getDiagnosticField(); + const pylith::topology::Mesh& domainMesh = _physics->getPhysicsDomainMesh(); const pylith::string_vector& infoNames = _expandInfoFieldNames(auxiliaryField, diagnosticField); const bool isInfo = true; - const pylith::topology::Mesh& domainMesh = _physics->getPhysicsDomainMesh(); - _open(domainMesh, isInfo); - _openDataStep(0.0, domainMesh); if (auxiliaryField) { auxiliaryField->scatterLocalToOutput(); } PetscVec auxiliaryVector = (auxiliaryField) ? auxiliaryField->getOutputVector() : NULL; @@ -284,20 +282,28 @@ pylith::meshio::OutputPhysics::_writeInfo(void) { const size_t numInfoFields = infoNames.size(); for (size_t i = 0; i < numInfoFields; i++) { + OutputSubfield* subfield = NULL; if (auxiliaryField->hasSubfield(infoNames[i].c_str())) { - OutputSubfield* subfield = _getSubfield(*auxiliaryField, domainMesh, infoNames[i].c_str()); + subfield = _getSubfield(*auxiliaryField, domainMesh, infoNames[i].c_str()); subfield->project(auxiliaryVector); - _appendField(0.0, *subfield); } else if (diagnosticField->hasSubfield(infoNames[i].c_str())) { - OutputSubfield* subfield = _getSubfield(*diagnosticField, domainMesh, infoNames[i].c_str()); + subfield = _getSubfield(*diagnosticField, domainMesh, infoNames[i].c_str()); subfield->project(diagnosticVector); - _appendField(0.0, *subfield); } else { std::ostringstream msg; msg << "Internal Error: Could not find subfield '" << infoNames[i] << "' for info output."; PYLITH_COMPONENT_ERROR(msg.str()); throw std::runtime_error(msg.str()); } // if/else + + if (0 == i) { + // Need output mesh from subfield (which may be refined). + assert(subfield); + pylith::topology::Mesh* outputMesh = _getOutputMesh(*subfield); + _open(*outputMesh, isInfo); + _openDataStep(0.0, *outputMesh); + } // if + OutputObserver::_appendField(0.0, *subfield); } // for _closeDataStep(); @@ -395,8 +401,6 @@ pylith::meshio::OutputPhysics::_writeDataStep(const PylithReal t, const pylith::string_vector& dataNames = _expandDataFieldNames(solution, auxiliaryField, derivedField); - _openDataStep(t, domainMesh); - if (auxiliaryField) { auxiliaryField->scatterLocalToOutput(); } PetscVec auxiliaryVector = (auxiliaryField) ? auxiliaryField->getOutputVector() : NULL; @@ -429,6 +433,12 @@ pylith::meshio::OutputPhysics::_writeDataStep(const PylithReal t, throw std::runtime_error(msg.str()); } // if/else + if (0 == i) { + // Need output mesh from subfield (which may be refined). + assert(subfield); + pylith::topology::Mesh* outputMesh = _getOutputMesh(*subfield); + _openDataStep(t, *outputMesh); + } // if OutputObserver::_appendField(t, *subfield); } // for _closeDataStep(); diff --git a/libsrc/pylith/meshio/OutputSubfield.cc b/libsrc/pylith/meshio/OutputSubfield.cc index bfe71e6185..d9226d3ef1 100644 --- a/libsrc/pylith/meshio/OutputSubfield.cc +++ b/libsrc/pylith/meshio/OutputSubfield.cc @@ -16,6 +16,7 @@ #include "pylith/topology/Mesh.hh" // USES Mesh #include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/topology/RefineInterpolator.hh" // USES RefineInterpolator #include "pylith/fekernels/Solution.hh" // USES Solution::passThruSubfield #include "pylith/utils/error.hh" // USES PYLITH_CHECK_ERROR @@ -75,9 +76,13 @@ pylith::meshio::_OutputSubfield::Events::init(void) { // ------------------------------------------------------------------------------------------------ // Constructor pylith::meshio::OutputSubfield::OutputSubfield(void) : - _dm(NULL), - _vector(NULL), + _subfieldIndex(-1), + _projectDM(PETSC_NULLPTR), + _projectVector(PETSC_NULLPTR), _fn(pylith::fekernels::Solution::passThruSubfield), + _outputDM(PETSC_NULLPTR), + _outputVector(PETSC_NULLPTR), + _interpolator(NULL), _label(NULL), _labelValue(0) { _OutputSubfield::Events::init(); @@ -95,9 +100,13 @@ pylith::meshio::OutputSubfield::~OutputSubfield(void) { // Deallocate PETSc and local data structures. void pylith::meshio::OutputSubfield::deallocate(void) { + delete _interpolator;_interpolator = NULL; + PetscErrorCode err; - err = DMDestroy(&_dm);PYLITH_CHECK_ERROR(err); - err = VecDestroy(&_vector);PYLITH_CHECK_ERROR(err); + err = VecDestroy(&_projectVector);PYLITH_CHECK_ERROR(err); + err = DMDestroy(&_projectDM);PYLITH_CHECK_ERROR(err); + err = VecDestroy(&_outputVector);PYLITH_CHECK_ERROR(err); + err = DMDestroy(&_outputDM);PYLITH_CHECK_ERROR(err); _label = NULL; // Destroyed by DMDestroy() } // deallocate @@ -109,7 +118,8 @@ pylith::meshio::OutputSubfield* pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, const pylith::topology::Mesh& mesh, const char* name, - const int basisOrder) { + const int basisOrder, + const int refineLevels) { PYLITH_METHOD_BEGIN; // _OutputSubfield::Events::logger.eventBegin(_OutputSubfield::Events::create); @@ -124,21 +134,41 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, subfield->_discretization.basisOrder = std::min(basisOrder, info.fe.basisOrder); PetscErrorCode err = PETSC_SUCCESS; - err = DMClone(mesh.getDM(), &subfield->_dm);PYLITH_CHECK_ERROR(err); - err = DMReorderSectionSetDefault(subfield->_dm, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); - err = DMReorderSectionSetType(subfield->_dm, NULL);PYLITH_CHECK_ERROR(err); - err = PetscObjectSetName((PetscObject)subfield->_dm, name);PYLITH_CHECK_ERROR(err); - PetscFE fe = pylith::topology::FieldOps::createFE(subfield->_discretization, subfield->_dm, + // Setup PETSc DM for projection + err = DMClone(mesh.getDM(), &subfield->_projectDM);PYLITH_CHECK_ERROR(err); + err = DMReorderSectionSetDefault(subfield->_projectDM, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); + err = DMReorderSectionSetType(subfield->_projectDM, NULL);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); + + PetscFE fe = pylith::topology::FieldOps::createFE(subfield->_discretization, subfield->_projectDM, info.description.numComponents);assert(fe); err = PetscFESetName(fe, info.description.label.c_str());PYLITH_CHECK_ERROR(err); - err = DMSetField(subfield->_dm, 0, NULL, (PetscObject)fe);PYLITH_CHECK_ERROR(err); - err = DMSetFieldAvoidTensor(subfield->_dm, 0, PETSC_TRUE);PYLITH_CHECK_ERROR(err); + err = DMSetField(subfield->_projectDM, 0, NULL, (PetscObject)fe);PYLITH_CHECK_ERROR(err); + err = DMSetFieldAvoidTensor(subfield->_projectDM, 0, PETSC_TRUE);PYLITH_CHECK_ERROR(err); err = PetscFEDestroy(&fe);PYLITH_CHECK_ERROR(err); - err = DMCreateDS(subfield->_dm);PYLITH_CHECK_ERROR(err); - - err = DMCreateGlobalVector(subfield->_dm, &subfield->_vector);PYLITH_CHECK_ERROR(err); - err = PetscObjectSetName((PetscObject)subfield->_vector, name);PYLITH_CHECK_ERROR(err); + err = DMCreateDS(subfield->_projectDM);PYLITH_CHECK_ERROR(err); + + if (!refineLevels) { + subfield->_outputDM = subfield->_projectDM; + err = PetscObjectReference((PetscObject)subfield->_outputDM);PYLITH_CHECK_ERROR(err); + } else { + delete subfield->_interpolator;subfield->_interpolator = new pylith::topology::RefineInterpolator(); + assert(subfield->_interpolator); + subfield->_interpolator->initialize(subfield->_projectDM, refineLevels); + subfield->_outputDM = subfield->_interpolator->getOutputDM(); + err = PetscObjectReference((PetscObject)subfield->_outputDM);PYLITH_CHECK_ERROR(err); + } + + err = DMCreateGlobalVector(subfield->_projectDM, &subfield->_projectVector);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_projectVector, name);PYLITH_CHECK_ERROR(err); + if (refineLevels) { + err = DMCreateGlobalVector(subfield->_outputDM, &subfield->_outputVector);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_outputVector, name);PYLITH_CHECK_ERROR(err); + } else { + subfield->_outputVector = subfield->_projectVector; + err = PetscObjectReference((PetscObject)subfield->_outputVector);PYLITH_CHECK_ERROR(err); + } // _OutputSubfield::Events::logger.eventEnd(_OutputSubfield::Events::create); PYLITH_METHOD_RETURN(subfield); @@ -160,11 +190,11 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, subfield->_subfieldIndex = info.index; subfield->_description = info.description; - PetscErrorCode err; - err = DMClone(mesh.getDM(), &subfield->_dm);PYLITH_CHECK_ERROR(err); - err = DMReorderSectionSetDefault(subfield->_dm, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); - err = DMReorderSectionSetType(subfield->_dm, NULL);PYLITH_CHECK_ERROR(err); - err = PetscObjectSetName((PetscObject)subfield->_dm, name);PYLITH_CHECK_ERROR(err); + PetscErrorCode err = PETSC_SUCCESS; + err = DMClone(mesh.getDM(), &subfield->_projectDM);PYLITH_CHECK_ERROR(err); + err = DMReorderSectionSetDefault(subfield->_projectDM, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); + err = DMReorderSectionSetType(subfield->_projectDM, NULL);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); pylith::topology::VecVisitorMesh fieldVisitor(field, name); @@ -178,10 +208,15 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, err = PetscSectionSetDof(subfieldSection, point, numDof);PYLITH_CHECK_ERROR(err); offset += numDof; } // for - err = DMSetLocalSection(subfield->_dm, subfieldSection);PYLITH_CHECK_ERROR(err); + err = DMSetLocalSection(subfield->_projectDM, subfieldSection);PYLITH_CHECK_ERROR(err); err = PetscSectionDestroy(&subfieldSection);PYLITH_CHECK_ERROR(err); - err = DMCreateGlobalVector(subfield->_dm, &subfield->_vector);PYLITH_CHECK_ERROR(err); - err = PetscObjectSetName((PetscObject)subfield->_vector, name);PYLITH_CHECK_ERROR(err); + err = DMCreateGlobalVector(subfield->_projectDM, &subfield->_projectVector);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_projectVector, name);PYLITH_CHECK_ERROR(err); + + subfield->_outputDM = subfield->_projectDM; + err = PetscObjectReference((PetscObject) subfield->_outputDM);PYLITH_CHECK_ERROR(err); + subfield->_outputVector = subfield->_projectVector; + err = PetscObjectReference((PetscObject) subfield->_outputVector);PYLITH_CHECK_ERROR(err); _OutputSubfield::Events::logger.eventEnd(_OutputSubfield::Events::createBasisOrder); PYLITH_METHOD_RETURN(subfield); @@ -200,8 +235,8 @@ pylith::meshio::OutputSubfield::setLabel(const char* name, PYLITH_METHOD_END; } // if PetscErrorCode err; - err = DMGetLabel(_dm, name, &_label);PYLITH_CHECK_ERROR(err); - err = DMPlexLabelComplete(_dm, _label); + err = DMGetLabel(_projectDM, name, &_label);PYLITH_CHECK_ERROR(err); + err = DMPlexLabelComplete(_projectDM, _label); _labelValue = value; @@ -229,16 +264,16 @@ pylith::meshio::OutputSubfield::getBasisOrder(void) const { // ------------------------------------------------------------------------------------------------ // Get filtered PETSc global vector. PetscVec -pylith::meshio::OutputSubfield::getVector(void) const { - return _vector; +pylith::meshio::OutputSubfield::getOutputVector(void) const { + return _outputVector; } // ------------------------------------------------------------------------------------------------ // Get PETSc DM for filtered vector. PetscDM -pylith::meshio::OutputSubfield::getDM(void) const { - return _dm; +pylith::meshio::OutputSubfield::getOutputDM(void) const { + return _outputDM; } @@ -249,13 +284,17 @@ pylith::meshio::OutputSubfield::project(const PetscVec& fieldVector) { PYLITH_METHOD_BEGIN; _OutputSubfield::Events::logger.eventBegin(_OutputSubfield::Events::project); assert(fieldVector); - assert(_vector); + assert(_projectVector); + assert(_outputVector); PetscErrorCode err; - const PetscReal t = PetscReal(_subfieldIndex) + 0.01; // :KLUDGE: Easiest way to get subfield to extract into fn. + const PetscReal t = PetscReal(_subfieldIndex) + 0.01; // :KLUDGE: Easiest way to get subfield to extract into fn - err = DMProjectField(_dm, t, fieldVector, &_fn, INSERT_VALUES, _vector);PYLITH_CHECK_ERROR(err); - err = VecScale(_vector, _description.scale);PYLITH_CHECK_ERROR(err); + err = DMProjectField(_projectDM, t, fieldVector, &_fn, INSERT_VALUES, _projectVector);PYLITH_CHECK_ERROR(err); + if (_interpolator) { + _interpolator->interpolate(&_outputVector, _projectVector); + } // if + err = VecScale(_outputVector, _description.scale);PYLITH_CHECK_ERROR(err); _OutputSubfield::Events::logger.eventEnd(_OutputSubfield::Events::project); PYLITH_METHOD_END; @@ -269,14 +308,18 @@ pylith::meshio::OutputSubfield::projectWithLabel(const PetscVec& fieldVector) { PYLITH_METHOD_BEGIN; _OutputSubfield::Events::logger.eventBegin(_OutputSubfield::Events::projectWithLabel); assert(fieldVector); - assert(_vector); + assert(_projectVector); + assert(_outputVector); assert(_label); PetscErrorCode err; - const PetscReal t = PetscReal(_subfieldIndex) + 0.01; // :KLUDGE: Easiest way to get subfield to extract into fn. + const PetscReal t = PetscReal(_subfieldIndex) + 0.01; // :KLUDGE: Easiest way to get subfield to extract into fn - err = DMProjectFieldLabel(_dm, t, _label, 1, &_labelValue, PETSC_DETERMINE, NULL, fieldVector, &_fn, INSERT_VALUES, _vector);PYLITH_CHECK_ERROR(err); - err = VecScale(_vector, _description.scale);PYLITH_CHECK_ERROR(err); + err = DMProjectFieldLabel(_projectDM, t, _label, 1, &_labelValue, PETSC_DETERMINE, NULL, fieldVector, &_fn, INSERT_VALUES, _projectVector);PYLITH_CHECK_ERROR(err); + if (_interpolator) { + _interpolator->interpolate(&_outputVector, _projectVector); + } // if + err = VecScale(_outputVector, _description.scale);PYLITH_CHECK_ERROR(err); _OutputSubfield::Events::logger.eventEnd(_OutputSubfield::Events::projectWithLabel); PYLITH_METHOD_END; @@ -297,7 +340,7 @@ pylith::meshio::OutputSubfield::extractSubfield(const pylith::topology::Field& f err = PetscSectionGetField(field.getLocalSection(), subfieldIndex, &subfieldSection);PYLITH_CHECK_ERROR(err); err = PetscSectionGetStorageSize(subfieldSection, &storageSize);PYLITH_CHECK_ERROR(err); - PetscVec subfieldVector = this->getVector(); + PetscVec subfieldVector = this->getOutputVector(); PetscInt subfieldSize = 0; err = VecGetLocalSize(subfieldVector, &subfieldSize);PYLITH_CHECK_ERROR(err); assert(subfieldSize == storageSize); diff --git a/libsrc/pylith/meshio/OutputSubfield.hh b/libsrc/pylith/meshio/OutputSubfield.hh index fe6c012f7f..d6e55296cf 100644 --- a/libsrc/pylith/meshio/OutputSubfield.hh +++ b/libsrc/pylith/meshio/OutputSubfield.hh @@ -15,7 +15,7 @@ #include "pylith/topology/FieldBase.hh" // HASA Description, Discretization -#include "pylith/topology/topologyfwd.hh" // USES Field +#include "pylith/topology/topologyfwd.hh" // USES Field, RefineInterpolator #include "pylith/utils/petscfwd.h" // HASA PetscVec class pylith::meshio::OutputSubfield : public pylith::utils::GenericComponent { @@ -30,12 +30,14 @@ public: * @param[in] mesh Mesh for subfield. * @param[in] name Name of subfield that will be extracted. * @param[in] basisOrder Basis order for subfield. + * @param[in] refineLevels Number of levels of mesh refinement. */ static OutputSubfield* create(const pylith::topology::Field& field, const pylith::topology::Mesh& mesh, const char* name, - const int basisOrder); + const int basisOrder, + const int refineLevels); /** Create OutputSubfield from Field. * @@ -76,17 +78,17 @@ public: */ int getBasisOrder(void) const; - /** Get PETSc global vector for projected subfield. + /** Get PETSc global vector for output subfield. * * @returns PETSc global vector. */ - PetscVec getVector(void) const; + PetscVec getOutputVector(void) const; - /** Get PETSc DM for projected subfield. + /** Get PETSc DM for output subfield. * * @returns PETSc DM. */ - PetscDM getDM(void) const; + PetscDM getOutputDM(void) const; /** Project PETSc vector to subfield. * @@ -121,10 +123,13 @@ protected: pylith::topology::FieldBase::Description _description; ///< Description of subfield. pylith::topology::FieldBase::Discretization _discretization; ///< Discretization of subfield. - PetscDM _dm; ///< PETSc DM for subfield. - PetscVec _vector; ///< PETSc global vector for subfield. - PetscPointFunc _fn; ///< PETSc point function for projection. PetscInt _subfieldIndex; ///< Index of subfield in fields. + PetscDM _projectDM; ///< PETSc global vector for subfield projection. + PetscVec _projectVector; ///< PETSc global vector for subfield projection. + PetscPointFunc _fn; ///< PETSc point function for projection. + PetscDM _outputDM; ///< PETSc DM for subfield output. + PetscVec _outputVector; ///< PETSc global vector for subfield output. + pylith::topology::RefineInterpolator* _interpolator; ///< Interpolator for refined output. PetscDMLabel _label; ///< PETSc label associated with subfield. PetscInt _labelValue; ///< Value of PETSc label associated with subfield. diff --git a/libsrc/pylith/topology/Distributor.cc b/libsrc/pylith/topology/Distributor.cc index bf3f6e933d..3f7b7773d0 100644 --- a/libsrc/pylith/topology/Distributor.cc +++ b/libsrc/pylith/topology/Distributor.cc @@ -171,8 +171,9 @@ pylith::topology::Distributor::write(meshio::DataWriter* const writer, partitionField.scatterLocalToOutput(); const int basisOrder = 0; + const int refineLevels = 0; pylith::meshio::OutputSubfield* outputField = - pylith::meshio::OutputSubfield::create(partitionField, mesh, "partition", basisOrder); + pylith::meshio::OutputSubfield::create(partitionField, mesh, "partition", basisOrder, refineLevels); outputField->project(partitionField.getOutputVector()); const PylithScalar t = 0.0; diff --git a/libsrc/pylith/topology/Makefile.am b/libsrc/pylith/topology/Makefile.am index 0143890fdb..566e69c864 100644 --- a/libsrc/pylith/topology/Makefile.am +++ b/libsrc/pylith/topology/Makefile.am @@ -31,6 +31,7 @@ subpkginclude_HEADERS = \ VisitorSubmesh.hh \ VisitorSubmesh.icc \ RefineUniform.hh \ + RefineInterpolator.hh \ topologyfwd.hh diff --git a/libsrc/pylith/topology/MeshOps.cc b/libsrc/pylith/topology/MeshOps.cc index bffe829aa8..e9180b54c9 100644 --- a/libsrc/pylith/topology/MeshOps.cc +++ b/libsrc/pylith/topology/MeshOps.cc @@ -146,9 +146,6 @@ pylith::topology::MeshOps::createSubdomainMesh(const pylith::topology::Mesh& mes throw std::runtime_error(msg.str()); } // if - // Set name - err = PetscObjectSetName((PetscObject) dmSubdomain, descriptiveLabel);PYLITH_CHECK_ERROR(err); - // Set lengthscale PylithScalar lengthScale; err = DMPlexGetScale(dmDomain, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); @@ -156,7 +153,7 @@ pylith::topology::MeshOps::createSubdomainMesh(const pylith::topology::Mesh& mes pylith::topology::Mesh* submesh = new pylith::topology::Mesh(true);assert(submesh); submesh->setCoordSys(mesh.getCoordSys()); - submesh->setDM(dmSubdomain); + submesh->setDM(dmSubdomain, descriptiveLabel); _MeshOps::Events::logger.eventEnd(_MeshOps::Events::createSubdomainMesh); PYLITH_METHOD_RETURN(submesh); @@ -223,18 +220,15 @@ pylith::topology::MeshOps::createLowerDimMesh(const pylith::topology::Mesh& mesh throw std::runtime_error(msg.str()); } // if - // Set name - std::string meshLabel = "subdomain_" + std::string(labelName); - err = PetscObjectSetName((PetscObject) dmSubmesh, meshLabel.c_str());PYLITH_CHECK_ERROR(err); - // Set lengthscale PylithScalar lengthScale; err = DMPlexGetScale(dmDomain, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); err = DMPlexSetScale(dmSubmesh, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); - pylith::topology::Mesh* submesh = new pylith::topology::Mesh(true);assert(submesh); submesh->setCoordSys(mesh.getCoordSys()); - submesh->setDM(dmSubmesh); + + std::string meshLabel = "subdomain_" + std::string(labelName); + submesh->setDM(dmSubmesh, meshLabel.c_str()); // Check topology MeshOps::checkTopology(*submesh); @@ -349,6 +343,44 @@ pylith::topology::MeshOps::nondimensionalize(Mesh* const mesh, } // nondimensionalize +// --------------------------------------------------------------------------------------------------------------------- +// Strip out "ghost" cells hanging off mesh +PetscDM +pylith::topology::MeshOps::removeHangingCells(const PetscDM& dmMesh) { + PYLITH_METHOD_BEGIN; + + PetscErrorCode err = PETSC_SUCCESS; + PetscDM dmClean = PETSC_NULLPTR; + + MPI_Comm comm = PetscObjectComm((PetscObject) dmMesh); + pylith::topology::Stratum cells(dmMesh, pylith::topology::Stratum::HEIGHT, 0); + DMPolytopeType cellType; + err = DMPlexGetCellType(dmMesh, cells.begin(), &cellType);PYLITH_CHECK_ERROR(err); + if (DMPolytopeTypeGetDim(cellType) < 0) { + // Hanging cells have dim == -1 + + // Create label over cells 1 dimension lower + PetscDMLabel labelInclude = PETSC_NULLPTR; + const PetscInt labelValue = 1; + err = DMLabelCreate(comm, "no_hanging_cells", &labelInclude);PYLITH_CHECK_ERROR(err); + pylith::topology::Stratum faces(dmMesh, pylith::topology::Stratum::HEIGHT, 1); + for (PetscInt face = faces.begin(); face < faces.end(); ++face) { + err = DMLabelSetValue(labelInclude, face, labelValue);PYLITH_CHECK_ERROR(err); + } // for + + err = DMPlexFilter(dmMesh, labelInclude, labelValue, PETSC_FALSE, PETSC_FALSE, PETSC_NULLPTR, &dmClean);PYLITH_CHECK_ERROR(err); + } else { + dmClean = dmMesh; + err = PetscObjectReference((PetscObject) dmClean); + } // if/else + PetscReal lengthScale = 1.0; + err = DMPlexGetScale(dmMesh, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); + err = DMPlexSetScale(dmClean, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); + + PYLITH_METHOD_RETURN(dmClean); +} + + // --------------------------------------------------------------------------------------------------------------------- // Check topology of mesh. void diff --git a/libsrc/pylith/topology/MeshOps.hh b/libsrc/pylith/topology/MeshOps.hh index dbe17a507c..b04e5f736c 100644 --- a/libsrc/pylith/topology/MeshOps.hh +++ b/libsrc/pylith/topology/MeshOps.hh @@ -66,6 +66,15 @@ public: const PylithReal lengthScale, MPI_Comm comm); + /** Remove cells hanging off mesh. + * + * @param[in] dmMesh PETSc DM to clean. + * + * @returns PETSc DM without hanging cells. + */ + static + PetscDM removeHangingCells(const PetscDM& dmMesh); + /** Nondimensionalize the finite-element mesh. * * @param[in] mesh Finite-element mesh. diff --git a/libsrc/pylith/topology/RefineInterpolator.cc b/libsrc/pylith/topology/RefineInterpolator.cc new file mode 100644 index 0000000000..043d38184b --- /dev/null +++ b/libsrc/pylith/topology/RefineInterpolator.cc @@ -0,0 +1,168 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2024, University of California, Davis and the PyLith Development Team. +// All rights reserved. +// +// See https://mit-license.org/ and LICENSE.md and for license information. +// ================================================================================================= + +#include + +#include "pylith/topology/RefineInterpolator.hh" // implementation of class methods + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps +#include "pylith/topology/Field.hh" // USES Field + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/EventLogger.hh" // USES EventLogger + +#include // USES assert() + +// ------------------------------------------------------------------------------------------------ +namespace pylith { + namespace topology { + class _RefineInterpolator { +public: + + class Events { +public: + + static + void init(void); + + static pylith::utils::EventLogger logger; + static PylithInt initialize; + static PylithInt interpolate; + }; + + }; // _RefineInterpolator + } // topology +} // pylith + +pylith::utils::EventLogger pylith::topology::_RefineInterpolator::Events::logger; +PylithInt pylith::topology::_RefineInterpolator::Events::initialize; +PylithInt pylith::topology::_RefineInterpolator::Events::interpolate; + +// ------------------------------------------------------------------------------------------------ +void +pylith::topology::_RefineInterpolator::Events::init(void) { + logger.setClassName("RefineInterpolator"); + logger.initialize(); + initialize = logger.registerEvent("PL:RefineInterpolator:initialize"); + interpolate = logger.registerEvent("PL:RefineInterpolator:interpolate"); +} + + +// ------------------------------------------------------------------------------------------------ +// Constructor +pylith::topology::RefineInterpolator::RefineInterpolator(void) { + _RefineInterpolator::Events::init(); +} + + +// ------------------------------------------------------------------------------------------------ +// Destructor +pylith::topology::RefineInterpolator::~RefineInterpolator(void) { + deallocate(); +} + + +// ------------------------------------------------------------------------------------------------ +// Deallocate data structures. +void +pylith::topology::RefineInterpolator::deallocate(void) { + for (auto level : _levels) { + DMDestroy(&level.dm); + MatDestroy(&level.interpolateMatrix); + VecDestroy(&level.vector); + } // for + _levels.resize(0); +} // deallocate + + +// ------------------------------------------------------------------------------------------------ +// Get PETSc DM for output (finest level) +PetscDM +pylith::topology::RefineInterpolator::getOutputDM(void) { + return (_levels.size() > 0) ? _levels[_levels.size()-1].dm : PETSC_NULLPTR; +} + + +// ------------------------------------------------------------------------------------------------ +// Initialize interpolation to refined mesh. +void +pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, + const int refineLevels) { + PYLITH_METHOD_BEGIN; + _RefineInterpolator::Events::logger.eventBegin(_RefineInterpolator::Events::initialize); + + _levels.resize(refineLevels); + PetscErrorCode err = PETSC_SUCCESS; + + PetscDM dmStart = pylith::topology::MeshOps::removeHangingCells(dmMesh); + err = DMCopyDisc(dmMesh, dmStart);PYLITH_CHECK_ERROR(err); + + PetscDM dmPrev = dmStart; + PetscReal lengthScale = 1.0; + for (size_t iLevel = 0; iLevel < _levels.size(); ++iLevel) { + _levels[iLevel].dm = PETSC_NULLPTR; + _levels[iLevel].interpolateMatrix = PETSC_NULLPTR; + _levels[iLevel].vector = PETSC_NULLPTR; + + err = DMPlexSetRefinementUniform(dmPrev, PETSC_TRUE);PYLITH_CHECK_ERROR(err); + err = DMRefine(dmPrev, PetscObjectComm((PetscObject) dmMesh), &_levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + err = DMSetCoarseDM(_levels[iLevel].dm, dmPrev);PYLITH_CHECK_ERROR(err); + err = DMPlexGetScale(dmPrev, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); + err = DMPlexSetScale(_levels[iLevel].dm, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); + +#if 0 // needed for higher order coordinates (not needed for affine coordinates) + PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); + PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); + PetscCall(DMGetCoordinateDM(odm, &cdm)); + PetscCall(DMGetCoordinateDM(rdm, &rcdm)); + PetscCall(DMGetCoordinatesLocal(odm, &cl)); + PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); + +#endif + err = DMCopyDisc(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + err = DMGetGlobalVector(_levels[iLevel].dm, &_levels[iLevel].vector);PYLITH_CHECK_ERROR(err); + err = PetscObjectReference((PetscObject) _levels[iLevel].vector);PYLITH_CHECK_ERROR(err); + + err = DMCreateInterpolation(dmPrev, _levels[iLevel].dm, &_levels[iLevel].interpolateMatrix, NULL);PYLITH_CHECK_ERROR(err); + + dmPrev = _levels[iLevel].dm; + } // for + + _RefineInterpolator::Events::logger.eventEnd(_RefineInterpolator::Events::initialize); + PYLITH_METHOD_END; +} // initialize + + +// ------------------------------------------------------------------------------------------------ +// Interpolate field to fine mesh level. +void +pylith::topology::RefineInterpolator::interpolate(const PetscVec* vectorOut, + const PetscVec& vectorIn) { + PYLITH_METHOD_BEGIN; + _RefineInterpolator::Events::logger.eventBegin(_RefineInterpolator::Events::interpolate); + assert(vectorOut); + + // Should be global vectors + + PetscVec vectorPrev = vectorIn; + PetscErrorCode err = PETSC_SUCCESS; + for (auto level : _levels) { + err = MatMult(level.interpolateMatrix, vectorPrev, level.vector);PYLITH_CHECK_ERROR(err); + vectorPrev = level.vector; + } // for + err = VecCopy(vectorPrev, *vectorOut); + + _RefineInterpolator::Events::logger.eventEnd(_RefineInterpolator::Events::interpolate); + PYLITH_METHOD_END; +} // interpolate + + +// End of file diff --git a/libsrc/pylith/topology/RefineInterpolator.hh b/libsrc/pylith/topology/RefineInterpolator.hh new file mode 100644 index 0000000000..5c03fdd3f0 --- /dev/null +++ b/libsrc/pylith/topology/RefineInterpolator.hh @@ -0,0 +1,73 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2024, University of California, Davis and the PyLith Development Team. +// All rights reserved. +// +// See https://mit-license.org/ and LICENSE.md and for license information. +// ================================================================================================= +#pragma once + +#include "pylith/topology/topologyfwd.hh" // forward declarations +#include "pylith/utils/petscfwd.h" // USES PetscDM + +#include // HASA std::vector + +/// @brief Interpolate fields to uniformly refined mesh. +class pylith::topology::RefineInterpolator { + friend class TestRefineUniform; // unit testing + + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + RefineInterpolator(void); + + /// Destructor + ~RefineInterpolator(void); + + /// Deallocate data structures. + void deallocate(void); + + /** Get PETSc DM for output (finest level) + * + */ + PetscDM getOutputDM(void); + + /** Initialize interpolation to refined mesh. + * + * @param[in] dmMesh PETSc DM for starting point of refinement. + * @param[in] refineLevels Number of levels of mesh refinement. + */ + void initialize(const PetscDM& dmMesh, + const int refineLevels); + + /** Interpolate field to fine mesh level. + * + * @param[out] vectorOut PETSc Vec with interpolated field. + * @param[in] vectorIn PETSc Vec with field to interpolate. + */ + void interpolate(const PetscVec* vectorOut, + const PetscVec& vectorIn); + + // PRIvATE MEMBERS //////////////////////////////////////////////////////////////////////////// +private: + + struct Level { + PetscDM dm; + PetscMat interpolateMatrix; + PetscVec vector; + }; + + std::vector _levels; ///< Information at each refinement level. + + // NOT IMPLEMENTED //////////////////////////////////////////////////////////////////////////// +private: + + RefineInterpolator(const RefineInterpolator&); ///< Not implemented + const RefineInterpolator& operator=(const RefineInterpolator&); ///< Not implemented + +}; // RefineInterpolator + +// End of file diff --git a/libsrc/pylith/topology/topologyfwd.hh b/libsrc/pylith/topology/topologyfwd.hh index d0eac0df64..6d6b2e18c0 100644 --- a/libsrc/pylith/topology/topologyfwd.hh +++ b/libsrc/pylith/topology/topologyfwd.hh @@ -29,6 +29,7 @@ namespace pylith { class FieldFactory; class FieldOps; class FieldQuery; + class RefineInterpolator; class MatVisitorMesh; class MatVisitorSubmesh; diff --git a/modulesrc/meshio/OutputObserver.i b/modulesrc/meshio/OutputObserver.i index 0d4483ef62..c3b65855da 100644 --- a/modulesrc/meshio/OutputObserver.i +++ b/modulesrc/meshio/OutputObserver.i @@ -54,6 +54,12 @@ public: */ void setOutputBasisOrder(const int value); + /** Set number of mesh refinement levels for output. + * + * @param[in] value Number of mesh refinement levels for output. + */ + void setRefineLevels(const int value); + /** Set time scale. * * @param[in] value Time scale for dimensionalizing time. diff --git a/pylith/meshio/OutputObserver.py b/pylith/meshio/OutputObserver.py index 1e9995569f..29769acec7 100644 --- a/pylith/meshio/OutputObserver.py +++ b/pylith/meshio/OutputObserver.py @@ -30,6 +30,9 @@ class OutputObserver(PetscComponent, ModuleOutputObserver): outputBasisOrder = pythia.pyre.inventory.int("output_basis_order", default=1, validator=pythia.pyre.inventory.choice([0,1])) outputBasisOrder.meta['tip'] = "Basis order for output." + refineLevels = pythia.pyre.inventory.int("refine_levels", default=0, validator=pythia.pyre.inventory.greaterEqual(0)) + refineLevels.meta['tip'] = "Number of mesh refinement levels for output." + def __init__(self, name="outputobserver"): """Constructor. """ @@ -50,6 +53,7 @@ def preinitialize(self, problem): else: outputBasisOrder = self.outputBasisOrder ModuleOutputObserver.setOutputBasisOrder(self, outputBasisOrder) + ModuleOutputObserver.setRefineLevels(self, self.refineLevels) self.writer.preinitialize() ModuleOutputObserver.setWriter(self, self.writer) From 27a97f7624a61b873db110296bc3b4eece43afd2 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Thu, 22 Aug 2024 21:43:15 -0600 Subject: [PATCH 05/18] Updates for changes to OutputSubfield API (getDM -> getOutputDM; getVector -> getOutputVector). --- libsrc/pylith/meshio/DataWriterHDF5.cc | 9 ++++----- libsrc/pylith/meshio/DataWriterHDF5Ext.cc | 10 +++++----- libsrc/pylith/meshio/DataWriterVTK.cc | 8 ++++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/libsrc/pylith/meshio/DataWriterHDF5.cc b/libsrc/pylith/meshio/DataWriterHDF5.cc index fe3830072c..b331620fd7 100644 --- a/libsrc/pylith/meshio/DataWriterHDF5.cc +++ b/libsrc/pylith/meshio/DataWriterHDF5.cc @@ -178,7 +178,7 @@ pylith::meshio::DataWriterHDF5::writeVertexField(const PylithScalar t, const int istep = _timesteps[name]; // Add time stamp to "/time" if necessary. MPI_Comm comm; - err = PetscObjectGetComm((PetscObject)subfield.getDM(), &comm);PYLITH_CHECK_ERROR(err); + err = PetscObjectGetComm((PetscObject)subfield.getOutputDM(), &comm);PYLITH_CHECK_ERROR(err); PetscMPIInt commRank; err = MPI_Comm_rank(comm, &commRank);PYLITH_CHECK_ERROR(err); if (_tstampIndex == istep) { @@ -189,7 +189,7 @@ pylith::meshio::DataWriterHDF5::writeVertexField(const PylithScalar t, err = PetscViewerHDF5PushTimestepping(_viewer);PYLITH_CHECK_ERROR(err); err = PetscViewerHDF5SetTimestep(_viewer, istep);PYLITH_CHECK_ERROR(err); - PetscVec vector = subfield.getVector();assert(vector); + PetscVec vector = subfield.getOutputVector();assert(vector); DataWriter::_writeVec(vector, _viewer);PYLITH_CHECK_ERROR(err); err = PetscViewerHDF5PopTimestepping(_viewer);PYLITH_CHECK_ERROR(err); err = PetscViewerHDF5PopGroup(_viewer);PYLITH_CHECK_ERROR(err); @@ -240,8 +240,7 @@ pylith::meshio::DataWriterHDF5::writeCellField(const PylithScalar t, } const int istep = _timesteps[name]; // Add time stamp to "/time" if necessary. - MPI_Comm comm; - err = PetscObjectGetComm((PetscObject)subfield.getDM(), &comm);PYLITH_CHECK_ERROR(err); + MPI_Comm comm = PetscObjectComm((PetscObject)subfield.getOutputDM()); PetscMPIInt commRank; err = MPI_Comm_rank(comm, &commRank);PYLITH_CHECK_ERROR(err); if (_tstampIndex == istep) { @@ -252,7 +251,7 @@ pylith::meshio::DataWriterHDF5::writeCellField(const PylithScalar t, err = PetscViewerHDF5PushTimestepping(_viewer);PYLITH_CHECK_ERROR(err); err = PetscViewerHDF5SetTimestep(_viewer, istep);PYLITH_CHECK_ERROR(err); - PetscVec vector = subfield.getVector();assert(vector); + PetscVec vector = subfield.getOutputVector();assert(vector); DataWriter::_writeVec(vector, _viewer); err = PetscViewerHDF5PopTimestepping(_viewer);PYLITH_CHECK_ERROR(err); err = PetscViewerHDF5PopGroup(_viewer);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/meshio/DataWriterHDF5Ext.cc b/libsrc/pylith/meshio/DataWriterHDF5Ext.cc index f9dbe3854f..e8d1863cf9 100644 --- a/libsrc/pylith/meshio/DataWriterHDF5Ext.cc +++ b/libsrc/pylith/meshio/DataWriterHDF5Ext.cc @@ -148,7 +148,7 @@ pylith::meshio::DataWriterHDF5Ext::writeVertexField(const PylithScalar t, const char* name = subfield.getDescription().label.c_str(); try { - PetscDM dmMesh = subfield.getDM();assert(dmMesh); + PetscDM dmMesh = subfield.getOutputDM();assert(dmMesh); PetscErrorCode err; MPI_Comm comm; @@ -176,7 +176,7 @@ pylith::meshio::DataWriterHDF5Ext::writeVertexField(const PylithScalar t, } // else assert(binaryViewer); - PetscVec vector = subfield.getVector();assert(vector); + PetscVec vector = subfield.getOutputVector();assert(vector); DataWriter::_writeVec(vector, binaryViewer); ExternalDataset& datasetInfo = _datasets[name]; @@ -288,7 +288,7 @@ pylith::meshio::DataWriterHDF5Ext::writeCellField(const PylithScalar t, try { PetscErrorCode err; - PetscDM dmMesh = subfield.getDM();assert(dmMesh); + PetscDM dmMesh = subfield.getOutputDM();assert(dmMesh); MPI_Comm comm; PetscMPIInt commRank; err = PetscObjectGetComm((PetscObject) dmMesh, &comm);PYLITH_CHECK_ERROR(err); @@ -314,7 +314,7 @@ pylith::meshio::DataWriterHDF5Ext::writeCellField(const PylithScalar t, } // else assert(binaryViewer); - PetscVec vector = subfield.getVector();assert(vector); + PetscVec vector = subfield.getOutputVector();assert(vector); DataWriter::_writeVec(vector, binaryViewer); ExternalDataset& datasetInfo = _datasets[name]; @@ -333,7 +333,7 @@ pylith::meshio::DataWriterHDF5Ext::writeCellField(const PylithScalar t, if (createdExternalDataset) { // Get cell information PetscSection section = NULL; - err = DMGetLocalSection(subfield.getDM(), §ion);assert(section); + err = DMGetLocalSection(subfield.getOutputDM(), §ion);assert(section); PetscInt dof = 0, numLocalCells = 0, numCells, cellHeight, cStart, cEnd; PetscIS globalCellNumbers; diff --git a/libsrc/pylith/meshio/DataWriterVTK.cc b/libsrc/pylith/meshio/DataWriterVTK.cc index 651749c220..0eee256e75 100644 --- a/libsrc/pylith/meshio/DataWriterVTK.cc +++ b/libsrc/pylith/meshio/DataWriterVTK.cc @@ -212,8 +212,8 @@ pylith::meshio::DataWriterVTK::writeVertexField(const PylithScalar t, PetscViewerVTKFieldType ft = subfield.getDescription().vectorFieldType == pylith::topology::FieldBase::VECTOR ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; err = PetscViewerVTKAddField(_viewer, (PetscObject)_dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, - PETSC_TRUE, (PetscObject)subfield.getVector());PYLITH_CHECK_ERROR(err); - err = PetscObjectReference((PetscObject) subfield.getVector());PYLITH_CHECK_ERROR(err); // Viewer destroys Vec + PETSC_TRUE, (PetscObject)subfield.getOutputVector());PYLITH_CHECK_ERROR(err); + err = PetscObjectReference((PetscObject) subfield.getOutputVector());PYLITH_CHECK_ERROR(err); // Viewer destroys Vec _wroteVertexHeader = true; @@ -234,8 +234,8 @@ pylith::meshio::DataWriterVTK::writeCellField(const PylithScalar t, PetscViewerVTKFieldType ft = subfield.getDescription().vectorFieldType == pylith::topology::FieldBase::VECTOR ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; err = PetscViewerVTKAddField(_viewer, (PetscObject)_dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, - PETSC_TRUE, (PetscObject)subfield.getVector());PYLITH_CHECK_ERROR(err); - err = PetscObjectReference((PetscObject) subfield.getVector());PYLITH_CHECK_ERROR(err); // Viewer destroys Vec + PETSC_TRUE, (PetscObject)subfield.getOutputVector());PYLITH_CHECK_ERROR(err); + err = PetscObjectReference((PetscObject) subfield.getOutputVector());PYLITH_CHECK_ERROR(err); // Viewer destroys Vec _wroteCellHeader = true; From 5a4f35195d268556c31c8ec9e486fce22261422c Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Thu, 22 Aug 2024 21:44:11 -0600 Subject: [PATCH 06/18] Use empty default argument for Mesh::setDM() instead of "domain". --- libsrc/pylith/meshio/MeshBuilder.cc | 2 +- libsrc/pylith/meshio/MeshIOPetsc.cc | 2 +- libsrc/pylith/topology/Distributor.cc | 2 +- libsrc/pylith/topology/Mesh.cc | 6 ++++-- libsrc/pylith/topology/Mesh.hh | 2 +- libsrc/pylith/topology/RefineUniform.cc | 2 +- libsrc/pylith/topology/ReverseCuthillMcKee.cc | 2 +- libsrc/pylith/topology/Stratum.icc | 6 +++--- modulesrc/topology/Mesh.i | 14 -------------- tests/libtests/meshio/TestMeshIO.cc | 2 +- tests/libtests/topology/TestReverseCuthillMcKee.cc | 2 +- 11 files changed, 15 insertions(+), 27 deletions(-) diff --git a/libsrc/pylith/meshio/MeshBuilder.cc b/libsrc/pylith/meshio/MeshBuilder.cc index dcd26039b9..404e9dd901 100644 --- a/libsrc/pylith/meshio/MeshBuilder.cc +++ b/libsrc/pylith/meshio/MeshBuilder.cc @@ -127,7 +127,7 @@ pylith::meshio::MeshBuilder::buildMesh(topology::Mesh* mesh, err = DMPlexInvertCell(ct, (int *) &cells[coff]);PYLITH_CHECK_ERROR(err); } err = DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, &cells[0], spaceDim, &(*coordinates)[0], &dmMesh);PYLITH_CHECK_ERROR(err); - mesh->setDM(dmMesh); + mesh->setDM(dmMesh, "domain"); _MeshBuilder::Events::logger.eventEnd(_MeshBuilder::Events::buildMesh); PYLITH_METHOD_END; diff --git a/libsrc/pylith/meshio/MeshIOPetsc.cc b/libsrc/pylith/meshio/MeshIOPetsc.cc index d6c38058ad..f8268ba9cd 100644 --- a/libsrc/pylith/meshio/MeshIOPetsc.cc +++ b/libsrc/pylith/meshio/MeshIOPetsc.cc @@ -148,7 +148,7 @@ pylith::meshio::MeshIOPetsc::_read(void) { _MeshIOPetsc::fixMaterialLabel(&dmMesh); _MeshIOPetsc::fixBoundaryLabels(&dmMesh); - _mesh->setDM(dmMesh); + _mesh->setDM(dmMesh, "domain"); } catch (...) { DMDestroy(&dmMesh); throw; diff --git a/libsrc/pylith/topology/Distributor.cc b/libsrc/pylith/topology/Distributor.cc index 3f7b7773d0..1a67437848 100644 --- a/libsrc/pylith/topology/Distributor.cc +++ b/libsrc/pylith/topology/Distributor.cc @@ -109,7 +109,7 @@ pylith::topology::Distributor::distribute(pylith::topology::Mesh* const newMesh, err = DMPlexDistributeSetDefault(dmNew, PETSC_FALSE);PYLITH_CHECK_ERROR(err); err = DMPlexReorderCohesiveSupports(dmNew);PYLITH_CHECK_ERROR(err); err = DMViewFromOptions(dmNew, NULL, "-pylith_dist_dm_view");PYLITH_CHECK_ERROR(err); - newMesh->setDM(dmNew); + newMesh->setDM(dmNew, "domain"); PYLITH_METHOD_END; } // distribute diff --git a/libsrc/pylith/topology/Mesh.cc b/libsrc/pylith/topology/Mesh.cc index cd64a6e38b..d417be8a3a 100644 --- a/libsrc/pylith/topology/Mesh.cc +++ b/libsrc/pylith/topology/Mesh.cc @@ -108,10 +108,12 @@ pylith::topology::Mesh::setDM(PetscDM dm, const char* label) { PYLITH_METHOD_BEGIN; - PetscErrorCode err; + PetscErrorCode err = PETSC_SUCCESS; err = DMDestroy(&_dm);PYLITH_CHECK_ERROR(err); _dm = dm; - err = PetscObjectSetName((PetscObject) _dm, label);PYLITH_CHECK_ERROR(err); + if (label) { + err = PetscObjectSetName((PetscObject) _dm, label);PYLITH_CHECK_ERROR(err); + } // if PYLITH_METHOD_END; } diff --git a/libsrc/pylith/topology/Mesh.hh b/libsrc/pylith/topology/Mesh.hh index e08cb52b37..006925d309 100644 --- a/libsrc/pylith/topology/Mesh.hh +++ b/libsrc/pylith/topology/Mesh.hh @@ -66,7 +66,7 @@ public: * @param label Label for mesh. */ void setDM(PetscDM dm, - const char* label="domain"); + const char* label=NULL); /** Set coordinate system. * diff --git a/libsrc/pylith/topology/RefineUniform.cc b/libsrc/pylith/topology/RefineUniform.cc index c4830712d5..d0250b7b9c 100644 --- a/libsrc/pylith/topology/RefineUniform.cc +++ b/libsrc/pylith/topology/RefineUniform.cc @@ -123,7 +123,7 @@ pylith::topology::RefineUniform::refine(Mesh* const newMesh, } // for err = DMPlexReorderCohesiveSupports(dmNew);PYLITH_CHECK_ERROR(err); - newMesh->setDM(dmNew); + newMesh->setDM(dmNew, "domain"); _RefineUniform::Events::logger.eventBegin(_RefineUniform::Events::refineFixCellLabel); // Remove all non-cells from cells label diff --git a/libsrc/pylith/topology/ReverseCuthillMcKee.cc b/libsrc/pylith/topology/ReverseCuthillMcKee.cc index d4e8e9fadf..efadce8fb6 100644 --- a/libsrc/pylith/topology/ReverseCuthillMcKee.cc +++ b/libsrc/pylith/topology/ReverseCuthillMcKee.cc @@ -32,7 +32,7 @@ pylith::topology::ReverseCuthillMcKee::reorder(topology::Mesh* mesh) { err = DMPlexGetOrdering(dmOrig, MATORDERINGRCM, dmLabel, &permutation);PYLITH_CHECK_ERROR(err); err = DMPlexPermute(dmOrig, permutation, &dmNew);PYLITH_CHECK_ERROR(err); err = ISDestroy(&permutation);PYLITH_CHECK_ERROR(err); - mesh->setDM(dmNew); + mesh->setDM(dmNew, "domain"); // Verify that all material points (cells) are consecutive. PetscIS valuesIS = NULL; diff --git a/libsrc/pylith/topology/Stratum.icc b/libsrc/pylith/topology/Stratum.icc index 7cf76a5672..321a347b9d 100644 --- a/libsrc/pylith/topology/Stratum.icc +++ b/libsrc/pylith/topology/Stratum.icc @@ -16,7 +16,7 @@ inline pylith::topology::Stratum::Stratum(const PetscDM dmMesh, const StratumEnum stype, - const int level) { // constructor + const int level) { assert(dmMesh); PetscErrorCode err = 0; switch (stype) { @@ -37,7 +37,7 @@ pylith::topology::Stratum::Stratum(const PetscDM dmMesh, // ---------------------------------------------------------------------- // Default destructor inline -pylith::topology::Stratum::~Stratum(void) { // destructor +pylith::topology::Stratum::~Stratum(void) { _begin = 0; _end = 0; } // destructor @@ -47,7 +47,7 @@ pylith::topology::Stratum::~Stratum(void) { // destructor // Get starting point. inline PetscInt -pylith::topology::Stratum::begin(void) const { // begin +pylith::topology::Stratum::begin(void) const { return _begin; } // begin diff --git a/modulesrc/topology/Mesh.i b/modulesrc/topology/Mesh.i index 01828c443d..640982036c 100644 --- a/modulesrc/topology/Mesh.i +++ b/modulesrc/topology/Mesh.i @@ -45,20 +45,6 @@ public: */ Mesh* clone(void) const; - /** Get DMPlex mesh. - * - * @returns DMPlex mesh. - */ - PetscDM getDM(void) const; - - /** Set DMPlex mesh. - * - * @param DMPlex mesh. - * @param label Label for mesh. - */ - void setDM(PetscDM dm, - const char* label="domain"); - /** Set coordinate system. * * @param cs Coordinate system. diff --git a/tests/libtests/meshio/TestMeshIO.cc b/tests/libtests/meshio/TestMeshIO.cc index 3a9dac285b..c9a44ca317 100644 --- a/tests/libtests/meshio/TestMeshIO.cc +++ b/tests/libtests/meshio/TestMeshIO.cc @@ -114,7 +114,7 @@ pylith::meshio::TestMeshIO::_createMesh(void) { } // for err = DMPlexCreateFromCellListPetsc(_mesh->getComm(), _data->cellDim, _data->numCells, _data->numVertices, _data->numCorners, interpolateMesh, cells, _data->spaceDim, _data->vertices, &dmMesh);PYLITH_CHECK_ERROR(err); delete [] cells; - _mesh->setDM(dmMesh); + _mesh->setDM(dmMesh, "domain"); // Material ids PylithInt cStart, cEnd; diff --git a/tests/libtests/topology/TestReverseCuthillMcKee.cc b/tests/libtests/topology/TestReverseCuthillMcKee.cc index 51f4db0f01..69dc221a77 100644 --- a/tests/libtests/topology/TestReverseCuthillMcKee.cc +++ b/tests/libtests/topology/TestReverseCuthillMcKee.cc @@ -65,7 +65,7 @@ pylith::topology::TestReverseCuthillMcKee::testReorder(void) { const PetscDM dmOrig = _mesh->getDM(); PetscObjectReference((PetscObject) dmOrig); Mesh meshOrig; - meshOrig.setDM(dmOrig); + meshOrig.setDM(dmOrig, "domain"); ReverseCuthillMcKee::reorder(_mesh); From 3815917524f6f33f326052218a77d48b33235dd3 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 23 Aug 2024 11:23:44 -0600 Subject: [PATCH 07/18] Move change in basis order from projection to loweest interpolation level. --- libsrc/pylith/meshio/OutputSubfield.cc | 29 ++++++++++++------- libsrc/pylith/topology/RefineInterpolator.cc | 26 +++++++++++++++-- libsrc/pylith/topology/RefineInterpolator.hh | 8 ++++- .../meshio/TestDataWriterHDF5ExtMaterial.cc | 4 +-- .../meshio/TestDataWriterHDF5ExtMesh.cc | 4 +-- .../meshio/TestDataWriterHDF5ExtSubmesh.cc | 4 +-- .../meshio/TestDataWriterHDF5Material.cc | 4 +-- .../libtests/meshio/TestDataWriterHDF5Mesh.cc | 4 +-- .../meshio/TestDataWriterHDF5Submesh.cc | 4 +-- .../meshio/TestDataWriterVTKMaterial.cc | 4 +-- .../libtests/meshio/TestDataWriterVTKMesh.cc | 4 +-- .../meshio/TestDataWriterVTKSubmesh.cc | 4 +-- 12 files changed, 67 insertions(+), 32 deletions(-) diff --git a/libsrc/pylith/meshio/OutputSubfield.cc b/libsrc/pylith/meshio/OutputSubfield.cc index d9226d3ef1..8ccd480b55 100644 --- a/libsrc/pylith/meshio/OutputSubfield.cc +++ b/libsrc/pylith/meshio/OutputSubfield.cc @@ -128,10 +128,16 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, const pylith::topology::Field::SubfieldInfo& info = field.getSubfieldInfo(name); subfield->_subfieldIndex = info.index; subfield->_description = info.description; - subfield->_discretization = info.fe; - subfield->_discretization.dimension = mesh.getDimension(); - // Basis order of output should be less than or equai to the basis order of the computed field. - subfield->_discretization.basisOrder = std::min(basisOrder, info.fe.basisOrder); + const int outputBasisOrder = std::min(basisOrder, info.fe.basisOrder); + + // Discretization for projection + pylith::topology::FieldBase::Discretization projectDiscretization = info.fe; + projectDiscretization.dimension = mesh.getDimension(); + projectDiscretization.basisOrder = refineLevels ? info.fe.basisOrder : outputBasisOrder; + + // Discretization for output + subfield->_discretization = projectDiscretization; + subfield->_discretization.basisOrder = outputBasisOrder; PetscErrorCode err = PETSC_SUCCESS; @@ -141,12 +147,13 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, err = DMReorderSectionSetType(subfield->_projectDM, NULL);PYLITH_CHECK_ERROR(err); err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); - PetscFE fe = pylith::topology::FieldOps::createFE(subfield->_discretization, subfield->_projectDM, - info.description.numComponents);assert(fe); - err = PetscFESetName(fe, info.description.label.c_str());PYLITH_CHECK_ERROR(err); - err = DMSetField(subfield->_projectDM, 0, NULL, (PetscObject)fe);PYLITH_CHECK_ERROR(err); + // Setup PETSc FE (discretization) for projection + PetscFE projectFE = pylith::topology::FieldOps::createFE(projectDiscretization, subfield->_projectDM, + info.description.numComponents);assert(projectFE); + err = PetscFESetName(projectFE, info.description.label.c_str());PYLITH_CHECK_ERROR(err); + err = DMSetField(subfield->_projectDM, 0, NULL, (PetscObject)projectFE);PYLITH_CHECK_ERROR(err); err = DMSetFieldAvoidTensor(subfield->_projectDM, 0, PETSC_TRUE);PYLITH_CHECK_ERROR(err); - err = PetscFEDestroy(&fe);PYLITH_CHECK_ERROR(err); + err = PetscFEDestroy(&projectFE);PYLITH_CHECK_ERROR(err); err = DMCreateDS(subfield->_projectDM);PYLITH_CHECK_ERROR(err); if (!refineLevels) { @@ -155,10 +162,10 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, } else { delete subfield->_interpolator;subfield->_interpolator = new pylith::topology::RefineInterpolator(); assert(subfield->_interpolator); - subfield->_interpolator->initialize(subfield->_projectDM, refineLevels); + subfield->_interpolator->initialize(subfield->_projectDM, refineLevels, outputBasisOrder, info.description, subfield->_discretization); subfield->_outputDM = subfield->_interpolator->getOutputDM(); err = PetscObjectReference((PetscObject)subfield->_outputDM);PYLITH_CHECK_ERROR(err); - } + } // if/else err = DMCreateGlobalVector(subfield->_projectDM, &subfield->_projectVector);PYLITH_CHECK_ERROR(err); err = PetscObjectSetName((PetscObject)subfield->_projectVector, name);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/topology/RefineInterpolator.cc b/libsrc/pylith/topology/RefineInterpolator.cc index 043d38184b..200b09b248 100644 --- a/libsrc/pylith/topology/RefineInterpolator.cc +++ b/libsrc/pylith/topology/RefineInterpolator.cc @@ -15,6 +15,7 @@ #include "pylith/topology/Mesh.hh" // USES Mesh #include "pylith/topology/MeshOps.hh" // USES MeshOps #include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/EventLogger.hh" // USES EventLogger @@ -95,7 +96,10 @@ pylith::topology::RefineInterpolator::getOutputDM(void) { // Initialize interpolation to refined mesh. void pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, - const int refineLevels) { + const int refineLevels, + const int outputBasisOrder, + const pylith::topology::FieldBase::Description& description, + const pylith::topology::FieldBase::Discretization& discretization) { PYLITH_METHOD_BEGIN; _RefineInterpolator::Events::logger.eventBegin(_RefineInterpolator::Events::initialize); @@ -127,7 +131,25 @@ pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); #endif - err = DMCopyDisc(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + + if (iLevel < _levels.size()-1) { + err = DMCopyDisc(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + } else { +#if 1 + PetscFE outputFE = pylith::topology::FieldOps::createFE(discretization, _levels[iLevel].dm, + description.numComponents);assert(outputFE); + err = PetscFESetName(outputFE, description.label.c_str());PYLITH_CHECK_ERROR(err); + err = DMSetField(_levels[iLevel].dm, 0, NULL, (PetscObject)outputFE);PYLITH_CHECK_ERROR(err); + err = DMSetFieldAvoidTensor(_levels[iLevel].dm, 0, PETSC_TRUE);PYLITH_CHECK_ERROR(err); + err = PetscFEDestroy(&outputFE);PYLITH_CHECK_ERROR(err); + err = DMCreateDS(_levels[iLevel].dm);PYLITH_CHECK_ERROR(err); +#else + err = DMCopyFields(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + const PetscInt minBasisOrder = PETSC_DETERMINE; + const PetscInt maxBasisOrder = outputBasisOrder; + err = DMCopyDS(dmPrev, minBasisOrder, maxBasisOrder, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); +#endif + } // else err = DMGetGlobalVector(_levels[iLevel].dm, &_levels[iLevel].vector);PYLITH_CHECK_ERROR(err); err = PetscObjectReference((PetscObject) _levels[iLevel].vector);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/topology/RefineInterpolator.hh b/libsrc/pylith/topology/RefineInterpolator.hh index 5c03fdd3f0..453f1e6662 100644 --- a/libsrc/pylith/topology/RefineInterpolator.hh +++ b/libsrc/pylith/topology/RefineInterpolator.hh @@ -12,6 +12,8 @@ #include "pylith/topology/topologyfwd.hh" // forward declarations #include "pylith/utils/petscfwd.h" // USES PetscDM +#include "pylith/topology/FieldBase.hh" // USES FieldBase + #include // HASA std::vector /// @brief Interpolate fields to uniformly refined mesh. @@ -39,9 +41,13 @@ public: * * @param[in] dmMesh PETSc DM for starting point of refinement. * @param[in] refineLevels Number of levels of mesh refinement. + * @param[in] outputBasisOrder Basis order for output. */ void initialize(const PetscDM& dmMesh, - const int refineLevels); + const int refineLevels, + const int outputBasisOrder, + const pylith::topology::FieldBase::Description& description, + const pylith::topology::FieldBase::Discretization& discretization); /** Interpolate field to fine mesh level. * diff --git a/tests/libtests/meshio/TestDataWriterHDF5ExtMaterial.cc b/tests/libtests/meshio/TestDataWriterHDF5ExtMaterial.cc index db0d2dc91f..48d265542b 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5ExtMaterial.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5ExtMaterial.cc @@ -86,7 +86,7 @@ pylith::meshio::TestDataWriterHDF5ExtMaterial::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -127,7 +127,7 @@ pylith::meshio::TestDataWriterHDF5ExtMaterial::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterHDF5ExtMesh.cc b/tests/libtests/meshio/TestDataWriterHDF5ExtMesh.cc index c8bf8e15de..f4fb71b22f 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5ExtMesh.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5ExtMesh.cc @@ -156,7 +156,7 @@ pylith::meshio::TestDataWriterHDF5ExtMesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -197,7 +197,7 @@ pylith::meshio::TestDataWriterHDF5ExtMesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterHDF5ExtSubmesh.cc b/tests/libtests/meshio/TestDataWriterHDF5ExtSubmesh.cc index ff03340964..c237cbec9a 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5ExtSubmesh.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5ExtSubmesh.cc @@ -87,7 +87,7 @@ pylith::meshio::TestDataWriterHDF5ExtSubmesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -128,7 +128,7 @@ pylith::meshio::TestDataWriterHDF5ExtSubmesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterHDF5Material.cc b/tests/libtests/meshio/TestDataWriterHDF5Material.cc index 403f5ef896..7dd65469cc 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5Material.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5Material.cc @@ -86,7 +86,7 @@ pylith::meshio::TestDataWriterHDF5Material::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -127,7 +127,7 @@ pylith::meshio::TestDataWriterHDF5Material::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterHDF5Mesh.cc b/tests/libtests/meshio/TestDataWriterHDF5Mesh.cc index f0be68e6cd..f3aa359122 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5Mesh.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5Mesh.cc @@ -129,7 +129,7 @@ pylith::meshio::TestDataWriterHDF5Mesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -170,7 +170,7 @@ pylith::meshio::TestDataWriterHDF5Mesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterHDF5Submesh.cc b/tests/libtests/meshio/TestDataWriterHDF5Submesh.cc index 2ca0d280d6..d185943a96 100644 --- a/tests/libtests/meshio/TestDataWriterHDF5Submesh.cc +++ b/tests/libtests/meshio/TestDataWriterHDF5Submesh.cc @@ -87,7 +87,7 @@ pylith::meshio::TestDataWriterHDF5Submesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -128,7 +128,7 @@ pylith::meshio::TestDataWriterHDF5Submesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterVTKMaterial.cc b/tests/libtests/meshio/TestDataWriterVTKMaterial.cc index 096a6a71bc..0addb28da3 100644 --- a/tests/libtests/meshio/TestDataWriterVTKMaterial.cc +++ b/tests/libtests/meshio/TestDataWriterVTKMaterial.cc @@ -104,7 +104,7 @@ pylith::meshio::TestDataWriterVTKMaterial::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_materialMesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -148,7 +148,7 @@ pylith::meshio::TestDataWriterVTKMaterial::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_materialMesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterVTKMesh.cc b/tests/libtests/meshio/TestDataWriterVTKMesh.cc index 4604f55da0..ff1fe16fc8 100644 --- a/tests/libtests/meshio/TestDataWriterVTKMesh.cc +++ b/tests/libtests/meshio/TestDataWriterVTKMesh.cc @@ -163,7 +163,7 @@ pylith::meshio::TestDataWriterVTKMesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_mesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -206,7 +206,7 @@ pylith::meshio::TestDataWriterVTKMesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_mesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); diff --git a/tests/libtests/meshio/TestDataWriterVTKSubmesh.cc b/tests/libtests/meshio/TestDataWriterVTKSubmesh.cc index 6e6e4601f4..5b3d8b7c98 100644 --- a/tests/libtests/meshio/TestDataWriterVTKSubmesh.cc +++ b/tests/libtests/meshio/TestDataWriterVTKSubmesh.cc @@ -101,7 +101,7 @@ pylith::meshio::TestDataWriterVTKSubmesh::testWriteVertexField(void) { const pylith::string_vector& subfieldNames = vertexField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1); + OutputSubfield* subfield = OutputSubfield::create(vertexField, *_submesh, subfieldNames[i].c_str(), 1, 0); assert(subfield); subfield->project(vertexField.getOutputVector()); writer.writeVertexField(t, *subfield); @@ -146,7 +146,7 @@ pylith::meshio::TestDataWriterVTKSubmesh::testWriteCellField(void) { const pylith::string_vector& subfieldNames = cellField.getSubfieldNames(); const size_t numFields = subfieldNames.size(); for (size_t i = 0; i < numFields; ++i) { - OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0); + OutputSubfield* subfield = OutputSubfield::create(cellField, *_submesh, subfieldNames[i].c_str(), 0, 0); assert(subfield); subfield->project(cellField.getOutputVector()); writer.writeCellField(t, *subfield); From 3743fef4875be2e239441cc7805ff42c69979b9a Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Mon, 26 Aug 2024 08:23:31 -0600 Subject: [PATCH 08/18] Upate OutputSoln to allow refinement of output. --- libsrc/pylith/meshio/OutputSolnBoundary.cc | 7 ++++++- libsrc/pylith/meshio/OutputSolnDomain.cc | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/meshio/OutputSolnBoundary.cc b/libsrc/pylith/meshio/OutputSolnBoundary.cc index 54677772a1..262bfd602b 100644 --- a/libsrc/pylith/meshio/OutputSolnBoundary.cc +++ b/libsrc/pylith/meshio/OutputSolnBoundary.cc @@ -116,7 +116,6 @@ pylith::meshio::OutputSolnBoundary::_writeSolnStep(const PylithReal t, const pylith::string_vector& subfieldNames = pylith::topology::FieldOps::getSubfieldNamesDomain(solution); PetscVec solutionVector = solution.getOutputVector();assert(solutionVector); - _openSolnStep(t, *_boundaryMesh); const size_t numSubfieldNames = subfieldNames.size(); for (size_t iField = 0; iField < numSubfieldNames; iField++) { assert(solution.hasSubfield(subfieldNames[iField].c_str())); @@ -125,6 +124,12 @@ pylith::meshio::OutputSolnBoundary::_writeSolnStep(const PylithReal t, subfield = OutputObserver::_getSubfield(solution, *_boundaryMesh, subfieldNames[iField].c_str());assert(subfield); subfield->project(solutionVector); + if (0 == iField) { + // Need output mesh from subfield (which may be refined). + assert(subfield); + pylith::topology::Mesh* outputMesh = _getOutputMesh(*subfield); + _openSolnStep(t, *outputMesh); + } // if OutputObserver::_appendField(t, *subfield); } // for _closeSolnStep(); diff --git a/libsrc/pylith/meshio/OutputSolnDomain.cc b/libsrc/pylith/meshio/OutputSolnDomain.cc index c6a59d2bad..309b5f2ceb 100644 --- a/libsrc/pylith/meshio/OutputSolnDomain.cc +++ b/libsrc/pylith/meshio/OutputSolnDomain.cc @@ -44,7 +44,6 @@ pylith::meshio::OutputSolnDomain::_writeSolnStep(const PylithReal t, const pylith::string_vector& subfieldNames = pylith::topology::FieldOps::getSubfieldNamesDomain(solution); PetscVec solutionVector = solution.getOutputVector();assert(solutionVector); - _openSolnStep(t, solution.getMesh()); const size_t numSubfieldNames = subfieldNames.size(); for (size_t iField = 0; iField < numSubfieldNames; iField++) { assert(solution.hasSubfield(subfieldNames[iField].c_str())); @@ -53,6 +52,12 @@ pylith::meshio::OutputSolnDomain::_writeSolnStep(const PylithReal t, subfield = OutputObserver::_getSubfield(solution, solution.getMesh(), subfieldNames[iField].c_str());assert(subfield); subfield->project(solutionVector); + if (0 == iField) { + // Need output mesh from subfield (which may be refined). + assert(subfield); + pylith::topology::Mesh* outputMesh = _getOutputMesh(*subfield); + _openSolnStep(t, *outputMesh); + } // if OutputObserver::_appendField(t, *subfield); } // for _closeSolnStep(); From 5c699ec990a329d9e76364986c845ab42158a1aa Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Mon, 26 Aug 2024 08:24:11 -0600 Subject: [PATCH 09/18] Update meshio unit test data for setting DM label. --- tests/libtests/meshio/data/hex8_mat_cell_t10.vtk | 2 +- tests/libtests/meshio/data/hex8_mat_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/hex8_surf_cell_t10.vtk | 2 +- tests/libtests/meshio/data/hex8_surf_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/quad4_mat_cell_t10.vtk | 2 +- tests/libtests/meshio/data/quad4_mat_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/quad4_surf_cell_t10.vtk | 2 +- tests/libtests/meshio/data/quad4_surf_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/tet4_mat_cell_t10.vtk | 2 +- tests/libtests/meshio/data/tet4_mat_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/tet4_surf_cell_t10.vtk | 2 +- tests/libtests/meshio/data/tet4_surf_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/tri3_mat_cell_t10.vtk | 2 +- tests/libtests/meshio/data/tri3_mat_vertex_t10.vtk | 2 +- tests/libtests/meshio/data/tri3_surf_cell_t10.vtk | 2 +- tests/libtests/meshio/data/tri3_surf_vertex_t10.vtk | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/libtests/meshio/data/hex8_mat_cell_t10.vtk b/tests/libtests/meshio/data/hex8_mat_cell_t10.vtk index 13db520ad4..fc526eb108 100644 --- a/tests/libtests/meshio/data/hex8_mat_cell_t10.vtk +++ b/tests/libtests/meshio/data/hex8_mat_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 8 double diff --git a/tests/libtests/meshio/data/hex8_mat_vertex_t10.vtk b/tests/libtests/meshio/data/hex8_mat_vertex_t10.vtk index bba4d463ba..5874d5b6d3 100644 --- a/tests/libtests/meshio/data/hex8_mat_vertex_t10.vtk +++ b/tests/libtests/meshio/data/hex8_mat_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 8 double diff --git a/tests/libtests/meshio/data/hex8_surf_cell_t10.vtk b/tests/libtests/meshio/data/hex8_surf_cell_t10.vtk index 5141dd8d63..d0bd7cdd40 100644 --- a/tests/libtests/meshio/data/hex8_surf_cell_t10.vtk +++ b/tests/libtests/meshio/data/hex8_surf_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_top ASCII DATASET UNSTRUCTURED_GRID POINTS 6 double diff --git a/tests/libtests/meshio/data/hex8_surf_vertex_t10.vtk b/tests/libtests/meshio/data/hex8_surf_vertex_t10.vtk index ac0ddd8d61..56bcc135f2 100644 --- a/tests/libtests/meshio/data/hex8_surf_vertex_t10.vtk +++ b/tests/libtests/meshio/data/hex8_surf_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_top ASCII DATASET UNSTRUCTURED_GRID POINTS 6 double diff --git a/tests/libtests/meshio/data/quad4_mat_cell_t10.vtk b/tests/libtests/meshio/data/quad4_mat_cell_t10.vtk index c94c13a22f..c37c7dff7b 100644 --- a/tests/libtests/meshio/data/quad4_mat_cell_t10.vtk +++ b/tests/libtests/meshio/data/quad4_mat_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 4 double diff --git a/tests/libtests/meshio/data/quad4_mat_vertex_t10.vtk b/tests/libtests/meshio/data/quad4_mat_vertex_t10.vtk index e0324b73ca..c440a56d1d 100644 --- a/tests/libtests/meshio/data/quad4_mat_vertex_t10.vtk +++ b/tests/libtests/meshio/data/quad4_mat_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 4 double diff --git a/tests/libtests/meshio/data/quad4_surf_cell_t10.vtk b/tests/libtests/meshio/data/quad4_surf_cell_t10.vtk index 3da7d562ee..fda62a7282 100644 --- a/tests/libtests/meshio/data/quad4_surf_cell_t10.vtk +++ b/tests/libtests/meshio/data/quad4_surf_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_bc3 ASCII DATASET UNSTRUCTURED_GRID POINTS 3 double diff --git a/tests/libtests/meshio/data/quad4_surf_vertex_t10.vtk b/tests/libtests/meshio/data/quad4_surf_vertex_t10.vtk index a8c9e25451..0f2d7b5c76 100644 --- a/tests/libtests/meshio/data/quad4_surf_vertex_t10.vtk +++ b/tests/libtests/meshio/data/quad4_surf_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_bc3 ASCII DATASET UNSTRUCTURED_GRID POINTS 3 double diff --git a/tests/libtests/meshio/data/tet4_mat_cell_t10.vtk b/tests/libtests/meshio/data/tet4_mat_cell_t10.vtk index 48ca2e35a1..0cf84701b4 100644 --- a/tests/libtests/meshio/data/tet4_mat_cell_t10.vtk +++ b/tests/libtests/meshio/data/tet4_mat_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 8 double diff --git a/tests/libtests/meshio/data/tet4_mat_vertex_t10.vtk b/tests/libtests/meshio/data/tet4_mat_vertex_t10.vtk index 68a5601186..a0a936cbf1 100644 --- a/tests/libtests/meshio/data/tet4_mat_vertex_t10.vtk +++ b/tests/libtests/meshio/data/tet4_mat_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 8 double diff --git a/tests/libtests/meshio/data/tet4_surf_cell_t10.vtk b/tests/libtests/meshio/data/tet4_surf_cell_t10.vtk index 0e394235a6..82dbfd2ba3 100644 --- a/tests/libtests/meshio/data/tet4_surf_cell_t10.vtk +++ b/tests/libtests/meshio/data/tet4_surf_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_boundary ASCII DATASET UNSTRUCTURED_GRID POINTS 4 double diff --git a/tests/libtests/meshio/data/tet4_surf_vertex_t10.vtk b/tests/libtests/meshio/data/tet4_surf_vertex_t10.vtk index 4226f0d8db..5eb51ac2c8 100644 --- a/tests/libtests/meshio/data/tet4_surf_vertex_t10.vtk +++ b/tests/libtests/meshio/data/tet4_surf_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_boundary ASCII DATASET UNSTRUCTURED_GRID POINTS 4 double diff --git a/tests/libtests/meshio/data/tri3_mat_cell_t10.vtk b/tests/libtests/meshio/data/tri3_mat_cell_t10.vtk index 1fdbc33632..fb31945e3e 100644 --- a/tests/libtests/meshio/data/tri3_mat_cell_t10.vtk +++ b/tests/libtests/meshio/data/tri3_mat_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 3 double diff --git a/tests/libtests/meshio/data/tri3_mat_vertex_t10.vtk b/tests/libtests/meshio/data/tri3_mat_vertex_t10.vtk index 6cf3589c45..7cffc794df 100644 --- a/tests/libtests/meshio/data/tri3_mat_vertex_t10.vtk +++ b/tests/libtests/meshio/data/tri3_mat_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +material ASCII DATASET UNSTRUCTURED_GRID POINTS 3 double diff --git a/tests/libtests/meshio/data/tri3_surf_cell_t10.vtk b/tests/libtests/meshio/data/tri3_surf_cell_t10.vtk index 95b7f6a899..177cd6b5b7 100644 --- a/tests/libtests/meshio/data/tri3_surf_cell_t10.vtk +++ b/tests/libtests/meshio/data/tri3_surf_cell_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_bc ASCII DATASET UNSTRUCTURED_GRID POINTS 2 double diff --git a/tests/libtests/meshio/data/tri3_surf_vertex_t10.vtk b/tests/libtests/meshio/data/tri3_surf_vertex_t10.vtk index 35d4129bf0..6eebf45eeb 100644 --- a/tests/libtests/meshio/data/tri3_surf_vertex_t10.vtk +++ b/tests/libtests/meshio/data/tri3_surf_vertex_t10.vtk @@ -1,5 +1,5 @@ # vtk DataFile Version 2.0 -domain +subdomain_bc ASCII DATASET UNSTRUCTURED_GRID POINTS 2 double From 201c90cbce39d144e4577f23ed3ff4ed94caa3bc Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Mon, 26 Aug 2024 08:24:30 -0600 Subject: [PATCH 10/18] Fix ordering of input vector for interpolation to refined meshes and memory leaks. --- libsrc/pylith/faults/TopologyOps.cc | 2 +- libsrc/pylith/meshio/OutputSubfield.cc | 12 +++- libsrc/pylith/meshio/OutputSubfield.hh | 1 + libsrc/pylith/topology/FieldOps.cc | 65 +++++++++++++++++++ libsrc/pylith/topology/FieldOps.hh | 15 +++++ libsrc/pylith/topology/MeshOps.cc | 17 ++++- libsrc/pylith/topology/RefineInterpolator.cc | 37 ++++++----- libsrc/pylith/topology/RefineInterpolator.hh | 5 ++ .../libtests/meshio/TestDataWriterMaterial.cc | 2 +- 9 files changed, 130 insertions(+), 26 deletions(-) diff --git a/libsrc/pylith/faults/TopologyOps.cc b/libsrc/pylith/faults/TopologyOps.cc index 11560d6e49..13402d8bed 100644 --- a/libsrc/pylith/faults/TopologyOps.cc +++ b/libsrc/pylith/faults/TopologyOps.cc @@ -222,7 +222,7 @@ pylith::faults::TopologyOps::create(pylith::topology::Mesh* mesh, err = DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); err = DMPlexSetScale(sdm, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); err = DMViewFromOptions(sdm, NULL, "-pylith_cohesive_dm_view");PYLITH_CHECK_ERROR(err); - mesh->setDM(sdm); + mesh->setDM(sdm, "domain"); } // create diff --git a/libsrc/pylith/meshio/OutputSubfield.cc b/libsrc/pylith/meshio/OutputSubfield.cc index 8ccd480b55..04456a7493 100644 --- a/libsrc/pylith/meshio/OutputSubfield.cc +++ b/libsrc/pylith/meshio/OutputSubfield.cc @@ -79,6 +79,7 @@ pylith::meshio::OutputSubfield::OutputSubfield(void) : _subfieldIndex(-1), _projectDM(PETSC_NULLPTR), _projectVector(PETSC_NULLPTR), + _projectVectorInterp(PETSC_NULLPTR), _fn(pylith::fekernels::Solution::passThruSubfield), _outputDM(PETSC_NULLPTR), _outputVector(PETSC_NULLPTR), @@ -104,6 +105,7 @@ pylith::meshio::OutputSubfield::deallocate(void) { PetscErrorCode err; err = VecDestroy(&_projectVector);PYLITH_CHECK_ERROR(err); + err = VecDestroy(&_projectVectorInterp);PYLITH_CHECK_ERROR(err); err = DMDestroy(&_projectDM);PYLITH_CHECK_ERROR(err); err = VecDestroy(&_outputVector);PYLITH_CHECK_ERROR(err); err = DMDestroy(&_outputDM);PYLITH_CHECK_ERROR(err); @@ -143,9 +145,10 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, // Setup PETSc DM for projection err = DMClone(mesh.getDM(), &subfield->_projectDM);PYLITH_CHECK_ERROR(err); + err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); err = DMReorderSectionSetDefault(subfield->_projectDM, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); err = DMReorderSectionSetType(subfield->_projectDM, NULL);PYLITH_CHECK_ERROR(err); - err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); + err = DMPlexReorderSetDefault(subfield->_projectDM, DM_REORDER_DEFAULT_FALSE); // Setup PETSc FE (discretization) for projection PetscFE projectFE = pylith::topology::FieldOps::createFE(projectDiscretization, subfield->_projectDM, @@ -172,6 +175,7 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, if (refineLevels) { err = DMCreateGlobalVector(subfield->_outputDM, &subfield->_outputVector);PYLITH_CHECK_ERROR(err); err = PetscObjectSetName((PetscObject)subfield->_outputVector, name);PYLITH_CHECK_ERROR(err); + err = VecDuplicate(subfield->_projectVector, &subfield->_projectVectorInterp);PYLITH_CHECK_ERROR(err); } else { subfield->_outputVector = subfield->_projectVector; err = PetscObjectReference((PetscObject)subfield->_outputVector);PYLITH_CHECK_ERROR(err); @@ -299,7 +303,8 @@ pylith::meshio::OutputSubfield::project(const PetscVec& fieldVector) { err = DMProjectField(_projectDM, t, fieldVector, &_fn, INSERT_VALUES, _projectVector);PYLITH_CHECK_ERROR(err); if (_interpolator) { - _interpolator->interpolate(&_outputVector, _projectVector); + pylith::topology::FieldOps::transformVector(&_projectVectorInterp, _interpolator->getInputDM(), _projectVector, _projectDM); + _interpolator->interpolate(&_outputVector, _projectVectorInterp); } // if err = VecScale(_outputVector, _description.scale);PYLITH_CHECK_ERROR(err); @@ -324,7 +329,8 @@ pylith::meshio::OutputSubfield::projectWithLabel(const PetscVec& fieldVector) { err = DMProjectFieldLabel(_projectDM, t, _label, 1, &_labelValue, PETSC_DETERMINE, NULL, fieldVector, &_fn, INSERT_VALUES, _projectVector);PYLITH_CHECK_ERROR(err); if (_interpolator) { - _interpolator->interpolate(&_outputVector, _projectVector); + pylith::topology::FieldOps::transformVector(&_projectVectorInterp, _interpolator->getInputDM(), _projectVector, _projectDM); + _interpolator->interpolate(&_outputVector, _projectVectorInterp); } // if err = VecScale(_outputVector, _description.scale);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/meshio/OutputSubfield.hh b/libsrc/pylith/meshio/OutputSubfield.hh index d6e55296cf..9501a87832 100644 --- a/libsrc/pylith/meshio/OutputSubfield.hh +++ b/libsrc/pylith/meshio/OutputSubfield.hh @@ -126,6 +126,7 @@ protected: PetscInt _subfieldIndex; ///< Index of subfield in fields. PetscDM _projectDM; ///< PETSc global vector for subfield projection. PetscVec _projectVector; ///< PETSc global vector for subfield projection. + PetscVec _projectVectorInterp; ///< PETSc global vector for subfield projection transformed for interpolation. PetscPointFunc _fn; ///< PETSc point function for projection. PetscDM _outputDM; ///< PETSc DM for subfield output. PetscVec _outputVector; ///< PETSc global vector for subfield output. diff --git a/libsrc/pylith/topology/FieldOps.cc b/libsrc/pylith/topology/FieldOps.cc index 1ce3269fab..03507063be 100644 --- a/libsrc/pylith/topology/FieldOps.cc +++ b/libsrc/pylith/topology/FieldOps.cc @@ -318,4 +318,69 @@ pylith::topology::FieldOps::createOutputLabel(const pylith::topology::Field* fie } +// ------------------------------------------------------------------------------------------------ +void +pylith::topology::FieldOps::transformVector(PetscVec* outputVector, + const PetscDM& outputDM, + const PetscVec& inputVector, + const PetscDM& inputDM) { + PYLITH_METHOD_BEGIN; + + assert(outputVector); + assert(outputDM); + assert(inputVector); + assert(inputDM); + + PetscErrorCode err = PETSC_SUCCESS; + PetscSection inputSection = PETSC_NULLPTR, outputSection = PETSC_NULLPTR; + err = DMGetGlobalSection(inputDM, &inputSection);PYLITH_CHECK_ERROR(err); + err = DMGetGlobalSection(outputDM, &outputSection);PYLITH_CHECK_ERROR(err); + + // Verify sizes + PetscInt outputNumFields = 0, inputNumFields = 0; + err = PetscSectionGetNumFields(inputSection, &inputNumFields);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetNumFields(outputSection, &outputNumFields);PYLITH_CHECK_ERROR(err); + assert(inputNumFields == outputNumFields); + + PetscInt inputSize = 0, outputSize = 0; + err = PetscSectionGetStorageSize(inputSection, &inputSize);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetStorageSize(outputSection, &outputSize);PYLITH_CHECK_ERROR(err); + assert(inputSize == outputSize); + + // Copy values from input vector to output vector + PetscIS subpointMap = PETSC_NULLPTR; // Mapping of points in output DM back to input DM + err = DMPlexGetSubpointIS(outputDM, &subpointMap);PYLITH_CHECK_ERROR(err); + PetscInt subpointMapSize = 0; + const PetscInt* subpointMapPoints = PETSC_NULLPTR; + err = ISGetSize(subpointMap, &subpointMapSize);PYLITH_CHECK_ERROR(err); + err = ISGetIndices(subpointMap, &subpointMapPoints);PYLITH_CHECK_ERROR(err); + + const PetscScalar* inputArray = PETSC_NULLPTR; + PetscScalar* outputArray = PETSC_NULLPTR; + err = VecGetArrayRead(inputVector, &inputArray);PYLITH_CHECK_ERROR(err); + err = VecGetArray(*outputVector, &outputArray);PYLITH_CHECK_ERROR(err); + + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(outputSection, &pStart, &pEnd); + for (PetscInt iPoint = 0; iPoint < subpointMapSize; ++iPoint) { + PetscInt inputDof = 0, inputOffset = 0; + PetscInt outputDof = 0, outputOffset = 0; + const PetscInt inputPoint = subpointMapPoints[iPoint]; + const PetscInt outputPoint = pStart + iPoint; + err = PetscSectionGetDof(inputSection, inputPoint, &inputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(inputSection, inputPoint, &inputOffset);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetDof(outputSection, outputPoint, &outputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(outputSection, outputPoint, &outputOffset);PYLITH_CHECK_ERROR(err); + assert(inputDof == outputDof); + for (PetscInt iDof = 0; iDof < inputDof; ++iDof) { + outputArray[outputOffset + iDof] = inputArray[inputOffset + iDof]; + } // for + } // for + err = VecRestoreArrayRead(inputVector, &inputArray);PYLITH_CHECK_ERROR(err); + err = VecRestoreArray(*outputVector, &outputArray);PYLITH_CHECK_ERROR(err); + + PYLITH_METHOD_END; +} + + // End of file diff --git a/libsrc/pylith/topology/FieldOps.hh b/libsrc/pylith/topology/FieldOps.hh index b434d08ba3..32307d088f 100644 --- a/libsrc/pylith/topology/FieldOps.hh +++ b/libsrc/pylith/topology/FieldOps.hh @@ -120,6 +120,21 @@ public: static void createOutputLabel(const pylith::topology::Field* field); + /** Transform vector using mapping from one PETSc DM to another. + * + * @note PETSc DMs must be compatible, including discretization. + * + * @param[out] outputVector Output vector. + * @param[in] outputDM PETSc DM associated with output vector. + * @param[out] outputVector Output vector. + * @param[in] outputDM PETSc DM associated with output vector. + */ + static + void transformVector(PetscVec* outputVector, + const PetscDM& outputDM, + const PetscVec& inputVector, + const PetscDM& inputDM); + /** Free saved PetscFE objects. */ static diff --git a/libsrc/pylith/topology/MeshOps.cc b/libsrc/pylith/topology/MeshOps.cc index e9180b54c9..2ad9fff789 100644 --- a/libsrc/pylith/topology/MeshOps.cc +++ b/libsrc/pylith/topology/MeshOps.cc @@ -369,13 +369,24 @@ pylith::topology::MeshOps::removeHangingCells(const PetscDM& dmMesh) { } // for err = DMPlexFilter(dmMesh, labelInclude, labelValue, PETSC_FALSE, PETSC_FALSE, PETSC_NULLPTR, &dmClean);PYLITH_CHECK_ERROR(err); + err = DMLabelDestroy(&labelInclude);PYLITH_CHECK_ERROR(err); + + // Create section using subpoint map to ensure sections are consistent. + PetscIS subpointIS = PETSC_NULLPTR; + PetscSection sectionOld = PETSC_NULLPTR, sectionNew = PETSC_NULLPTR; + err = DMPlexGetSubpointIS(dmClean, &subpointIS);PYLITH_CHECK_ERROR(err); + err = DMGetLocalSection(dmMesh, §ionOld);PYLITH_CHECK_ERROR(err); + err = PetscSectionCreateSubmeshSection(sectionOld, subpointIS, §ionNew);PYLITH_CHECK_ERROR(err); + err = DMSetLocalSection(dmClean, sectionNew);PYLITH_CHECK_ERROR(err); + err = PetscSectionDestroy(§ionNew);PYLITH_CHECK_ERROR(err); + + PetscReal lengthScale = 0.0; + err = DMPlexGetScale(dmMesh, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); + err = DMPlexSetScale(dmClean, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); } else { dmClean = dmMesh; err = PetscObjectReference((PetscObject) dmClean); } // if/else - PetscReal lengthScale = 1.0; - err = DMPlexGetScale(dmMesh, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); - err = DMPlexSetScale(dmClean, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); PYLITH_METHOD_RETURN(dmClean); } diff --git a/libsrc/pylith/topology/RefineInterpolator.cc b/libsrc/pylith/topology/RefineInterpolator.cc index 200b09b248..497671084f 100644 --- a/libsrc/pylith/topology/RefineInterpolator.cc +++ b/libsrc/pylith/topology/RefineInterpolator.cc @@ -84,6 +84,19 @@ pylith::topology::RefineInterpolator::deallocate(void) { } // deallocate +// ------------------------------------------------------------------------------------------------ +// Get PETSc DM for input (coarsest level) +PetscDM +pylith::topology::RefineInterpolator::getInputDM(void) { + PetscDM dmStart = PETSC_NULLPTR; + if (_levels.size() > 0) { + PetscErrorCode err = PETSC_SUCCESS; + err = DMGetCoarseDM(_levels[0].dm, &dmStart);PYLITH_CHECK_ERROR(err); + } // if + return dmStart; +} + + // ------------------------------------------------------------------------------------------------ // Get PETSc DM for output (finest level) PetscDM @@ -111,16 +124,18 @@ pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, PetscDM dmPrev = dmStart; PetscReal lengthScale = 1.0; + MPI_Comm comm = PetscObjectComm((PetscObject) dmMesh); for (size_t iLevel = 0; iLevel < _levels.size(); ++iLevel) { _levels[iLevel].dm = PETSC_NULLPTR; _levels[iLevel].interpolateMatrix = PETSC_NULLPTR; _levels[iLevel].vector = PETSC_NULLPTR; err = DMPlexSetRefinementUniform(dmPrev, PETSC_TRUE);PYLITH_CHECK_ERROR(err); - err = DMRefine(dmPrev, PetscObjectComm((PetscObject) dmMesh), &_levels[iLevel].dm);PYLITH_CHECK_ERROR(err); + err = DMRefine(dmPrev, comm, &_levels[iLevel].dm);PYLITH_CHECK_ERROR(err); err = DMSetCoarseDM(_levels[iLevel].dm, dmPrev);PYLITH_CHECK_ERROR(err); err = DMPlexGetScale(dmPrev, PETSC_UNIT_LENGTH, &lengthScale);PYLITH_CHECK_ERROR(err); err = DMPlexSetScale(_levels[iLevel].dm, PETSC_UNIT_LENGTH, lengthScale);PYLITH_CHECK_ERROR(err); + err = DMPlexReorderSetDefault(_levels[iLevel].dm, DM_REORDER_DEFAULT_FALSE); #if 0 // needed for higher order coordinates (not needed for affine coordinates) PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); @@ -129,34 +144,22 @@ pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, PetscCall(DMGetCoordinateDM(rdm, &rcdm)); PetscCall(DMGetCoordinatesLocal(odm, &cl)); PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); - #endif if (iLevel < _levels.size()-1) { err = DMCopyDisc(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); } else { -#if 1 - PetscFE outputFE = pylith::topology::FieldOps::createFE(discretization, _levels[iLevel].dm, - description.numComponents);assert(outputFE); - err = PetscFESetName(outputFE, description.label.c_str());PYLITH_CHECK_ERROR(err); - err = DMSetField(_levels[iLevel].dm, 0, NULL, (PetscObject)outputFE);PYLITH_CHECK_ERROR(err); - err = DMSetFieldAvoidTensor(_levels[iLevel].dm, 0, PETSC_TRUE);PYLITH_CHECK_ERROR(err); - err = PetscFEDestroy(&outputFE);PYLITH_CHECK_ERROR(err); - err = DMCreateDS(_levels[iLevel].dm);PYLITH_CHECK_ERROR(err); -#else - err = DMCopyFields(dmPrev, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); const PetscInt minBasisOrder = PETSC_DETERMINE; const PetscInt maxBasisOrder = outputBasisOrder; + err = DMCopyFields(dmPrev, minBasisOrder, maxBasisOrder, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); err = DMCopyDS(dmPrev, minBasisOrder, maxBasisOrder, _levels[iLevel].dm);PYLITH_CHECK_ERROR(err); -#endif } // else - err = DMGetGlobalVector(_levels[iLevel].dm, &_levels[iLevel].vector);PYLITH_CHECK_ERROR(err); - err = PetscObjectReference((PetscObject) _levels[iLevel].vector);PYLITH_CHECK_ERROR(err); - + err = DMCreateGlobalVector(_levels[iLevel].dm, &_levels[iLevel].vector);PYLITH_CHECK_ERROR(err); err = DMCreateInterpolation(dmPrev, _levels[iLevel].dm, &_levels[iLevel].interpolateMatrix, NULL);PYLITH_CHECK_ERROR(err); dmPrev = _levels[iLevel].dm; } // for + err = DMDestroy(&dmStart);PYLITH_CHECK_ERROR(err); _RefineInterpolator::Events::logger.eventEnd(_RefineInterpolator::Events::initialize); PYLITH_METHOD_END; @@ -172,8 +175,6 @@ pylith::topology::RefineInterpolator::interpolate(const PetscVec* vectorOut, _RefineInterpolator::Events::logger.eventBegin(_RefineInterpolator::Events::interpolate); assert(vectorOut); - // Should be global vectors - PetscVec vectorPrev = vectorIn; PetscErrorCode err = PETSC_SUCCESS; for (auto level : _levels) { diff --git a/libsrc/pylith/topology/RefineInterpolator.hh b/libsrc/pylith/topology/RefineInterpolator.hh index 453f1e6662..7614560a89 100644 --- a/libsrc/pylith/topology/RefineInterpolator.hh +++ b/libsrc/pylith/topology/RefineInterpolator.hh @@ -32,6 +32,11 @@ public: /// Deallocate data structures. void deallocate(void); + /** Get PETSc DM for input (coarsest level) + * + */ + PetscDM getInputDM(void); + /** Get PETSc DM for output (finest level) * */ diff --git a/tests/libtests/meshio/TestDataWriterMaterial.cc b/tests/libtests/meshio/TestDataWriterMaterial.cc index 7b8d7bd06e..2bf614659b 100644 --- a/tests/libtests/meshio/TestDataWriterMaterial.cc +++ b/tests/libtests/meshio/TestDataWriterMaterial.cc @@ -270,7 +270,7 @@ pylith::meshio::TestDataWriterMaterial::_initialize(void) { } // if delete _materialMesh; - _materialMesh = pylith::topology::MeshOps::createSubdomainMesh(*_domainMesh, pylith::topology::Mesh::cells_label_name, data->materialId, ":UNKNOWN:"); + _materialMesh = pylith::topology::MeshOps::createSubdomainMesh(*_domainMesh, pylith::topology::Mesh::cells_label_name, data->materialId, "material"); assert(_materialMesh); PYLITH_METHOD_END; From 0393473956cdab2cd261e6bdf0365fbe5f598d11 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Wed, 8 Jan 2025 15:00:53 -0700 Subject: [PATCH 11/18] Add some additional internal error checking for refining output. --- libsrc/pylith/meshio/OutputSubfield.cc | 2 +- libsrc/pylith/topology/RefineInterpolator.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/meshio/OutputSubfield.cc b/libsrc/pylith/meshio/OutputSubfield.cc index 04456a7493..a65015edb5 100644 --- a/libsrc/pylith/meshio/OutputSubfield.cc +++ b/libsrc/pylith/meshio/OutputSubfield.cc @@ -202,7 +202,7 @@ pylith::meshio::OutputSubfield::create(const pylith::topology::Field& field, subfield->_description = info.description; PetscErrorCode err = PETSC_SUCCESS; - err = DMClone(mesh.getDM(), &subfield->_projectDM);PYLITH_CHECK_ERROR(err); + err = DMClone(mesh.getDM(), &subfield->_projectDM);PYLITH_CHECK_ERROR(err);assert(subfield->_projectDM); err = DMReorderSectionSetDefault(subfield->_projectDM, DM_REORDER_DEFAULT_FALSE);PYLITH_CHECK_ERROR(err); err = DMReorderSectionSetType(subfield->_projectDM, NULL);PYLITH_CHECK_ERROR(err); err = PetscObjectSetName((PetscObject)subfield->_projectDM, name);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/topology/RefineInterpolator.cc b/libsrc/pylith/topology/RefineInterpolator.cc index 497671084f..1ff604f27f 100644 --- a/libsrc/pylith/topology/RefineInterpolator.cc +++ b/libsrc/pylith/topology/RefineInterpolator.cc @@ -119,7 +119,7 @@ pylith::topology::RefineInterpolator::initialize(const PetscDM& dmMesh, _levels.resize(refineLevels); PetscErrorCode err = PETSC_SUCCESS; - PetscDM dmStart = pylith::topology::MeshOps::removeHangingCells(dmMesh); + PetscDM dmStart = pylith::topology::MeshOps::removeHangingCells(dmMesh);assert(dmStart); err = DMCopyDisc(dmMesh, dmStart);PYLITH_CHECK_ERROR(err); PetscDM dmPrev = dmStart; From 431efc5963c3b8efb2a1e57c477b066295890f09 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Wed, 8 Jan 2025 15:01:11 -0700 Subject: [PATCH 12/18] Adjust code to work for refining output for domain. --- libsrc/pylith/topology/FieldOps.cc | 75 +++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/libsrc/pylith/topology/FieldOps.cc b/libsrc/pylith/topology/FieldOps.cc index 03507063be..7f13738272 100644 --- a/libsrc/pylith/topology/FieldOps.cc +++ b/libsrc/pylith/topology/FieldOps.cc @@ -348,34 +348,65 @@ pylith::topology::FieldOps::transformVector(PetscVec* outputVector, assert(inputSize == outputSize); // Copy values from input vector to output vector - PetscIS subpointMap = PETSC_NULLPTR; // Mapping of points in output DM back to input DM - err = DMPlexGetSubpointIS(outputDM, &subpointMap);PYLITH_CHECK_ERROR(err); - PetscInt subpointMapSize = 0; - const PetscInt* subpointMapPoints = PETSC_NULLPTR; - err = ISGetSize(subpointMap, &subpointMapSize);PYLITH_CHECK_ERROR(err); - err = ISGetIndices(subpointMap, &subpointMapPoints);PYLITH_CHECK_ERROR(err); - const PetscScalar* inputArray = PETSC_NULLPTR; PetscScalar* outputArray = PETSC_NULLPTR; err = VecGetArrayRead(inputVector, &inputArray);PYLITH_CHECK_ERROR(err); err = VecGetArray(*outputVector, &outputArray);PYLITH_CHECK_ERROR(err); - PetscInt pStart = 0, pEnd = 0; - err = PetscSectionGetChart(outputSection, &pStart, &pEnd); - for (PetscInt iPoint = 0; iPoint < subpointMapSize; ++iPoint) { - PetscInt inputDof = 0, inputOffset = 0; - PetscInt outputDof = 0, outputOffset = 0; - const PetscInt inputPoint = subpointMapPoints[iPoint]; - const PetscInt outputPoint = pStart + iPoint; - err = PetscSectionGetDof(inputSection, inputPoint, &inputDof);PYLITH_CHECK_ERROR(err); - err = PetscSectionGetOffset(inputSection, inputPoint, &inputOffset);PYLITH_CHECK_ERROR(err); - err = PetscSectionGetDof(outputSection, outputPoint, &outputDof);PYLITH_CHECK_ERROR(err); - err = PetscSectionGetOffset(outputSection, outputPoint, &outputOffset);PYLITH_CHECK_ERROR(err); - assert(inputDof == outputDof); - for (PetscInt iDof = 0; iDof < inputDof; ++iDof) { - outputArray[outputOffset + iDof] = inputArray[inputOffset + iDof]; + // Check whether inputDM and outputDM have the same names for points. + // We will assume that if inputDM and outputDM have the same range of points, + // then the names are the same and we ignore the subpoint map. + PetscDMLabel subpointMap = PETSC_NULLPTR; // Mapping of points in output DM back to input DM + PetscInt pStartIn, pEndIn, pStartOut, pEndOut; + PetscBool renamePoints = PETSC_FALSE; + err = DMPlexGetSubpointMap(outputDM, &subpointMap);PYLITH_CHECK_ERROR(err); + err = DMPlexGetChart(inputDM, &pStartIn, &pEndIn); + err = DMPlexGetChart(outputDM, &pStartOut, &pEndOut); + renamePoints = subpointMap && ((pStartIn != pStartOut) || (pEndIn != pEndOut)) ? PETSC_TRUE : PETSC_FALSE; + if (renamePoints) { + PetscIS subpointIS = PETSC_NULLPTR; // Mapping of points in output DM back to input DM + PetscInt subpointISSize = 0; + const PetscInt* subpointISPoints = PETSC_NULLPTR; + err = DMPlexGetSubpointIS(outputDM, &subpointIS);PYLITH_CHECK_ERROR(err); + err = ISGetSize(subpointIS, &subpointISSize);PYLITH_CHECK_ERROR(err); + err = ISGetIndices(subpointIS, &subpointISPoints);PYLITH_CHECK_ERROR(err); + + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(outputSection, &pStart, &pEnd); + for (PetscInt iPoint = 0; iPoint < subpointISSize; ++iPoint) { + PetscInt inputDof = 0, inputOffset = 0; + PetscInt outputDof = 0, outputOffset = 0; + const PetscInt inputPoint = subpointISPoints[iPoint]; + const PetscInt outputPoint = pStart + iPoint; + err = PetscSectionGetDof(inputSection, inputPoint, &inputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(inputSection, inputPoint, &inputOffset);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetDof(outputSection, outputPoint, &outputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(outputSection, outputPoint, &outputOffset);PYLITH_CHECK_ERROR(err); + + assert(inputDof == outputDof); + for (PetscInt iDof = 0; iDof < inputDof; ++iDof) { + outputArray[outputOffset + iDof] = inputArray[inputOffset + iDof]; + } // for } // for - } // for + } else { + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(outputSection, &pStart, &pEnd); + for (PetscInt point = pStart; point < pEnd; ++point) { + PetscInt inputDof = 0, inputOffset = 0; + PetscInt outputDof = 0, outputOffset = 0; + const PetscInt inputPoint = point; + const PetscInt outputPoint = point; + err = PetscSectionGetDof(inputSection, inputPoint, &inputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(inputSection, inputPoint, &inputOffset);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetDof(outputSection, outputPoint, &outputDof);PYLITH_CHECK_ERROR(err); + err = PetscSectionGetOffset(outputSection, outputPoint, &outputOffset);PYLITH_CHECK_ERROR(err); + + assert(inputDof == outputDof); + for (PetscInt iDof = 0; iDof < inputDof; ++iDof) { + outputArray[outputOffset + iDof] = inputArray[inputOffset + iDof]; + } // for + } // for + } // if/else err = VecRestoreArrayRead(inputVector, &inputArray);PYLITH_CHECK_ERROR(err); err = VecRestoreArray(*outputVector, &outputArray);PYLITH_CHECK_ERROR(err); From 3a1621a6013abee590eb5acf712dcd148ec78f06 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:07:43 -0600 Subject: [PATCH 13/18] Update examples/strikeslip-2d for better slip distribution and refining output. --- .../strikeslip-2d/figs/step06-solution.pdf | Bin 15506 -> 0 bytes .../strikeslip-2d/figs/step06-solution.svg | 1285 ---------------- .../strikeslip-2d/figs/step07a-solution.pdf | Bin 15523 -> 0 bytes .../strikeslip-2d/figs/step07a-solution.svg | 1293 ----------------- .../strikeslip-2d/figs/step07b-solution.pdf | Bin 15527 -> 0 bytes .../strikeslip-2d/figs/step07b-solution.svg | 1293 ----------------- examples/strikeslip-2d/Makefile.am | 11 +- .../strikeslip-2d/cfcatmip_parameters.txt | 6 +- examples/strikeslip-2d/generate_slip.py | 362 +++++ examples/strikeslip-2d/invert_slip.py | 98 +- .../strikeslip-2d/slip_variable.spatialdb | 453 +++++- examples/strikeslip-2d/step04_varslip.cfg | 14 +- examples/strikeslip-2d/step05_greensfns.cfg | 1 + .../strikeslip-2d/viz/plot_catmip_results.py | 127 +- .../viz/plot_inversion_results.py | 111 +- examples/strikeslip-2d/viz/plot_slip.py | 25 + .../strikeslip-2d/viz/plot_slip_impulses.py | 35 + 17 files changed, 1060 insertions(+), 4054 deletions(-) delete mode 100644 docs/user/examples/strikeslip-2d/figs/step06-solution.pdf delete mode 100644 docs/user/examples/strikeslip-2d/figs/step06-solution.svg delete mode 100644 docs/user/examples/strikeslip-2d/figs/step07a-solution.pdf delete mode 100644 docs/user/examples/strikeslip-2d/figs/step07a-solution.svg delete mode 100644 docs/user/examples/strikeslip-2d/figs/step07b-solution.pdf delete mode 100644 docs/user/examples/strikeslip-2d/figs/step07b-solution.svg create mode 100755 examples/strikeslip-2d/generate_slip.py create mode 100755 examples/strikeslip-2d/viz/plot_slip.py create mode 100755 examples/strikeslip-2d/viz/plot_slip_impulses.py diff --git a/docs/user/examples/strikeslip-2d/figs/step06-solution.pdf b/docs/user/examples/strikeslip-2d/figs/step06-solution.pdf deleted file mode 100644 index bf40381433572f012ab1f955710037c982192d44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15506 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 diff --git a/docs/user/examples/strikeslip-2d/figs/step06-solution.svg b/docs/user/examples/strikeslip-2d/figs/step06-solution.svg deleted file mode 100644 index 906e7383cb..0000000000 --- a/docs/user/examples/strikeslip-2d/figs/step06-solution.svg +++ /dev/null @@ -1,1285 +0,0 @@ - - - - - - - - 2024-06-06T05:30:41.253651 - image/svg+xml - - - Matplotlib v3.8.2, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/user/examples/strikeslip-2d/figs/step07a-solution.pdf b/docs/user/examples/strikeslip-2d/figs/step07a-solution.pdf deleted file mode 100644 index 1223f609fae2b656c8c8c47c2bd49ce0e77288ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15523 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 Y^`|(IDb%G1g~eboFflPL6K&Z40lkG4O8@`> diff --git a/docs/user/examples/strikeslip-2d/figs/step07a-solution.svg b/docs/user/examples/strikeslip-2d/figs/step07a-solution.svg deleted file mode 100644 index 71104fae95..0000000000 --- a/docs/user/examples/strikeslip-2d/figs/step07a-solution.svg +++ /dev/null @@ -1,1293 +0,0 @@ - - - - - - - - 2023-06-09T21:21:51.387141 - image/svg+xml - - - Matplotlib v3.7.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/user/examples/strikeslip-2d/figs/step07b-solution.pdf b/docs/user/examples/strikeslip-2d/figs/step07b-solution.pdf deleted file mode 100644 index 85af0efc20ad41076054cb26a05c380d27de479a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15527 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⁣-)JcHZ9P%# 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 - - - - - - - 2023-06-09T21:22:00.438095 - image/svg+xml - - - Matplotlib v3.7.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/strikeslip-2d/Makefile.am b/examples/strikeslip-2d/Makefile.am index 12c567f400..b62d9e970f 100644 --- a/examples/strikeslip-2d/Makefile.am +++ b/examples/strikeslip-2d/Makefile.am @@ -12,7 +12,12 @@ dist_noinst_PYTHON = \ generate_gmsh.py \ generate_cubit.py \ generate_gnssstations.py \ - invert_slip.py + generate_slip.py \ + invert_slip.py \ + viz/plot_slip.py \ + viz/plot_slip_impulses.py \ + viz/plot_inversion_results.py \ + viz/plot_catmip_results.py dist_noinst_DATA = \ README.md \ @@ -31,9 +36,7 @@ dist_noinst_DATA = \ disprate_bc_xpos.spatialdb \ gnss_stations.txt \ slip_impulses.spatialdb \ - slip_variable.spatialdb \ - viz/plot_inversion_results.py \ - viz/plot_catmip_results.py + slip_variable.spatialdb # End of file diff --git a/examples/strikeslip-2d/cfcatmip_parameters.txt b/examples/strikeslip-2d/cfcatmip_parameters.txt index 43a5bd85e0..26ff163eaa 100644 --- a/examples/strikeslip-2d/cfcatmip_parameters.txt +++ b/examples/strikeslip-2d/cfcatmip_parameters.txt @@ -1,8 +1,8 @@ -# Sample parameter file for pylith_catmip model. +# Sample parameter file for pylith_cfcatmip model. # Data files -filename_observations = output/step04_varslip-gps_stations.h5 -filename_greens_fns = output/step05_greensfns-gps_stations.h5 +filename_observations = output/step04_varslip-gnss_stations.h5 +filename_greens_fns = output/step05_greensfns-gnss_stations.h5 # Model parameters rake_parallel_prior = logistic diff --git a/examples/strikeslip-2d/generate_slip.py b/examples/strikeslip-2d/generate_slip.py new file mode 100755 index 0000000000..91ba7e5569 --- /dev/null +++ b/examples/strikeslip-2d/generate_slip.py @@ -0,0 +1,362 @@ +#!/usr/bin/env nemesis +"""Python script for generating slip profile. + +REQUIRES: scipy (not included in PyLith binary distribution) +""" + +import math +import abc + +import scipy +import numpy + +from pythia.pyre.units.length import m, km + + +def cli(): + """Command line interface. + """ + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--eq-magnitude", action="store", type=float, dest="eq_magnitude", default=6.5, help="Earthquake magnitude.") + parser.add_argument("--total-length", action="store", type=float, dest="total_length", default=40.0, help="Rupture length (km).") + parser.add_argument("--taper-length", action="store", type=float, dest="taper_length", default=0.5, help="Taper length (km).") + parser.add_argument("--resolution", action="store", type=float, dest="resolution", default=100.0, help="Resolution (m).") + parser.add_argument("--db-filename", action="store", dest="filename_db", default="slip_variable.spatialdb", help="Filename for slip spatial database.") + parser.add_argument("--raw-filename", action="store", dest="filename_raw", default="output/slip_variable.txt", help="Filename for raw slip data.") + args = parser.parse_args() + + generator = SlipGenerator( + eq_magnitude=args.eq_magnitude, + total_length=args.total_length*km, + taper_length=args.taper_length*km, + dx=args.resolution*m, + ) + (x, slip) = generator.generate() + SpatialDBWriter.write(args.filename_db, x, slip) + RawWriter.write(args.filename_raw, x, slip) + + +class SlipGenerator: + """Object for generating 1D slip profile. + """ + + def __init__(self, eq_magnitude: float, total_length: float, taper_length: float, dx: float): + """Generate 1D slip profile. + + Args: + eq_magnitude: Earthquake magnitude. + total_length: Rupture length (m) + taper_length: Length of taper (m) at ends of rupture. + dx: Discretization size for slip profile. + """ + self.eq_magnitude = eq_magnitude + self.total_length = total_length + self.taper_length = taper_length + self.dx = dx + + def generate(self) -> tuple: + """Generate slip profile. + + Returns: + (numpy.ndarray, numpy.ndarray): (distance along fault (m), slip along fault (m)) + """ + MAX_ITERATIONS = 100 + END_TOLERANCE = 0.02 + ZERO_TOLERANCE = 0.05 + SPLINE_SPACING = 4 # Ratio of discretization size in raw slip profile to discretization size in spline + + dx_points = SPLINE_SPACING*self.dx # Discretization size of raw slip profile + randomizer = RandomizerLA( + eq_magnitude=self.eq_magnitude, + total_length=self.total_length, + dx=dx_points, + ) + total_length_m = self.total_length.value + dx_points_m = dx_points.value + x_pts = numpy.arange(-0.5*total_length_m, +0.5*(total_length_m+dx_points_m), dx_points_m) + for i in range(MAX_ITERATIONS): + # Iterate until we find slip profile that is nearly zero at the ends + slip_pts = randomizer.create(x_pts) + if slip_pts[0] < END_TOLERANCE and numpy.sum(slip_pts == 0.0) < (1.0-ZERO_TOLERANCE)*len(slip_pts): + break + else: + print("Failed to generated slip distribution.") + + # Apply taper to force slip profile to zero at the ends. + taper = Taper( + total_length=self.total_length, + taper_length=self.taper_length, + ) + taper.apply(x_pts, slip_pts) + + # Fit spline to slip profile + dx_spline_m = self.dx.value + x = numpy.arange(-0.5*total_length_m, +0.5*(total_length_m+dx_spline_m), dx_spline_m) + spline = scipy.interpolate.CubicSpline(x_pts, slip_pts) + slip_spline = spline(x) + slip_spline[0] = 0.0 + slip_spline[-1] = 0.0 + slip_spline[slip_spline < 0.0] = 0.0 + return (x, slip_spline) + + +class SpatialDBWriter: + """Object for writing rupture information to spatial database file. + """ + + @staticmethod + def write(filename: str, y: numpy.ndarray, slip: numpy.ndarray): + """Write rupture information to SimpleGridDB ASCII file. + + Args: + filename: Name of spatial database file. + y: y coordinate (m) + slip: Slip (m) along fault + """ + from spatialdata.spatialdb.SimpleGridAscii import SimpleGridAscii + from spatialdata.geocoords.CSCart import CSCart + + DOMAIN_Y = 150.0*km + + writer = SimpleGridAscii() + writer.filename = filename + + # Add points to encompass entire fault (regions beyond rupture) + y_ext = numpy.concatenate(([-0.5*DOMAIN_Y.value], y, [+0.5*DOMAIN_Y.value])) + slip_ext = numpy.concatenate(([0.0], slip, [0.0])) + + cs = CSCart() + cs.spaceDim = 2 + cs._configure() + points = numpy.zeros((len(y_ext), 2)) + points[:,1] = y_ext + + data = { + "points": points, + 'x': numpy.array([0]), + 'y': y_ext, + 'z': numpy.array([0]), + "coordsys": cs, + "data_dim": 1, + "values": [{ + "name": "final_slip_left_lateral", + "units": "m", + "data": slip_ext, + },{ + "name": "final_slip_opening", + "units": "m", + "data": 0*slip_ext, + },{ + "name": "initiation_time", + "units": "s", + "data": 0*slip_ext, + }] + } + writer.write(data) + + +class RawWriter: + """Write slip profile to ASCII file for easy plotting. + """ + + @staticmethod + def write(filename: str, x: numpy.ndarray, slip: numpy.ndarray): + """Write rupture information to SimpleGridDB ASCII file. + + Args: + filename: Name of spatial database file. + x: Along-fault coordinate (m) + slip: Slip (m) along fault + """ + data = numpy.stack((x, slip)).T + numpy.savetxt(filename, data, fmt=("%8.1f", "%5.3f")) + + +class Randomizer(abc.ABC): + """Abstract base class for generating random distribution. + """ + SHEAR_MODULUS = 3.3e+10 # Pa + SEED = 234 + + def __init__(self, eq_magnitude: float, total_length: float, dx: float): + """Constructor. + + Args: + eq_magnitude: Earthquake magnitude. + total_length: Total length of rupture. + dx: Discretization size for slip profile along fault. + """ + self.eq_magnitude = eq_magnitude + self.total_length = total_length + self.dx = dx + numpy.random.seed(self.SEED) + + @staticmethod + def _inverse_fft(amplitude: numpy.ndarray, phase: numpy.ndarray) -> numpy.ndarray: + """Compute inverse FFT to get slip profile from amplitude and phase. + + Args: + amplitude: Slip amplitude. + phase: Slip phase. + + Returns: + Slip profile. + """ + amplitudeFFT = amplitude * (numpy.cos(phase) + numpy.sin(phase)*complex(0,1)) + return numpy.real(numpy.fft.ifft(amplitudeFFT)) + + @staticmethod + def _avg_slip(eq_magnitude: float) -> float: + """Compute average slip given earthquake magnitude. + + Args: + eq_magnitude: Earthquake magnitude. + + Returns: + Average slip (m). + """ + area = 10**(0.8*(eq_magnitude - 3.30)) + area *= 1.0e+6 # km**2 -> m**2 + seismic_moment = 10**(1.5*(eq_magnitude+10.7)-7) + avg_slip = seismic_moment / (area * Randomizer.SHEAR_MODULUS) + return avg_slip + + @staticmethod + def _correlation_coef(eq_magnitude: float) -> float: + """Compute correlation coefficient. + + Args: + eq_magnitude: Earthquake magnitude. + + Returns: + Correlation coefficient (m). + """ + return 1*km * 10**(0.5*eq_magnitude - 2.5) + + +class RandomizerLA(Randomizer): + """Random slip profile based on Lavrentiadis and Abrahamson + (2019, doi: 10.1785/0120180252). + + We use a slightly larger value for phi_0. + """ + + Np = 1.24 + #PHI0 = 0.265 # Original value used by Lavrentiadis and Abrahamson + PHI0 = 0.35 # Modified value + + def create(self, x: numpy.ndarray) -> numpy.ndarray: + """Create 1D slip profile. + + Args: + x: Along-fault coordinate. + + Returns: + Slip profile. + """ + mag = self._create_amplitude(x) + phase = self._create_phase(x) + + slip = numpy.abs(self._inverse_fft(mag, phase)) + i_min = numpy.argmin(slip) + slip = numpy.concatenate((slip[i_min:], slip[:i_min])) + return slip + + def _create_amplitude(self, x: numpy.ndarray) -> numpy.ndarray: + """Generate slip amplitude. + + Args: + x: Along-fault coordinate. + + Returns: + Slip amplitude. + """ + avg_slip_m = self._avg_slip(self.eq_magnitude) + + kx = numpy.fft.fftfreq(len(x), self.dx / km) + k = numpy.abs(kx) + kc = self._kc() + scale0 = avg_slip_m * len(x) + scale = scale0 / numpy.sqrt(1.0+(k/kc)**(2*self.Np)) + + amplitude = scale * 10**(numpy.random.normal(loc=0.0, scale=self.PHI0, size=len(scale))) + amplitude[k==0] = scale0 + return amplitude + + def _create_phase(self, x: numpy.ndarray) -> numpy.ndarray: + """Generate slip phase. + + Args: + x: Along-fault coordinate. + + Returns: + Slip phase. + """ + total_length_km = self.total_length / km + dx_km = self.dx / km + + mu = -total_length_km * math.pi + phase_der = numpy.random.logistic(loc=mu, scale=self._s(), size=len(x)) + + dk = 1.0 / (dx_km * len(x)) + phase = scipy.integrate.cumulative_simpson(phase_der, dx=dk, initial=0.0) + phase = phase % (2.0*math.pi) + return phase + + def _kc(self) -> float: + """Compute kc parameter. + + Returns: + kc parameter. + """ + c1 = -2.03 + c2 = -1.0 + c3 = 1.6 + total_length_km = self.total_length / km + return 10**(c1 + c2*(math.log10(total_length_km) - c3)) + + def _s(self) -> float: + """Compute asa parameter. + + Returns: + `s` parameter. + """ + d1 = 1.49 + d2 = 1.0 + d3 = 1.6 + total_length_km = self.total_length / km + return 10**(d1 + d2*(math.log10(total_length_km) - d3)) + + +class Taper: + """Object for applying linear taper at ends of slip profile. + """ + + def __init__(self, total_length: float, taper_length: float): + """Constructor. + + Args: + total_length: Total rupture length. + taper_length: Length of linear taper at each end. + """ + self.total_length = total_length + self.taper_length = taper_length + + def apply(self, x: numpy.ndarray, slip: numpy.ndarray): + """Apply linear taper at ends of slip profile. + + Args: + x: Along-fault coordinate. + slip: Slip profile to apply taper to. + """ + l_taper = self.taper_length.value + maskL = x <= x[0] + l_taper + maskR = x >= x[-1] - l_taper + taper = numpy.logical_and(~maskL, ~maskR) + maskL * (x-x[0]) / l_taper + maskR * (x[-1] - x) / l_taper + slip *= taper + + +if __name__ == "__main__": + cli() diff --git a/examples/strikeslip-2d/invert_slip.py b/examples/strikeslip-2d/invert_slip.py index b1a3e2a9be..f5b3aa3d4a 100755 --- a/examples/strikeslip-2d/invert_slip.py +++ b/examples/strikeslip-2d/invert_slip.py @@ -11,40 +11,64 @@ consistent ordering. """ -# Import argparse Python module (standard Python) -import argparse +import pathlib # Import numpy and h5py modules (included in PyLith installation) import numpy import h5py +OUTPUT_DIR = pathlib.Path("output") + +def cli(): + """Command line interface. + """ + import argparse + parser = argparse.ArgumentParser() + + parser.add_argument("--impulse-data", action="store", type=str, dest="filename_fault", default="step05_greensfns-fault.h5", help="Fault HDF5 data file from Green's function simulation.") + parser.add_argument("--impulse-responses", action="store", type=str, dest="filename_responses", default="step05_greensfns-gnss_stations.h5", help="Station HDF5 data file from Green's function simulation.") + parser.add_argument("--observed-data", action="store", type=str, dest="filename_observed", default="step04_varslip-gnss_stations.h5", help="Station HDF5 data file from variable slip simulation.") + parser.add_argument("--penalties", action="store", type=str, dest="penalties", default="0.02,0.1,0.4", help="Comma separated list of penalties.") + parser.add_argument("--output", action="store", type=str, dest="filename_output", default="step06_inversion-results.txt", help="Name of output file with inversion results.") + + args = parser.parse_args() + app = InvertSlipApp(output_dir=OUTPUT_DIR) + app.run( + filename_fault=args.filename_fault, + filename_responses=args.filename_responses, + filename_observed=args.filename_observed, + filename_output=args.filename_output, + penalties=[float(p) for p in args.penalties.split(",")], + ) + + class InvertSlipApp: """Application to invert for fault slip using PyLith-generated Green's functions. """ - def __init__(self): - self.filename_fault = "output/step05_greensfns-fault.h5" - self.filename_responses = "output/step05_greensfns-gnss_stations.h5" - self.filename_observed = "output/step04_varslip-gnss_stations.h5" - self.filename_output = "output/step06_inversion-results.txt" - self.penalties = [0.01, 0.1, 1.0] - - def main(self): - """Entry point for running application. + def __init__(self, output_dir: str): + """Constructor + + Args: + output_dir: Directory with simulation output. """ - args = self._parse_command_line() + self.output_dir = output_dir - self.get_fault_impulses(args.filename_fault) - self.get_station_responses(args.filename_responses) - self.get_station_observed(args.filename_observed) + def run(self, filename_fault: str, filename_responses: str, filename_observed: str, filename_output: str, penalties: list): + """Entry point for running application. + """ + self._get_fault_impulses(self.output_dir / filename_fault) + self._get_station_responses(self.output_dir / filename_responses) + self._get_station_observed(self.output_dir / filename_observed) - self.penalties = list(map(float, args.penalties.split(","))) - results = self.invert() - self.write_results(self.filename_output, results) + self.penalties = penalties + results = self._invert() + self.write_results(self.output_dir / filename_output, results) - def get_fault_impulses(self, filename): + def _get_fault_impulses(self, filename: str): """Get coordinates, amplitude, and order of impulses. Fault points are sorted by y coordinate. - :param filename: Name of HDF5 file with fault data from PyLith Green's function simulation (Step 5). + Args: + filename: Name of HDF5 file with fault data from PyLith Green's function simulation (Step 5). """ h5 = h5py.File(filename, "r") y = h5['geometry/vertices'][:,1] @@ -57,11 +81,12 @@ def get_fault_impulses(self, filename): self.impulse_y = y[reorder] self.impulse_slip = slip[:,reorder] - def get_station_responses(self, filename): + def _get_station_responses(self, filename): """ Get coordinates and displacements at stations for Green's function responses. - :param filename: Name of HDF5 file with point data from PyLith Green's function simulation (Step 5_). + Args: + filename: Name of HDF5 file with point data from PyLith Green's function simulation (Step 5_). """ h5 = h5py.File(filename, "r") xy = h5['geometry/vertices'][:,0:2] @@ -72,11 +97,12 @@ def get_station_responses(self, filename): reorder = numpy.argsort(xy[:,1]) self.station_responses = displacement[:,reorder,:] - def get_station_observed(self, filename): + def _get_station_observed(self, filename): """ Get coordinates and displacements at stations for fake observations. - :param filename: Name of HDF5 file with point data from PyLith forward simulation (Step 4). + Args: + filename: Name of HDF5 file with point data from PyLith forward simulation (Step 4). """ h5 = h5py.File(filename, "r") xy = h5['geometry/vertices'][:,0:2] @@ -87,7 +113,7 @@ def get_station_observed(self, filename): reorder = numpy.argsort(xy[:,1]) self.station_observed = displacement[:,reorder,:] - def invert(self): + def _invert(self) -> numpy.ndarray: """Invert observations for amplitude of impulses and fault slip. """ # Determine matrix sizes and set up A-matrix. @@ -129,11 +155,12 @@ def invert(self): print(f"Residual norm: {residual_norm}") return results - def write_results(self, filename, results): + def write_results(self, filename: str, results: numpy.ndarray): """Write inversion results to file. - :param filename: Name of output file. - :param results: Inversion results as Numpy array. + Args: + filename: Name of output file. + results: Inversion results as Numpy array. """ header = "# y" for penalty in self.penalties: @@ -144,22 +171,9 @@ def write_results(self, filename, results): fout.write(header) numpy.savetxt(fout, results, fmt="%14.6e") - def _parse_command_line(self): - """Parse command line arguments. - - :returns: Command line arugment information as argparse.Namespace. - """ - parser = argparse.ArgumentParser() - - parser.add_argument("--impulse-data", action="store", type=str, dest="filename_fault", default=self.filename_fault, help="Fault HDF5 data file from Green's function simulation.") - parser.add_argument("--impulse-responses", action="store", type=str, dest="filename_responses", default=self.filename_responses, help="Station HDF5 data file from Green's function simulation.") - parser.add_argument("--observed-data", action="store", type=str, dest="filename_observed", default=self.filename_observed, help="Station HDF5 data file from variable slip simulation.") - parser.add_argument("--penalties", action="store", type=str, dest="penalties", default="0.01,0.1,1.0", help="Comma separated list of penalties.") - parser.add_argument("--output", action="store", type=str, dest="filename_output", default=self.filename_output, help="Name of output file with inversion results.") - return parser.parse_args() if __name__ == "__main__": - InvertSlipApp().main() + cli() # End of file diff --git a/examples/strikeslip-2d/slip_variable.spatialdb b/examples/strikeslip-2d/slip_variable.spatialdb index 1180c4d334..ef864f28ae 100644 --- a/examples/strikeslip-2d/slip_variable.spatialdb +++ b/examples/strikeslip-2d/slip_variable.spatialdb @@ -1,33 +1,424 @@ -// This spatial database specifies the distribution of slip on the -// fault surface for Step 4 (forward simulation to generate fake observations). -// The slip extends from -20 <= y <= 20 km. -#SPATIAL.ascii 1 -SimpleDB { - num-values = 3 - value-names = final_slip_left_lateral final_slip_opening initiation_time - value-units = cm cm year - num-locs = 11 - data-dim = 1 // Data is specified along a line. +#SPATIAL_GRID.ascii 1 +SimpleGridDB { + num-x = 1 + num-y = 403 + num-z = 0 space-dim = 2 + num-values = 3 + value-names = final_slip_left_lateral final_slip_opening initiation_time + value-units = m m s cs-data = cartesian { - to-meters = 1.0e+3 // Specify coordinates in km for convenience. - space-dim = 2 - } // cs-data -} // SimpleDB -// Columns are -// (1) x coordinate (km) -// (2) y coordinate (km) -// (3) left-lateral slip (cm) -// (4) fault opening (cm) -// (5) slip time relative to origin time (year) -0.0 99.0 0.0 0.0 0.0 -0.0 20.0 0.0 0.0 0.0 -0.0 15.0 30.0 0.0 0.0 -0.0 10.0 40.0 0.0 0.0 -0.0 5.0 20.0 0.0 0.0 -0.0 0.0 60.0 0.0 0.0 -0.0 -5.0 80.0 0.0 0.0 -0.0 -10.0 30.0 0.0 0.0 -0.0 -15.0 10.0 0.0 0.0 -0.0 -20.0 0.0 0.0 0.0 -0.0 -99.0 0.0 0.0 0.0 + to-meters = 1 + space-dim = 2 +} +} +// x-coordinates + 0.000000e+00 +// y-coordinates + -7.500000e+04 -2.000000e+04 -1.990000e+04 -1.980000e+04 -1.970000e+04 -1.960000e+04 -1.950000e+04 -1.940000e+04 -1.930000e+04 -1.920000e+04 -1.910000e+04 -1.900000e+04 -1.890000e+04 -1.880000e+04 -1.870000e+04 -1.860000e+04 -1.850000e+04 -1.840000e+04 -1.830000e+04 -1.820000e+04 -1.810000e+04 -1.800000e+04 -1.790000e+04 -1.780000e+04 -1.770000e+04 -1.760000e+04 -1.750000e+04 -1.740000e+04 -1.730000e+04 -1.720000e+04 -1.710000e+04 -1.700000e+04 -1.690000e+04 -1.680000e+04 -1.670000e+04 -1.660000e+04 -1.650000e+04 -1.640000e+04 -1.630000e+04 -1.620000e+04 -1.610000e+04 -1.600000e+04 -1.590000e+04 -1.580000e+04 -1.570000e+04 -1.560000e+04 -1.550000e+04 -1.540000e+04 -1.530000e+04 -1.520000e+04 -1.510000e+04 -1.500000e+04 -1.490000e+04 -1.480000e+04 -1.470000e+04 -1.460000e+04 -1.450000e+04 -1.440000e+04 -1.430000e+04 -1.420000e+04 -1.410000e+04 -1.400000e+04 -1.390000e+04 -1.380000e+04 -1.370000e+04 -1.360000e+04 -1.350000e+04 -1.340000e+04 -1.330000e+04 -1.320000e+04 -1.310000e+04 -1.300000e+04 -1.290000e+04 -1.280000e+04 -1.270000e+04 -1.260000e+04 -1.250000e+04 -1.240000e+04 -1.230000e+04 -1.220000e+04 -1.210000e+04 -1.200000e+04 -1.190000e+04 -1.180000e+04 -1.170000e+04 -1.160000e+04 -1.150000e+04 -1.140000e+04 -1.130000e+04 -1.120000e+04 -1.110000e+04 -1.100000e+04 -1.090000e+04 -1.080000e+04 -1.070000e+04 -1.060000e+04 -1.050000e+04 -1.040000e+04 -1.030000e+04 -1.020000e+04 -1.010000e+04 -1.000000e+04 -9.900000e+03 -9.800000e+03 -9.700000e+03 -9.600000e+03 -9.500000e+03 -9.400000e+03 -9.300000e+03 -9.200000e+03 -9.100000e+03 -9.000000e+03 -8.900000e+03 -8.800000e+03 -8.700000e+03 -8.600000e+03 -8.500000e+03 -8.400000e+03 -8.300000e+03 -8.200000e+03 -8.100000e+03 -8.000000e+03 -7.900000e+03 -7.800000e+03 -7.700000e+03 -7.600000e+03 -7.500000e+03 -7.400000e+03 -7.300000e+03 -7.200000e+03 -7.100000e+03 -7.000000e+03 -6.900000e+03 -6.800000e+03 -6.700000e+03 -6.600000e+03 -6.500000e+03 -6.400000e+03 -6.300000e+03 -6.200000e+03 -6.100000e+03 -6.000000e+03 -5.900000e+03 -5.800000e+03 -5.700000e+03 -5.600000e+03 -5.500000e+03 -5.400000e+03 -5.300000e+03 -5.200000e+03 -5.100000e+03 -5.000000e+03 -4.900000e+03 -4.800000e+03 -4.700000e+03 -4.600000e+03 -4.500000e+03 -4.400000e+03 -4.300000e+03 -4.200000e+03 -4.100000e+03 -4.000000e+03 -3.900000e+03 -3.800000e+03 -3.700000e+03 -3.600000e+03 -3.500000e+03 -3.400000e+03 -3.300000e+03 -3.200000e+03 -3.100000e+03 -3.000000e+03 -2.900000e+03 -2.800000e+03 -2.700000e+03 -2.600000e+03 -2.500000e+03 -2.400000e+03 -2.300000e+03 -2.200000e+03 -2.100000e+03 -2.000000e+03 -1.900000e+03 -1.800000e+03 -1.700000e+03 -1.600000e+03 -1.500000e+03 -1.400000e+03 -1.300000e+03 -1.200000e+03 -1.100000e+03 -1.000000e+03 -9.000000e+02 -8.000000e+02 -7.000000e+02 -6.000000e+02 -5.000000e+02 -4.000000e+02 -3.000000e+02 -2.000000e+02 -1.000000e+02 0.000000e+00 1.000000e+02 2.000000e+02 3.000000e+02 4.000000e+02 5.000000e+02 6.000000e+02 7.000000e+02 8.000000e+02 9.000000e+02 1.000000e+03 1.100000e+03 1.200000e+03 1.300000e+03 1.400000e+03 1.500000e+03 1.600000e+03 1.700000e+03 1.800000e+03 1.900000e+03 2.000000e+03 2.100000e+03 2.200000e+03 2.300000e+03 2.400000e+03 2.500000e+03 2.600000e+03 2.700000e+03 2.800000e+03 2.900000e+03 3.000000e+03 3.100000e+03 3.200000e+03 3.300000e+03 3.400000e+03 3.500000e+03 3.600000e+03 3.700000e+03 3.800000e+03 3.900000e+03 4.000000e+03 4.100000e+03 4.200000e+03 4.300000e+03 4.400000e+03 4.500000e+03 4.600000e+03 4.700000e+03 4.800000e+03 4.900000e+03 5.000000e+03 5.100000e+03 5.200000e+03 5.300000e+03 5.400000e+03 5.500000e+03 5.600000e+03 5.700000e+03 5.800000e+03 5.900000e+03 6.000000e+03 6.100000e+03 6.200000e+03 6.300000e+03 6.400000e+03 6.500000e+03 6.600000e+03 6.700000e+03 6.800000e+03 6.900000e+03 7.000000e+03 7.100000e+03 7.200000e+03 7.300000e+03 7.400000e+03 7.500000e+03 7.600000e+03 7.700000e+03 7.800000e+03 7.900000e+03 8.000000e+03 8.100000e+03 8.200000e+03 8.300000e+03 8.400000e+03 8.500000e+03 8.600000e+03 8.700000e+03 8.800000e+03 8.900000e+03 9.000000e+03 9.100000e+03 9.200000e+03 9.300000e+03 9.400000e+03 9.500000e+03 9.600000e+03 9.700000e+03 9.800000e+03 9.900000e+03 1.000000e+04 1.010000e+04 1.020000e+04 1.030000e+04 1.040000e+04 1.050000e+04 1.060000e+04 1.070000e+04 1.080000e+04 1.090000e+04 1.100000e+04 1.110000e+04 1.120000e+04 1.130000e+04 1.140000e+04 1.150000e+04 1.160000e+04 1.170000e+04 1.180000e+04 1.190000e+04 1.200000e+04 1.210000e+04 1.220000e+04 1.230000e+04 1.240000e+04 1.250000e+04 1.260000e+04 1.270000e+04 1.280000e+04 1.290000e+04 1.300000e+04 1.310000e+04 1.320000e+04 1.330000e+04 1.340000e+04 1.350000e+04 1.360000e+04 1.370000e+04 1.380000e+04 1.390000e+04 1.400000e+04 1.410000e+04 1.420000e+04 1.430000e+04 1.440000e+04 1.450000e+04 1.460000e+04 1.470000e+04 1.480000e+04 1.490000e+04 1.500000e+04 1.510000e+04 1.520000e+04 1.530000e+04 1.540000e+04 1.550000e+04 1.560000e+04 1.570000e+04 1.580000e+04 1.590000e+04 1.600000e+04 1.610000e+04 1.620000e+04 1.630000e+04 1.640000e+04 1.650000e+04 1.660000e+04 1.670000e+04 1.680000e+04 1.690000e+04 1.700000e+04 1.710000e+04 1.720000e+04 1.730000e+04 1.740000e+04 1.750000e+04 1.760000e+04 1.770000e+04 1.780000e+04 1.790000e+04 1.800000e+04 1.810000e+04 1.820000e+04 1.830000e+04 1.840000e+04 1.850000e+04 1.860000e+04 1.870000e+04 1.880000e+04 1.890000e+04 1.900000e+04 1.910000e+04 1.920000e+04 1.930000e+04 1.940000e+04 1.950000e+04 1.960000e+04 1.970000e+04 1.980000e+04 1.990000e+04 2.000000e+04 7.500000e+04 +// z-coordinates + +// data + 0.000000e+00 -7.500000e+04 0.000000e+00 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.000000e+04 0.000000e+00 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.990000e+04 0.000000e+00 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.980000e+04 0.000000e+00 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.970000e+04 2.412684e-03 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.960000e+04 2.256749e-02 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.950000e+04 4.867393e-02 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.940000e+04 7.849781e-02 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.930000e+04 1.098049e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.920000e+04 1.403611e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.910000e+04 1.682456e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.900000e+04 1.927916e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.890000e+04 2.136458e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.880000e+04 2.304548e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.870000e+04 2.433468e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.860000e+04 2.543759e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.850000e+04 2.660779e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.840000e+04 2.809884e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.830000e+04 3.005525e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.820000e+04 3.218530e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.810000e+04 3.408820e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.800000e+04 3.536317e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.790000e+04 3.577180e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.780000e+04 3.572513e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.770000e+04 3.579658e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.760000e+04 3.655955e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.750000e+04 3.843875e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.740000e+04 4.126400e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.730000e+04 4.471640e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.720000e+04 4.847705e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.710000e+04 5.221622e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.700000e+04 5.556079e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.690000e+04 5.812681e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.680000e+04 5.953032e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.670000e+04 5.960158e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.660000e+04 5.902772e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.650000e+04 5.871010e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.640000e+04 5.955007e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.630000e+04 6.215960e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.620000e+04 6.599316e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.610000e+04 7.021583e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.600000e+04 7.399272e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.590000e+04 7.665415e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.580000e+04 7.819146e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.570000e+04 7.876126e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.560000e+04 7.852013e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.550000e+04 7.765686e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.540000e+04 7.648898e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.530000e+04 7.536622e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.520000e+04 7.463831e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.510000e+04 7.459639e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.500000e+04 7.529715e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.490000e+04 7.673874e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.480000e+04 7.891925e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.470000e+04 8.171729e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.460000e+04 8.453338e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.450000e+04 8.664853e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.440000e+04 8.734374e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.430000e+04 8.615923e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.420000e+04 8.367204e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.410000e+04 8.071842e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.400000e+04 7.813462e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.390000e+04 7.655544e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.380000e+04 7.580990e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.370000e+04 7.552559e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.360000e+04 7.533008e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.350000e+04 7.495864e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.340000e+04 7.457725e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.330000e+04 7.445958e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.320000e+04 7.487930e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.310000e+04 7.599690e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.300000e+04 7.752009e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.290000e+04 7.904341e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.280000e+04 8.016140e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.270000e+04 8.054088e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.260000e+04 8.013786e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.250000e+04 7.898066e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.240000e+04 7.709756e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.230000e+04 7.458569e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.220000e+04 7.181742e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.210000e+04 6.923394e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.200000e+04 6.727643e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.190000e+04 6.625286e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.180000e+04 6.593831e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.170000e+04 6.597463e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.160000e+04 6.600367e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.150000e+04 6.575607e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.140000e+04 6.531759e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.130000e+04 6.486277e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.120000e+04 6.456617e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.110000e+04 6.451082e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.100000e+04 6.441376e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.090000e+04 6.390052e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.080000e+04 6.259663e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.070000e+04 6.027037e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.060000e+04 5.726102e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.050000e+04 5.405060e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.040000e+04 5.112111e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.030000e+04 4.881081e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.020000e+04 4.688279e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.010000e+04 4.495638e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.000000e+04 4.265090e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.900000e+03 3.973335e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.800000e+03 3.656145e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.700000e+03 3.364061e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.600000e+03 3.147624e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.500000e+03 3.041734e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.400000e+03 3.018743e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.300000e+03 3.035361e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.200000e+03 3.048298e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.100000e+03 3.026867e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.000000e+03 2.990775e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.900000e+03 2.972333e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.800000e+03 3.003848e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.700000e+03 3.105374e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.600000e+03 3.247942e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.500000e+03 3.390328e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.400000e+03 3.491309e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.300000e+03 3.520572e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.200000e+03 3.491455e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.100000e+03 3.428207e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.000000e+03 3.355079e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.900000e+03 3.293136e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.800000e+03 3.250702e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.700000e+03 3.232917e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.600000e+03 3.244921e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.500000e+03 3.288110e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.400000e+03 3.348907e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.300000e+03 3.409993e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.200000e+03 3.454046e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.100000e+03 3.468976e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.000000e+03 3.463594e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.900000e+03 3.451944e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.800000e+03 3.448065e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.700000e+03 3.462225e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.600000e+03 3.489599e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.500000e+03 3.521587e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.400000e+03 3.549590e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.300000e+03 3.567982e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.200000e+03 3.583036e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.100000e+03 3.603998e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.000000e+03 3.640112e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.900000e+03 3.696177e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.800000e+03 3.759192e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.700000e+03 3.811710e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.600000e+03 3.836282e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.500000e+03 3.822439e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.400000e+03 3.787627e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.300000e+03 3.756270e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.200000e+03 3.752794e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.100000e+03 3.791992e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.000000e+03 3.850131e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.900000e+03 3.893848e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.800000e+03 3.889777e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.700000e+03 3.817088e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.600000e+03 3.705073e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.500000e+03 3.595561e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.400000e+03 3.530375e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.300000e+03 3.541422e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.200000e+03 3.620918e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.100000e+03 3.751156e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.000000e+03 3.914430e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.900000e+03 4.092948e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.800000e+03 4.268563e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.700000e+03 4.423039e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.600000e+03 4.538143e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.500000e+03 4.602813e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.400000e+03 4.634682e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.300000e+03 4.658553e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.200000e+03 4.699234e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.100000e+03 4.775196e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.000000e+03 4.879574e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.900000e+03 4.999171e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.800000e+03 5.120790e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.700000e+03 5.233784e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.600000e+03 5.337717e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.500000e+03 5.434702e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.400000e+03 5.526852e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.300000e+03 5.616372e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.200000e+03 5.705822e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.100000e+03 5.797851e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.000000e+03 5.895108e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.900000e+03 5.998409e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.800000e+03 6.101233e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.700000e+03 6.195224e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.600000e+03 6.272026e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.500000e+03 6.325783e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.400000e+03 6.360630e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.300000e+03 6.383200e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.200000e+03 6.400127e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.100000e+03 6.416080e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.000000e+03 6.427876e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -9.000000e+02 6.430370e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -8.000000e+02 6.418415e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -7.000000e+02 6.387166e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -6.000000e+02 6.332977e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -5.000000e+02 6.252501e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -4.000000e+02 6.142392e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -3.000000e+02 6.003878e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -2.000000e+02 5.856475e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 -1.000000e+02 5.724272e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 0.000000e+00 5.631357e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.000000e+02 5.595985e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.000000e+02 5.613062e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.000000e+02 5.671661e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.000000e+02 5.760856e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.000000e+02 5.869534e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.000000e+02 5.985844e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.000000e+02 6.097753e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.000000e+02 6.193226e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.000000e+02 6.264477e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.000000e+03 6.320722e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.100000e+03 6.375423e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.200000e+03 6.442043e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.300000e+03 6.529204e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.400000e+03 6.626162e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.500000e+03 6.717328e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.600000e+03 6.787116e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.700000e+03 6.825109e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.800000e+03 6.841578e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.900000e+03 6.851964e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.000000e+03 6.871706e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.100000e+03 6.913161e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.200000e+03 6.976341e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.300000e+03 7.058170e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.400000e+03 7.155576e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.500000e+03 7.261780e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.600000e+03 7.355185e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.700000e+03 7.410489e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.800000e+03 7.402391e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 2.900000e+03 7.316842e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.000000e+03 7.184801e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.100000e+03 7.048480e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.200000e+03 6.950088e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.300000e+03 6.919010e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.400000e+03 6.933313e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.500000e+03 6.958235e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.600000e+03 6.959015e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.700000e+03 6.910968e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.800000e+03 6.829714e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 3.900000e+03 6.740951e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.000000e+03 6.670375e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.100000e+03 6.635449e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.200000e+03 6.620703e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.300000e+03 6.602436e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.400000e+03 6.556943e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.500000e+03 6.468512e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.600000e+03 6.353387e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.700000e+03 6.235803e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.800000e+03 6.139996e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 4.900000e+03 6.082016e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.000000e+03 6.045185e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.100000e+03 6.004639e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.200000e+03 5.935514e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.300000e+03 5.823580e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.400000e+03 5.697130e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.500000e+03 5.595090e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.600000e+03 5.556385e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.700000e+03 5.606441e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.800000e+03 5.716692e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 5.900000e+03 5.845071e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.000000e+03 5.949512e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.100000e+03 5.998187e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.200000e+03 6.000212e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.300000e+03 5.974942e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.400000e+03 5.941732e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.500000e+03 5.917137e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.600000e+03 5.906526e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.700000e+03 5.912469e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.800000e+03 5.937534e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 6.900000e+03 5.983378e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.000000e+03 6.047993e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.100000e+03 6.128457e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.200000e+03 6.221850e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.300000e+03 6.325833e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.400000e+03 6.440407e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.500000e+03 6.566156e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.600000e+03 6.703664e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.700000e+03 6.851582e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.800000e+03 7.000816e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 7.900000e+03 7.140342e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.000000e+03 7.259133e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.100000e+03 7.349952e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.200000e+03 7.420721e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.300000e+03 7.483151e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.400000e+03 7.548955e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.500000e+03 7.622325e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.600000e+03 7.677374e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.700000e+03 7.680695e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.800000e+03 7.598884e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 8.900000e+03 7.411567e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.000000e+03 7.150500e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.100000e+03 6.860474e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.200000e+03 6.586278e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.300000e+03 6.364743e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.400000e+03 6.200865e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.500000e+03 6.091678e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.600000e+03 6.034221e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.700000e+03 6.025935e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.800000e+03 6.065898e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 9.900000e+03 6.153590e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.000000e+04 6.288495e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.010000e+04 6.464937e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.020000e+04 6.656608e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.030000e+04 6.832041e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.040000e+04 6.959767e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.050000e+04 7.020821e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.060000e+04 7.046232e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.070000e+04 7.079531e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.080000e+04 7.164250e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.090000e+04 7.331307e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.100000e+04 7.561178e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.110000e+04 7.821728e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.120000e+04 8.080822e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.130000e+04 8.310616e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.140000e+04 8.500442e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.150000e+04 8.643920e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.160000e+04 8.734674e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.170000e+04 8.770231e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.180000e+04 8.763741e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.190000e+04 8.732262e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.200000e+04 8.692847e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.210000e+04 8.657004e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.220000e+04 8.614041e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.230000e+04 8.547717e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.240000e+04 8.441791e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.250000e+04 8.283698e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.260000e+04 8.075575e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.270000e+04 7.823238e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.280000e+04 7.532500e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.290000e+04 7.212912e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.300000e+04 6.888964e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.310000e+04 6.588886e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.320000e+04 6.340903e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.330000e+04 6.164106e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.340000e+04 6.041035e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.350000e+04 5.945089e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.360000e+04 5.849670e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.370000e+04 5.732284e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.380000e+04 5.586845e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.390000e+04 5.411375e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.400000e+04 5.203892e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.410000e+04 4.966009e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.420000e+04 4.713706e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.430000e+04 4.466558e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.440000e+04 4.244137e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.450000e+04 4.063868e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.460000e+04 3.934576e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.470000e+04 3.862939e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.480000e+04 3.855634e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.490000e+04 3.909772e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.500000e+04 3.984205e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.510000e+04 4.028217e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.520000e+04 3.991094e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.530000e+04 3.838987e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.540000e+04 3.605505e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.550000e+04 3.341123e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.560000e+04 3.096315e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.570000e+04 2.909893e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.580000e+04 2.774015e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.590000e+04 2.669174e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.600000e+04 2.575866e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.610000e+04 2.481058e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.620000e+04 2.397616e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.630000e+04 2.344880e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.640000e+04 2.342190e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.650000e+04 2.400258e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.660000e+04 2.495287e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.670000e+04 2.594855e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.680000e+04 2.666536e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.690000e+04 2.688999e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.700000e+04 2.685271e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.710000e+04 2.689472e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.720000e+04 2.735718e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.730000e+04 2.848830e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.740000e+04 3.016425e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.750000e+04 3.216823e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.760000e+04 3.428342e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.770000e+04 3.630299e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.780000e+04 3.806006e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.790000e+04 3.939771e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.800000e+04 4.015906e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.810000e+04 4.021254e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.820000e+04 3.952800e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.830000e+04 3.810066e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.840000e+04 3.592572e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.850000e+04 3.305635e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.860000e+04 2.977753e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.870000e+04 2.643223e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.880000e+04 2.336340e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.890000e+04 2.084238e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.900000e+04 1.885409e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.910000e+04 1.731183e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.920000e+04 1.612889e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.930000e+04 1.520061e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.940000e+04 1.435048e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.950000e+04 1.338403e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.960000e+04 1.210676e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.970000e+04 1.032420e-01 0.000000e+00 0.000000e+00 + 0.000000e+00 1.980000e+04 7.841873e-02 0.000000e+00 0.000000e+00 + 0.000000e+00 1.990000e+04 4.465299e-02 0.000000e+00 0.000000e+00 + 0.000000e+00 2.000000e+04 0.000000e+00 0.000000e+00 0.000000e+00 + 0.000000e+00 7.500000e+04 0.000000e+00 0.000000e+00 0.000000e+00 diff --git a/examples/strikeslip-2d/step04_varslip.cfg b/examples/strikeslip-2d/step04_varslip.cfg index 81e7cbc236..78762a868f 100644 --- a/examples/strikeslip-2d/step04_varslip.cfg +++ b/examples/strikeslip-2d/step04_varslip.cfg @@ -40,6 +40,12 @@ features = [ # output filenames. The default directory for output is 'output'. defaults.name = step04_varslip +# ---------------------------------------------------------------------- +# mesh_generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator] +refiner = pylith.topology.RefineUniform + # ---------------------------------------------------------------------- # problem # ---------------------------------------------------------------------- @@ -94,11 +100,15 @@ derived_subfields.cauchy_stress.basis_order = 1 # ---------------------------------------------------------------------- # fault # ---------------------------------------------------------------------- +# Refine output by a factor of 2**3=8 to capture higher order discretization. +[pylithapp.problem.interfaces.fault] +observers.observer.refine_levels = 3 + # Specify slip on the fault using a `SimpleDB` spatial database. [pylithapp.problem.interfaces.fault.eq_ruptures.rupture] -db_auxiliary_field = spatialdata.spatialdb.SimpleDB +db_auxiliary_field = spatialdata.spatialdb.SimpleGridDB db_auxiliary_field.description = Fault rupture auxiliary field spatial database -db_auxiliary_field.iohandler.filename = slip_variable.spatialdb +db_auxiliary_field.filename = slip_variable.spatialdb db_auxiliary_field.query_type = linear diff --git a/examples/strikeslip-2d/step05_greensfns.cfg b/examples/strikeslip-2d/step05_greensfns.cfg index 44e495cd28..1d607436c3 100644 --- a/examples/strikeslip-2d/step05_greensfns.cfg +++ b/examples/strikeslip-2d/step05_greensfns.cfg @@ -52,6 +52,7 @@ greensfns = 1 # ---------------------------------------------------------------------- [pylithapp.mesh_generator] refiner = pylith.topology.RefineUniform +refiner.levels = 1 # ---------------------------------------------------------------------- # problem diff --git a/examples/strikeslip-2d/viz/plot_catmip_results.py b/examples/strikeslip-2d/viz/plot_catmip_results.py index 684bd65040..67c275ed77 100755 --- a/examples/strikeslip-2d/viz/plot_catmip_results.py +++ b/examples/strikeslip-2d/viz/plot_catmip_results.py @@ -4,38 +4,64 @@ the true solution for Step 7 (CATMIP inversions). """ -# Import argparse and re (regular expressions) Python modules(standard Python) -import argparse +# Standard Python modules import pathlib -# Import numpy, h5py, and matplotlib modules (included in PyLith binary installation) +# Python modules included in PyLith binary installation import numpy import h5py import matplotlib.pyplot as pyplot +from pythia.pyre.units.length import km -class PlotApp: +OUTPUT_DIR = pathlib.Path("output") - FILENAME_IMPULSES = "output/step05_greensfns-fault.h5" - FILENAME_OBSERVED = "output/step04_varslip-fault.h5" - - COLOR_OBSERVED = "black" - COLOR_MODEL = "orange" - XLIM = (-25.0, 25.0) +FILENAME_IMPULSES = OUTPUT_DIR / "step05_greensfns-fault.h5" +FILENAME_PRESCRIBED = OUTPUT_DIR / "step04_varslip-fault.h5" +FILENAME_RAW = OUTPUT_DIR / "slip_variable.txt" - def __init__(self): - self.observed_coords = None - self.observed_slip = None - self.impulse_coords = None - self.impulse_slip = None +def cli(): + """Command line interface. + """ + import argparse - self.inversion_coefs = None - - def main(self, filename_theta: str, filename_observed: str=None, filename_impulses: str=None, show_plot: bool=False): - filename_observed = filename_observed or self.FILENAME_OBSERVED - filename_impulses = filename_impulses or self.FILENAME_IMPULSES - - self._load_observed(filename_observed) + parser = argparse.ArgumentParser() + parser.add_argument("--catmip-theta", action="store", dest="filename_theta", type=str, required=True, help="Filename of output from CATMIP inversion.") + parser.add_argument("--pylith-impulses", action="store", dest="filename_impulses", type=str, default=FILENAME_IMPULSES, help="Name of HDF5 file with fault slip inpulses from Green's functions simulation.") + parser.add_argument("--prescribed-slip", action="store", dest="filename_prescribed", type=str, default=FILENAME_PRESCRIBED, help="Name of HDF5 file for fault from prescribed slip simulation.") + parser.add_argument("--raw", action="store", dest="filename_raw", type=str, default=FILENAME_RAW, help="Name of ASCII file with raw slip profile.") + parser.add_argument("--no-gui", action="store_false", dest="show_plot", default=True, help="Do not display plot.") + + args = parser.parse_args() + PlotApp().run( + filename_prescribed=args.filename_prescribed, + filename_impulses=args.filename_impulses, + filename_theta=args.filename_theta, + filename_raw=args.filename_raw, + show_plot=args.show_plot, + ) + + +class PlotApp: + """Application to plot CATMIP inversion results. + """ + COLOR_RAW = "gray" + COLOR_OBSERVED = "black" + COLOR_MODEL = "orange" + XLIM = (-25.0, 35.0) + + def run(self, filename_theta: str, filename_prescribed: str, filename_impulses: str, filename_raw: str, show_plot: bool): + """Run plotting application. + + Args: + filename_theta: Filename of output from inversion. + filename_prescribed: Name of HDF5 file with station output with fake observations. + filename_raw: Name of ASCII file with raw slip values. + prescribed_only: Show only prescribed slip. + show_plot: Show plot window. + """ + self._load_observed(filename_prescribed) + self._load_raw(filename_raw) self._load_impulses(filename_impulses) self._load_inversion_results(filename_theta) @@ -45,9 +71,9 @@ def main(self, filename_theta: str, filename_observed: str=None, filename_impuls slip_median = self._calc_median() slip_stddev = self._calc_stddev() slip_minmax = self._calc_minmax() - self.plot(slip_median, slip_stddev, slip_minmax, filename_plot, show_plot) + self._plot(slip_median, slip_stddev, slip_minmax, filename_plot, show_plot) - def _load_observed(self, filename): + def _load_observed(self, filename: str): h5 = h5py.File(filename, "r") observed_coords = h5['geometry/vertices'][:] observed_slip = h5['vertex_fields/slip'][:,:,:].squeeze() @@ -58,7 +84,12 @@ def _load_observed(self, filename): self.observed_coords = observed_coords[reorder,:] self.observed_slip = observed_slip[reorder,:] - def _load_impulses(self, filename): + def _load_raw(self, filename: str): + data = numpy.loadtxt(filename) + self.raw_y = data[:,0] + self.raw_slip = data[:,1] + + def _load_impulses(self, filename: str): h5 = h5py.File(filename, "r") impulse_coords = h5['geometry/vertices'][:] impulse_slip = h5['vertex_fields/slip'][:,:,:].squeeze() @@ -69,41 +100,37 @@ def _load_impulses(self, filename): self.impulse_coords = impulse_coords[reorder,:] self.impulse_slip = impulse_slip[:,reorder,:] - def _load_inversion_results(self, filename): + def _load_inversion_results(self, filename: str): with open(filename, "rb") as fin: coefs = numpy.frombuffer(fin.read(), dtype=numpy.float64) nimpulses = self.impulse_slip.shape[0] self.inversion_coefs = coefs.reshape((nimpulses,-1)) - def _calc_median(self): - median_coefs = numpy.median(self.inversion_coefs, axis=1) - return _calc_slip(median_coefs) - - def _calc_median(self): + def _calc_median(self) -> numpy.ndarray: median_coefs = numpy.median(self.inversion_coefs, axis=1) return self._calc_slip(median_coefs) - def _calc_stddev(self): + def _calc_stddev(self) -> numpy.ndarray: median_coefs = numpy.median(self.inversion_coefs, axis=1) stddev_coefs = numpy.std(self.inversion_coefs, axis=1) low_slip = self._calc_slip(median_coefs - stddev_coefs) high_slip = self._calc_slip(median_coefs + stddev_coefs) return (low_slip, high_slip) - def _calc_minmax(self): + def _calc_minmax(self) -> tuple: min_coefs = numpy.min(self.inversion_coefs, axis=1) max_coefs = numpy.max(self.inversion_coefs, axis=1) min_slip = self._calc_slip(min_coefs) max_slip = self._calc_slip(max_coefs) return (min_slip, max_slip) - def _calc_slip(self, slip_coefs): + def _calc_slip(self, slip_coefs) -> numpy.ndarray: nimpulses, nlocs = self.impulse_slip.shape[0:2] slip = numpy.dot(slip_coefs.reshape((1,-1)), self.impulse_slip.reshape((nimpulses,-1))) return slip.reshape((nlocs,-1)) - def plot(self, median, stddev, minmax, filename, show_plot): - figure = pyplot.figure(figsize=(7.0, 4.0), dpi=150, layout="tight") + def _plot(self, median: numpy.ndarray, stddev: numpy.ndarray, minmax: tuple, filename: str, show_plot: bool): + figure = pyplot.figure(figsize=(6.5, 4.0), layout="tight") axes = self._setup_axes(figure) self._plot_observed(axes) self._plot_median(median, axes) @@ -118,20 +145,22 @@ def plot(self, median, stddev, minmax, filename, show_plot): def _setup_axes(self, figure): axes = figure.add_subplot() - axes.set_xlabel("Distance along Strike (km)") - axes.set_ylabel("Left-lateral Slip (m)") + axes.spines[["top", "right"]].set_visible(False) + axes.set_xlabel("Distance along strike, km") + axes.set_ylabel("Left-lateral slip, m") axes.set_xlim(self.XLIM) return axes def _plot_observed(self, axes): - axes.plot(self.observed_coords[:,1] / 1.0e+3, self.observed_slip[:,1], linewidth=2, color=self.COLOR_OBSERVED, label="Observed") + axes.plot(self.raw_y / km.value, self.raw_slip, linewidth=2, color=self.COLOR_RAW, label="Exact slip") + axes.plot(self.observed_coords[:,1] / 1.0e+3, self.observed_slip[:,1], linewidth=2, color=self.COLOR_OBSERVED, label="Prescribed slip") def _plot_median(self, median, axes): axes.plot(self.impulse_coords[:,1] / 1.0e+3, median[:,1], linewidth=2, color=self.COLOR_MODEL, label="Model median") def _plot_stddev(self, stddev, axes): low_slip, high_slip = stddev - axes.fill_between(self.impulse_coords[:,1] / 1.0e+3, low_slip[:,1], high_slip[:,1], color=self.COLOR_MODEL, lw=0, alpha=0.5, label="median$\pm$stddev") + axes.fill_between(self.impulse_coords[:,1] / 1.0e+3, low_slip[:,1], high_slip[:,1], color=self.COLOR_MODEL, lw=0, alpha=0.5, label=r"median$\pm$stddev") def _plot_minmax(self, minmax, axes): min_slip, max_slip = minmax @@ -139,24 +168,6 @@ def _plot_minmax(self, minmax, axes): axes.plot(self.impulse_coords[:,1] / 1.0e+3, max_slip[:,1], color=self.COLOR_MODEL, lw=1, ls="--", label=None) - -def cli(): - parser = argparse.ArgumentParser() - parser.add_argument("--catmip-theta", action="store", dest="filename_theta", type=str, required=True, help="Filename of output from CATMIP inversion.") - parser.add_argument("--pylith-impulses", action="store", dest="filename_impulses", type=str, default=PlotApp.FILENAME_IMPULSES, help="Name of HDF5 file with fault slip inpulses from Green's functions simulation.") - parser.add_argument("--observed", action="store", dest="filename_observed", type=str, default=PlotApp.FILENAME_OBSERVED, help="Name of HDF5 file with station output with fake observations.") - parser.add_argument("--no-gui", action="store_false", dest="show_plot", default=True, help="Do not display plot.") - - args = parser.parse_args() - kwargs = { - "filename_observed": args.filename_observed, - "filename_impulses": args.filename_impulses, - "filename_theta": args.filename_theta, - "show_plot": args.show_plot, - } - PlotApp().main(**kwargs) - - if __name__ == "__main__": cli() diff --git a/examples/strikeslip-2d/viz/plot_inversion_results.py b/examples/strikeslip-2d/viz/plot_inversion_results.py index fa9b09de9e..2f73b88762 100755 --- a/examples/strikeslip-2d/viz/plot_inversion_results.py +++ b/examples/strikeslip-2d/viz/plot_inversion_results.py @@ -4,34 +4,69 @@ the true solution for Step 6. """ -# Import argparse and re (regular expressions) Python modules(standard Python) -import argparse +# Standard Python modules +import pathlib import re -# Import numpy, h5py, and matplotlib modules (included in PyLith binary installation) +# Python modules included in PyLith binary installation import numpy import h5py import matplotlib.pyplot as pyplot +from pythia.pyre.units.length import km -class PlotApp: +OUTPUT_DIR = pathlib.Path("output") - FILENAME_MODELS = "output/step06_inversion-results.txt" - FILENAME_OBSERVED = "output/step04_varslip-fault.h5" +FILENAME_MODELS = OUTPUT_DIR / "step06_inversion-results.txt" +FILENAME_PRESCRIBED = OUTPUT_DIR / "step04_varslip-fault.h5" +FILENAME_RAW = OUTPUT_DIR / "slip_variable.txt" - - COLOR_OBSERVED = "black" - COLORS_MODEL = ["orange", "purple", "red", "cyan"] - XLIM = (-25.0, 25.0) - def main(self, filename_models: str=None, filename_observed: str=None, observed_only: bool=False, show_plot: bool=False): - filename_models = filename_models or self.FILENAME_MODELS - filename_observed = filename_observed or self.FILENAME_OBSERVED +def cli(): + """Command line interface. + """ + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--models", action="store", dest="filename_models", type=str, default=FILENAME_MODELS, help="Filename of output from inversion.") + parser.add_argument("--prescribed-slip", action="store", dest="filename_prescribed", type=str, default=FILENAME_PRESCRIBED, help="Name of HDF5 file for fault from prescribed slip simulation.") + parser.add_argument("--raw", action="store", dest="filename_raw", type=str, default=FILENAME_RAW, help="Name of ASCII file with raw slip profile.") + parser.add_argument("--prescribed-only", action="store_true", dest="prescribed_only", default=False, help="Show only observed slip.") + parser.add_argument("--no-gui", action="store_false", dest="show_plot", default=True, help="Do not display plot.") + + args = parser.parse_args() + PlotApp().run( + filename_models=args.filename_models, + filename_prescribed=args.filename_prescribed, + filename_raw=args.filename_raw, + prescribed_only=args.prescribed_only, + show_plot=args.show_plot, + ) - self.load_observed(filename_observed) - self.load_models(filename_models) - self.plot(observed_only, show_plot) - def load_observed(self, filename): +class PlotApp: + """Application to plot simple inversion results. + """ + COLOR_RAW = "gray" + COLOR_OBSERVED = "black" + COLORS_MODEL = ["orange", "purple", "red", "cyan"] + XLIM = (-25.0, 35.0) + + def run(self, filename_models: str, filename_prescribed: str, filename_raw: str, prescribed_only: bool, show_plot: bool): + """Run plotting application. + + Args: + filename_models: Filename of output from inversion. + filename_prescribed: Name of HDF5 file with station output with fake observations. + filename_raw: Name of ASCII file with raw slip values. + prescribed_only: Show only prescribed slip. + show_plot: Show plot window. + """ + self._load_observed(filename_prescribed) + self._load_raw(filename_raw) + self._load_models(filename_models) + self._plot(prescribed_only, show_plot) + + def _load_observed(self, filename: str): h5 = h5py.File(filename, "r") observed_coords = h5['geometry/vertices'][:] observed_slip = h5['vertex_fields/slip'][:,:,:].squeeze() @@ -42,7 +77,12 @@ def load_observed(self, filename): self.observed_coords = observed_coords[reorder,:] self.observed_slip = observed_slip[reorder,:] - def load_models(self, filename): + def _load_raw(self, filename: str): + data = numpy.loadtxt(filename) + self.raw_y = data[:,0] + self.raw_slip = data[:,1] + + def _load_models(self, filename: str): model = numpy.loadtxt(filename) self.models_coords = model[:,0] self.models_slip = model[:, 1:] @@ -51,53 +91,38 @@ def load_models(self, filename): header = fin.readline() self.models_penalty = list(map(float, re.findall(r"penalty=(\d+\.\d+)", header))) - def plot(self, observed_only=False, show_plot=False): - figure = pyplot.figure(figsize=(7.0, 3.5), dpi=150, layout="tight") + def _plot(self, prescribed_only=False, show_plot=False): + figure = pyplot.figure(figsize=(6.5, 4.0), layout="tight") axes = self._setup_axes(figure) self._plot_observed(axes) - if not observed_only: + if not prescribed_only: self._plot_models(axes) axes.legend(loc="upper right") if show_plot: pyplot.show() - filename = "step04-slip.pdf" if observed_only else "step06_inversion-results.pdf" + filename = "step04-slip.pdf" if prescribed_only else "step06_inversion-results.pdf" figure.savefig(filename) def _setup_axes(self, figure): axes = figure.add_subplot() - axes.set_xlabel("Distance along Strike (km)") - axes.set_ylabel("Left-lateral Slip (m)") + axes.spines[["top", "right"]].set_visible(False) + axes.set_xlabel("Distance along strike, km") + axes.set_ylabel("Left-lateral slip, m") axes.set_xlim(self.XLIM) return axes def _plot_observed(self, axes): - axes.plot(self.observed_coords[:,1] / 1.0e+3, self.observed_slip[:,1], linewidth=2, color=self.COLOR_OBSERVED, label="Observed") + axes.plot(self.raw_y / km.value, self.raw_slip, linewidth=2, color=self.COLOR_RAW, label="Exact slip") + axes.plot(self.observed_coords[:,1] / km.value, self.observed_slip[:,1], linewidth=2, color=self.COLOR_OBSERVED, label="Prescribed slip") def _plot_models(self, axes): nmodels = self.models_slip.shape[1] - coords = self.models_coords / 1.0e+3 + coords = self.models_coords / km.value for imodel in range(nmodels): axes.plot(coords, self.models_slip[:,imodel], "--", color=self.COLORS_MODEL[imodel], label=f"Model penalty={self.models_penalty[imodel]}") -def cli(): - parser = argparse.ArgumentParser() - parser.add_argument("--models", action="store", dest="filename_models", type=str, default=PlotApp.FILENAME_MODELS, help="Filename of output from inversion.") - parser.add_argument("--observed", action="store", dest="filename_observed", type=str, default=PlotApp.FILENAME_OBSERVED, help="Name of HDF5 file with station output with fake observations.") - parser.add_argument("--observed-only", action="store_true", dest="observed_only", default=False, help="Show only observed slip.") - parser.add_argument("--no-gui", action="store_false", dest="show_plot", default=True, help="Do not display plot.") - - args = parser.parse_args() - kwargs = { - "filename_models": args.filename_models, - "filename_observed": args.filename_observed, - "observed_only": args.observed_only, - "show_plot": args.show_plot, - } - PlotApp().main(**kwargs) - - if __name__ == "__main__": cli() diff --git a/examples/strikeslip-2d/viz/plot_slip.py b/examples/strikeslip-2d/viz/plot_slip.py new file mode 100755 index 0000000000..9b1744f14d --- /dev/null +++ b/examples/strikeslip-2d/viz/plot_slip.py @@ -0,0 +1,25 @@ +#!/usr/bin/env nemesis + +from matplotlib import pyplot +import numpy + +from pythia.pyre.units.length import km + +FILENAME = "output/slip_variable.txt" + +data = numpy.loadtxt(FILENAME) +x = data[:,0] / km.value +slip = data[:,1] + +figure = pyplot.figure(figsize=(6.5, 4.0)) +ax = figure.add_axes(rect=(0.09, 0.12, 0.88, 0.86)) +ax.spines[["top", "right"]].set_visible(False) +ax.plot(x, slip) +ax.set_xlabel("Distance along strike, km") +ax.set_ylabel("Left-lateral slip, m") + +ax.set_xlim(numpy.min(x), numpy.max(x)) +ax.set_ylim(0, 1.1*numpy.max(slip)) + +pyplot.savefig("step04-slip.pdf") +print(f"Mean slip: {numpy.mean(data[:,1]):.2f}") diff --git a/examples/strikeslip-2d/viz/plot_slip_impulses.py b/examples/strikeslip-2d/viz/plot_slip_impulses.py new file mode 100755 index 0000000000..2a7e4be564 --- /dev/null +++ b/examples/strikeslip-2d/viz/plot_slip_impulses.py @@ -0,0 +1,35 @@ +#!/usr/bin/env nemesis + +import pathlib + +from matplotlib import pyplot + +import numpy +import h5py + + +OUTPUT_DIR = pathlib.Path("output") +SIM_NAME = "step05_greensfns" + +filename = f"{SIM_NAME}-fault.h5" + +h5 = h5py.File(OUTPUT_DIR / filename) +y = h5["geometry/vertices"][:,1] +slip = h5["vertex_fields/slip"][:,:,1] +n_impulses = slip.shape[0] + +i_sort = numpy.argsort(y) +y = y[i_sort] / 1.0e+3 +slip = slip[:,i_sort] + +figure = pyplot.figure(figsize=(6.5, 4.0)) +ax = figure.add_axes(rect=(0.09, 0.13, 0.9, 0.83)) +ax.spines[["top", "right"]].set_visible(False) +for i_impulse in range(n_impulses): + ax.plot(y, slip[i_impulse,:]) +ax.set_xlabel("Distance along strike, km") +ax.set_ylabel("Impulse amplitude, m") +ax.autoscale(axis="both", enable=True, tight="True") + +pyplot.savefig(f"{SIM_NAME}-impulses.pdf") +pyplot.close(figure) From c5d609ce62a10977e565a0e6d7bba3243c8269fb Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:15:59 -0600 Subject: [PATCH 14/18] DOCS: Update component information for OutputObserver classes. --- docs/user/components/meshio/OutputObserver.md | 4 ++++ docs/user/components/meshio/OutputPhysics.md | 4 ++++ docs/user/components/meshio/OutputSoln.md | 4 ++++ docs/user/components/meshio/OutputSolnBoundary.md | 6 +++++- docs/user/components/meshio/OutputSolnDomain.md | 4 ++++ docs/user/components/meshio/OutputSolnPoints.md | 4 ++++ pylith/meshio/OutputSolnDomain.py | 3 +++ 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/user/components/meshio/OutputObserver.md b/docs/user/components/meshio/OutputObserver.md index 3010d8583d..5909c20867 100644 --- a/docs/user/components/meshio/OutputObserver.md +++ b/docs/user/components/meshio/OutputObserver.md @@ -21,4 +21,8 @@ Abstract base class for managing output of solution information. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) diff --git a/docs/user/components/meshio/OutputPhysics.md b/docs/user/components/meshio/OutputPhysics.md index dceacafa6e..55073b734e 100644 --- a/docs/user/components/meshio/OutputPhysics.md +++ b/docs/user/components/meshio/OutputPhysics.md @@ -33,6 +33,10 @@ Implements `OutputObserver`. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) ## Example diff --git a/docs/user/components/meshio/OutputSoln.md b/docs/user/components/meshio/OutputSoln.md index 7527d9e769..0021d71aa7 100644 --- a/docs/user/components/meshio/OutputSoln.md +++ b/docs/user/components/meshio/OutputSoln.md @@ -26,4 +26,8 @@ Implements `OutputObserver`. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) diff --git a/docs/user/components/meshio/OutputSolnBoundary.md b/docs/user/components/meshio/OutputSolnBoundary.md index b707c66a2a..f47f7ee5c0 100644 --- a/docs/user/components/meshio/OutputSolnBoundary.md +++ b/docs/user/components/meshio/OutputSolnBoundary.md @@ -29,7 +29,7 @@ Implements `OutputSoln`. * `label`=\: Name of label identifier for external boundary. - **default value**: '' - **current value**: '', from {default} - - **validator**: + - **validator**: * `label_value`=\: Value of label identifier for external boundary (tag of physical group in Gmsh files). - **default value**: 1 - **current value**: 1, from {default} @@ -37,6 +37,10 @@ Implements `OutputSoln`. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) ## Example diff --git a/docs/user/components/meshio/OutputSolnDomain.md b/docs/user/components/meshio/OutputSolnDomain.md index 7cbbe2ad11..d10e3828c6 100644 --- a/docs/user/components/meshio/OutputSolnDomain.md +++ b/docs/user/components/meshio/OutputSolnDomain.md @@ -30,6 +30,10 @@ Implements `OutputSoln`. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) ## Example diff --git a/docs/user/components/meshio/OutputSolnPoints.md b/docs/user/components/meshio/OutputSolnPoints.md index 3beca50750..9588ace460 100644 --- a/docs/user/components/meshio/OutputSolnPoints.md +++ b/docs/user/components/meshio/OutputSolnPoints.md @@ -36,6 +36,10 @@ Implements `OutputSoln`. - **default value**: 1 - **current value**: 1, from {default} - **validator**: (in [0, 1]) +* `refine_levels`=\: Number of mesh refinement levels for output. + - **default value**: 0 + - **current value**: 0, from {default} + - **validator**: (greater than or equal to 0) ## Example diff --git a/pylith/meshio/OutputSolnDomain.py b/pylith/meshio/OutputSolnDomain.py index 184bf8e265..8e92c88c9a 100644 --- a/pylith/meshio/OutputSolnDomain.py +++ b/pylith/meshio/OutputSolnDomain.py @@ -35,7 +35,10 @@ class OutputSolnDomain(OutputSoln, ModuleOutputSolnDomain): writer = pylith.meshio.DataWriterHDF5 writer.filename = domain.h5 + # Output with a basis order of 1 and refine mesh 3x (cells are 1/8 size). + # Refining the output mesh is useful with a basis order of 2 or greater in the solution. output_basis_order = 1 + refine_levels = 3 """ } From d69f51a18f9df0e39a2f2f7ed50632be734bb276 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:09:25 -0600 Subject: [PATCH 15/18] DOCS: Update examples/strikeslip-2d for better slip distribution and refining output. --- docs/Makefile.am | 14 +- .../strikeslip-2d/figs/step04-slip.pdf | Bin 13480 -> 14923 bytes .../strikeslip-2d/figs/step04-slip.svg | 448 +++++++++--------- .../figs/step05_greensfns-impulses.pdf | Bin 0 -> 12228 bytes .../figs/step05_greensfns-impulses.svg | 286 +++++++++++ .../figs/step06_inversion-results.pdf | Bin 0 -> 18873 bytes .../figs/step06_inversion-results.svg | 336 +++++++++++++ .../figs/step07a_catmip-results.pdf | Bin 0 -> 19482 bytes .../figs/step07a_catmip-results.svg | 322 +++++++++++++ .../figs/step07b_cfcatmip-results.pdf | Bin 0 -> 19486 bytes .../figs/step07b_cfcatmip-results.svg | 322 +++++++++++++ .../examples/strikeslip-2d/step04-varslip.md | 9 +- .../strikeslip-2d/step05-greensfns.md | 18 +- .../step06-inversion-leastsquares.md | 10 +- .../strikeslip-2d/step07-inversion-catmip.md | 8 +- 15 files changed, 1519 insertions(+), 254 deletions(-) create mode 100644 docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.pdf create mode 100644 docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.svg create mode 100644 docs/user/examples/strikeslip-2d/figs/step06_inversion-results.pdf create mode 100644 docs/user/examples/strikeslip-2d/figs/step06_inversion-results.svg create mode 100644 docs/user/examples/strikeslip-2d/figs/step07a_catmip-results.pdf create mode 100644 docs/user/examples/strikeslip-2d/figs/step07a_catmip-results.svg create mode 100644 docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.pdf create mode 100644 docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.svg diff --git a/docs/Makefile.am b/docs/Makefile.am index 02c7cc9ec0..e52421aba0 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -473,13 +473,15 @@ dist_noinst_DATA = \ user/examples/strikeslip-2d/figs/step04-solution.jpg \ user/examples/strikeslip-2d/figs/step05-diagram.pdf \ user/examples/strikeslip-2d/figs/step05-diagram.svg \ + user/examples/strikeslip-2d/figs/step05_greensfns-impulses.pdf \ + user/examples/strikeslip-2d/figs/step05_greensfns-impulses.svg \ user/examples/strikeslip-2d/figs/step05-solution.jpg \ - user/examples/strikeslip-2d/figs/step06-solution.pdf \ - user/examples/strikeslip-2d/figs/step06-solution.svg \ - user/examples/strikeslip-2d/figs/step07a-solution.pdf \ - user/examples/strikeslip-2d/figs/step07a-solution.svg \ - user/examples/strikeslip-2d/figs/step07b-solution.pdf \ - user/examples/strikeslip-2d/figs/step07b-solution.svg \ + user/examples/strikeslip-2d/figs/step06_inversion-results.pdf \ + user/examples/strikeslip-2d/figs/step06_inversion-results.svg \ + user/examples/strikeslip-2d/figs/step07a_catmip-results.pdf \ + user/examples/strikeslip-2d/figs/step07a_catmip-results.svg \ + user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.pdf \ + user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.svg \ user/examples/subduction-2d/index.md \ user/examples/subduction-2d/common-information.md \ user/examples/subduction-2d/exercises.md \ diff --git a/docs/user/examples/strikeslip-2d/figs/step04-slip.pdf b/docs/user/examples/strikeslip-2d/figs/step04-slip.pdf index 6609b620b993bd30c41b0b7a280b7e098bda661a..36c3d5deec4baba3c640525e06bdafd36e49617c 100644 GIT binary patch delta 6371 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 SOxdL{g0dj0wY6uU7xn)hKdw3e diff --git a/docs/user/examples/strikeslip-2d/figs/step04-slip.svg b/docs/user/examples/strikeslip-2d/figs/step04-slip.svg index 950d98c193..b81ec524f3 100644 --- a/docs/user/examples/strikeslip-2d/figs/step04-slip.svg +++ b/docs/user/examples/strikeslip-2d/figs/step04-slip.svg @@ -1,236 +1,224 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.pdf b/docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6723ec14699a7eab9e8e004b769ae39dd41c2e62 GIT binary patch literal 12228 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 H5Apv1&+ytN literal 0 HcmV?d00001 diff --git a/docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.svg b/docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.svg new file mode 100644 index 0000000000..1f33602be2 --- /dev/null +++ b/docs/user/examples/strikeslip-2d/figs/step05_greensfns-impulses.svg @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/examples/strikeslip-2d/figs/step06_inversion-results.pdf b/docs/user/examples/strikeslip-2d/figs/step06_inversion-results.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3c901af6d801cdc3ddf5429469a6f329b64f4dce GIT binary patch literal 18873 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 SMNnZB8V=&-mc1kg`u_mosjRvH literal 0 HcmV?d00001 diff --git a/docs/user/examples/strikeslip-2d/figs/step06_inversion-results.svg b/docs/user/examples/strikeslip-2d/figs/step06_inversion-results.svg new file mode 100644 index 0000000000..e95411c9c3 --- /dev/null +++ b/docs/user/examples/strikeslip-2d/figs/step06_inversion-results.svg @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/examples/strikeslip-2d/figs/step07a_catmip-results.pdf b/docs/user/examples/strikeslip-2d/figs/step07a_catmip-results.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f465d6754b58a331ee67e5f7675483abc37a8b98 GIT binary patch literal 19482 zcmb`v1yq&I^8gHz(v6_tMQMTCz@?GyMq0YNL6H&xkuE``kuCv|?iK+l6$wcLX+Z?x zdoJql^;Q1g>-o+HXV31l&+N|Z%se}@JG+-fRZ^N8%7Y+aDR~1bt|x$kARs4GTLK{= z5Lna4*#ZQXFmX4rcd`P3RZXlc+(0k@Kpi9^LSW%&jt1oarGd1QqdN$G0sz)gF}1ZY za|iK#f0Xiem(g%Hakl^=zE`N4xVu}pI)aesM*^^hwTZcnqZNqv$6Hq?GYt!OkUoG` zQW_w|!rL7LmU93|xcVcP_>s$j41Xa9`sV=9bfc+vwE(F5PCi)O!p+IU)eIO9ntpW< zSjocN#^kD#H-HfW{3CezK`?%PkRbtB0vHs~(hY?A4k_;F=mb1L(O|za0{!|Y=M*g* zt=z3a&>z^OZR~-ug22-D00Sf~%$&?E&?LLLyIPny5O}A3dY~WApye7eJ5*jELk{Kq zbg)GJ?0(o;!FHm~FM;>*bn&^QDWpyB?CT$e9%)-XTq{z~xKsIdP!dDk^K;poy6wl> z%Vky>&4*LPwBX|}uh<4e{ak!Jk85ey!7lqz{w;>>TMWlX)tyW5qi?$uU#1=?*aRQ9 zJUPyXe$jY&bexeqz?W=war@nk^e?OGUsDgl3VB${Di@7Df2=8gZ?xe{nOk<;JoD|j zmTB=(g;0ggSvLj_lB4^s`VtO@JJSP8v&ppsRnhTdVG26>@3W#}T@BlprfYkf55$@e zH>*f3)|;CQ(jV!18-`_ZahJR78n8`y>m1Sh*x3z~KJ$!Qsq4O%)h)+3nhGmdlJU9V zF<3Y5t;aS|nIz;Y)Wo;^RC_0UlbJNcunVg4(QMkt_2WK!nF&K)()Ob*0R@$;i=8$P z6PKdFifM8wHqU~qd1of&irAa_b0p>Iw9&SJse`W5Qhu7GiiI51%&de% zR57oNX;SY+_AF6OE*Z;uNlGQZGClv4uAR!0k;+T=RFO%uNaCFPCQ*vOnFCLt*!8H@LlS48N>c9xtY;IE3R+tv?Mm4KTUpGtJ zuExhTl<2%56W!`F5#BAFu3TnTudZS@_f7bbNc39p(j-lX5X%3GS*gj^^BkRgMge7S zGD-sWp!l&I{?MAt-ri%{%?`WS;l-pG()F!7N{;6??$lfqd2pW1=i?hE@4jH3n(dbK zNljCg{dc8iC5KrPH(l4DlQa5NJ$r32n`?~v_W5(+*wI1XsO&kUT_uW2FPOz6hGKJF zNtTpnxp70JflMqHKMPSE2I(31gwiV2f8)fj&~>i2w}I~VJTFT6$g zK7mv2;Ca-p^ws9X7N_L{{m*Zuh3mBZ9Vd$QKYx1bYdwCjy@W^L>S-{CbB;2AOYCf% z0qzYsH`fWlTxakiV(JbJPX>n4t@^`O|Bfw0g*ID^bhidRTU3Kf(Le-WvPyHK(80>n z&WfA+gBJLL&p!YPor9|Iqa7bhk=Ki!S<#nQIMg>iw>vw6ck4N0 z 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.pdf b/docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.pdf new file mode 100644 index 0000000000000000000000000000000000000000..95ed95d2dccb4885cce4ddf83fbb635c03c53536 GIT binary patch literal 19486 zcmb`v2UJwO^8gAW0!x!#L|CNPZS2B=^deolh=BCoJEGE?^ezYpNK-(ng(e`q2}&0b zr7Kmsg7EI5exE<(|31$?8elOokhy~yrl8O-733Tp+`x$A0ubHH zCN}1#ZeYRhkFs8Fmo(js-ORxP-!s&V-Q3Jw9KcA-BM72tWo%~cU9 zz6LZaBL|>j?&SuCDA)riNd1VVf5Zx4gI~~r{n-Hw-Wcp%%mM7aqYu$AcXf1kF$MaA z!CwOmQ872OHkNYq0$PLue*u&b7%n6PHUL4SfldK6UBT$@B_$mk9Dyeorr589z`XuR zIc0MPOE)Vp>_=;I)^+MPpoH!15+ zvjoXaLX_Sl(q)&i@WvTKX!RN!nTbGHDt_eKdbg#0eJ%P@SDVst-sF4g1j&QPG&7Qt zQjYqHZ|}@aP8l{l-ygVgo%d*c`{UT0BSb8HdPDTc_es#4&*9M~c}nTtQIY0*N5{)~ z#E0M74l~-`UpC&~^-Wiu%E-L+>H(A2bdlyq+f|nQn#AXA@jgR+w$}$_*DWY=AN#%- z`!>&8uI;Puz^n68|I(d6@%)KlwR1LC0!*(G~+vJSA8Dg7O&Wlm;BRrL*2{GA=TS;G{a@l8r{x>-WhoX{hlwY zUUgOMkFfGyx1e|BD2npj(({I0n+Z!xH!&N0h%>aWZ@Y|;&4rzDgBVw_wRU#4>9fAN z#fQ7J%l4`+gznxKc{}r7HYZ^v<F@|H(E>AN^v zSe^eQ?{&XjE)@r-N|D)$$dgp4weCVYf6ut9h>4e)12?r?Iyk~)tHv`Ns&lE zwxLPIOF6>{OeUE`87oZW#>{=SZq3Pm`Y`g`Ehc<&If$?INh_3;ak5L7#}cul-IosU6F8Q5Z>~Jsu6y#}o=<~y?!DnU^WA$KZu`8BnO})_ zN4+)rye!UTGk%M93JY=+7q$jrTds*l@)XR+wM1O20|m%Gwx>3#ja6rzlX^dI>K7Mn z%W-B#`(lM*DY|0F^Z@lv(AY^{kwuZdMkknF;Vc{D0EtL5tG!rk zmcwlMy)Ua4CUvQjjvV87qKvT?)^9> z-o_R(cW+HqI{4-pD%-=ujjfdp*5JNmamduchpl}_&TX$EYN8bJIB*G&;?}p-Ql?~xukNAO*O|^O@z$5A3(CA}R8tB}Ll;f-0}4gb_ww$vPf2}N zg05`6z-Q9F7Hq9k?Q4`m%E`F8J^9e*Xh$-idAJQbeNgED}m)V^mz(+hj$A~p4r_h#p)z$u#YpVA2H^*tsg~;A0w>b z`jNsW_tKEx%^*0=lijQ~*#iQkjiIJ&a5~4s9hhjB=?zv1mE7Fm2aF=0IkvJMEok6q zGYxJQGOnnL?mYmJI{5a_T)3?t)8ZJGL}$`R+1kEE+b-WPeEG=*Z^&hD=g2`HzOU=t zM_Y74rcVULtM?stQ|@QJ@ID-v++T1^CUrDCT3Ab#h8CVWv=O$(MezBS1*DFOpJkI^ zX=G>9M8{CxxB`J>pW&fB0IwKh-_1ASKYP}S!Y(%cBGb(TdOyN9iHRZku!r1t3wU|< zH1ivo-<&DnOeDCN#cES3dWZO02MiLRQN8=IPnEj6TDgVFEltnU`f?P*9ZFO}fEtwq zzjFT+_?$m0{D_x-wSL24#yB8Ly~FOM=O?wt(GnhGPNNra&$(m02?*|-?>a}m>Cnab zijr`wa(6g1;=`5mH!0EQi!~}sN)oy0Ik~j4otPgoxPWLFnO6Iso%X%1wHs_fY^BO} zg)*JGEVzftEaqXnxDZ7P#e4FAN|kjN(*#!LbnnyP+jjcyIJabij}`t%)im!XXb&Gln{C^;-a1m#UgFU3ahI^3Vivp!8|Q`_zN# z?LvZIX0_Ev>pD6U8d7?Q)hS3uHXlqs>YUXD!C_UZ6~)4}o#CrJzTwpNLDJ#;1tIEq z&fa0z>O#Q*24Wl}8jt6Kf(n&b8|mTZ7Tg$T4cRa+N~=aEjCyb6J}HA3HqLQqf$!RsFj8It(L* z@c?I}e(5B|CN%S8GU1=EWC#EyRGAFyCDc;s-$~&%Oo+{_$f*~cQ8G(>v+T`#PjO=Q z{8F@A{flX_twMMFwK12i1%e!sx2+E9S1&}a)bFvf69kNUk+W83aM@Bdw>o%bPP2P0 z*l;o{lSsSVeDtimQ(^6Ck7Q4306lX{{HD#45LsrKkreV=8EFCo428Z;*4q1-5T48< zy`llhc@)7e-j(?}$sR}7PwxUcGB|L2)?Ofh1kDpaa&f*)t1UQC_ptwRfk@1#?-M4% z@JM-Y=W24oh6^8vGo(vqc(0h1)3B++mnJeppAV}I4F~2vpoN+zI8G3qmQAuAqOgfN z5ZcZX$Xstv?ZxBqnI+4dr!2dxd8^sTTum;vh*+!c0rQuZCT-kGU5&@%@YtQO_|320 zBmwa`Qg^j&3tWo2KeK$g)5*fnkI;Rhnmet##Gw&;?drz|RSz$Oj}X5JsZA43q??iR zc@fVt;U2p=&|gI|lpf_XZx;kg^5MBpkVdn~zE*6#ouGBl{N zhjUnmmkJ2NuDaAzI6rv1o2kwHnP1}e;yo`vPA%@wvZyrF`KuLX$*@zz6pE`Iy_B5X z*&Q5sI&JI)Snmn1bW@0W#c?k(a>+;EQc#V!S@p5Mr^Wu!+8diH6=KZ;^5%N?kaFMJY#;wx$wPJ~36^R#UEO+>5**Xe zi}GS~d4p{?CU~%(Dl5)FJMheuGL4#C??$Z{nqQd3@y%ZDbT7(Wm*aST-YzlmwUEG_ zn0EG9!8x$t9fQz7y5(G~XWV(ugKv_(d&_Vkz#+kjqpgJwufuYH;@JZkTuHU%4BL&u z3>&%F`nRy=N3Gp3oHpvK)QfR-MTDnU(x1EJ-%d-4RDNY4|59;Jw=%%OZW`OftTgeI z?e1`##!fq)Pg7C>RkV!!*V&*3HT@8fjMjBgYNiIYsz7JKZ|VZsDJmq9sW8KCXJu;0 zj13(_0{z9Va{a5;L5>Apd2Ab*8l!JJ>tk#_mE@dF5Rsv^|#m%J328#Gjr^7`kn1FDcRx#@pnU z-@W;b`z?>&gZrmS1DI8s)ZuwnQMVtlF2;1<(yYnhBEMYWZ$*43Em9x#a#H!NqLn-H0SWsYuaSIbYIC(pi@QXST`clyQtHnNo>;DW`K{c=2>Wo4x#Zxw*=miwQ4g6n7=TK=gR=HjB-q{ zJ!NhH>I{#9E|jY$Y4O`2RizDczRFw{#^Um-5bA>YVQCcdM!UQpnl@fHb51lhVh-hu zc)&0-%+9OAAp5P%5SLI{Og1sWH7+PjjksK0 z5~mgQdifj{0q;=m`13BBK`yT>^*HH+qHO_OSqg?ewOj96gz}w9gsy2bjp{d8l3iah zFy<$kWebM4a?yqQ5thd-zIeDXbm?h+_B>l6E&^vX%!%(2*`+UM{(+1hzhE3 z5*fb7%nJ#VWo^uQ|9a;gy9XD2wh>#air~>8WnQ=(XHUn6)*Ad=A2Q9?VbUqG(smlD zRzbnN#Y1F%FK?f_Vmmt#j+mn1BwNmZTXmg-2g`rqQ$JaofhX=)_Jyhz2#E@lDjf$0 zjqRH}^@a7C_$1EJC>uHj+~>(9HVPz7N%yn@4>~mn@LE$*pGoGr9<|kUJJ+M_V^1SV zuCmxATp^pXuCFzqz?;R=eKbuIY9T`+T$^nM>5!nawovUf-Z6fD&g0JQofXxw2@aAp zpX_o`Qd*qUb8Dj% z9VWAcdi%^I{9}tU?!7Y6@T5h!GY!K1f+Q_?2O&vt^Zpy$**PNw>ed*TaSw+qw3ZhSBw=?@(u>9!X-_XC(IWZK3 zr|33cKI1gYBb7(HnRQ2##nQ#QTptqBl)A|-(KNj)TtT6|T>~0r9=l55`mibfbQtIB zLydJQD>)V~aYG$mCWXhRSm>K}*!y4X_2zTEykkzYE%*U6upz}h(CssGpewc^@v+Fg zKk{OiEw!!0@CO66PUec5y1X`KWQQV?ki^Ag7G(LGjBz>pdlQlM40GBtI?LDX<;v>s zF^Z5mYd=#yZPU5#?chS9ITA(^l~w!#%AYhJ=V1AXWP-BBIja1N`cho`NV>bAr z-I%NkBQ;@7JcqO9eTujB6{};i56Ly#y}rHUJ^gB-2Ge@dcD1CI(Osww?@UlTlyLVnHr@1A*b!9?cX)jes)vx z`ug=*>iewpCv-FPSTS)b z-e`!7puOp@;w=-%qzmO4*A(P$m6`%sRfH{Yp7$9!4h z64D;U@l}Gvalu-L*~iRLAt>iV`}DxWY_N-43I8~X^V2X$9ic1pycP8dCwpJ%Drf)9 zaC!L4N@>U$gZF(cF)HZ&AZCpW)>ac$r)mZ;xH4l!pe|cOw(3 z_NHXmayuLP0@*D91K)_U)dbY72DN_%$bgvr_96C{(>PD0osjT!Bxji#- z?FFkoafjma__f+#+qm`jx6P%Tb9+PE_>q{|{o=isno<3XuRBFTKD9_w=0;aL_b$vE z3=K`#7zn#e45v(9&rPyGdtbUQRDi|d9)o>IU+^4Z)vrjPokpj)&aBIFg(w(=OzbQ` zs@JMao_;h=D@mk%C@<`4^UztEI3zZpcuab0KX|y(R<3stmmW}$;_JIt1vj+b*tPG6 zZJ0;S5NngsALP()HVev@_K8v*+>&ur`yetDU*d1r_{d5^tClxtpE0~YJpX!)I4E}O z(65U?q5lRWNYQY)KB4@P_eh;1I9;rcv@wRjKxHI8q|<##f93I2xz7xx5vb2E&qYoX z2z~t08h&FzH)kOJ&K0{Ly2zMAi*H<YTyjOZ}RY z9u)Q7r~g~P%8dd}vlXG}nO@N4%8B|0ku(`};EWgv6T{n_kVtMh`lljS2A!NJgR8Ra zX*=sLHRt9g$E+0j`R=ER#hos&Qi#RrL-n~87ClK{p%tm_sTKb;f5x=O!#mq++;82Y zl4ZX{!$c%;$@bly3cZU}MD8ON-yqsEVs&cPStT`fjz0NY^cU|$?{9oK^|WSasIw*eEv5gb_|onm_5i32X@9r-dahT<#M7dx zd=dCyw8yum;Jm3iSdLmiHb)8lLa1 z=r@Z?eEqVuBBiQ7dbDAAb9$~fCjPdjV7cVx^03?FtrTgOjDUzsf@Jh*WuYryTjrV> zq@~A`4(cDMNp{R;z9aFH3Ke~d9?DaVF@XthyjHg}lv8}#S%ag8 z{3GqnJR{ArjQg>4>rc?7FADmD12c)Ozct)*Ynbhi>6F>^)#Lfbol5K9dx$$Ima+I^ zVB*FFAIR&Q&t5I>s(Kj02h&bbFyJ}axKwI0?XOgXr$JhaJ%h!-aBI8XzKj&VDJ+q5 zRPS!lQLsS_S3TLHHsT7|uc%6i4L#v76+FT-tl(itA%#cd`Rqq@#fYVvHC^9XVIvjW zuiGmCb6@$&Fl*^k>-(7?5-aL!V%}&dsU9nX?AIU!2xq;azRt?dj78O5t_jalQe6D= z^z4Nw@bXOGisNq43ia@Wq|#|0Dc{@W)(gIysF<&BKCRr74`_C=lpMW18U3lQnr5=7 z?waef%9!E}sr$n>ooj|ny_S>9=z*<=8H)-17;^0UwgjR11E7V0w_@XCz7(%}_zxh9e$g-->}!YD!&Gix5d#o%zrA&r1j1>*O{$m#1ryW{=>B{kndMg#^Igo9)fjK zzH(cSZ*T55N9>j!eOsLi+~0F+o7hQ4YECk>Ty<(Fjd)MP6gZc8>GFsBzFywD7T!L) z8^G?K&o`#MFmLaMBh)_4?T)$?HO+Z%kEb4NHB)(S7V8Udvc47D61yqA^PHG}&537` zf{XM#uM?~@;n{t@shhrUWP|UTl=Wft$X{Mv7LQG_b%8j4?p7i4w%I;xF6Jmzu_Jbj z%AWq_>vh|Z-Mu!@wV}UuQ>y)PUFJbbXKBO1jg6+3ws?Zoj7;${U%v>6(S^OLe9|zc z(bXwsyBD9A)SEnFYg8PV-PUGz}R@WU@t6 z6f;Px2FBk9FW_u{JimMbhQGS;etOdc{|3caCGuu4k@Rl5)FrGVzs;(Fj{y_D*Sb^P z0x3UBluISgyO+ z8uzEp)6no0(Uq7hzg{+eWXDJJDN53_YkTm<<4q{p+9uAFq?p+WUB);Ie`5*)D)<*% ziC1#KfdO3>3+6xD_;oCEGncdG?mORc4z`bX7{;h&ZIWx0uWB;J3M2&ieq47d&)5*L z>$9+Uua}b&K9{)APi3;2b91am&fqFX>!%+Y+$ER$dP2v*16*>qIkJ-qu$gv+9A$xVabfhLrhv16lfeeS`ityJG$ z84uf*{AdWmg=5vKZGNz0I`;5g)M=%d$5zan?@Jwq`Hku{g=J05R9%X#BeYd_)hGw5 zo9l_rZrjO9bGgP1eY)QKiqJOMj@nD{D=y=MNp>X?ow4yk)wPm~WBt2KdLwR3C(s__ zwEm6uaDl&=8)f5ETyUB3gLX4>AnT82uZZ^LYFt%bZ6NNgW988cp2rzDMR94JTzWY? ziGm4!6S4@u`3x?yEa8sZt*kJjkX@Ax&4Zsun9 zZ)B$t_QZxgCcEm!lj1HhkhrSxf!^*~0Oht~F-Jz0z#>`Kx@V&8O?QgRrRB3)z07*O zB^2~`%Iv%(2Rm8Go)AZHB)c-Je|dDSNSNO!fo*!rZz3zn;^qwv1u|&h&Eih0o>Qp) zgj!3QwlpP1+2|_*cgsW+kn4WC(@$UQqMTzkY4(CWr;d0?ZjGE0^Tkp+G&pkt@h~3! z--(BS|F_^G)fF6CphUI%R0oY%!>e^1ty!TvMCPoJ}yn6jLL!1mB#6MON< z2kf^kU9KGPUJkzWvgEx2rGLr?Lyv&&b8Y70BnYOu6rESOZ3#pjvMAAuWbje8v%=8Y zGw!1nZ^K_Of2d^9=#@(z7$M(!!+p9-^Xb&b0CM}Hude&Wg!cPyDO5dtJ}Jymge@c& zH=55-CA8|E5mm2Ng58S!WS7m6UB`Jp&`!)IOeTfX@_l$y6K6lka`lSkv^KMq!DNBG zX`!5A`#=M+ib_2G7a0P}rvj_ghrWIFFGluBRhhNOP9PZO%)@U41I`=#ry@q6s??xr zP{AwxNC5$DC>*W^6@aVD!)5_d#Y4DO8wH?^lEblMjqzEV=v|&0>A5xvgDccZ(E4=x z)>zIt_|i ziu0*nsVppI7VYDDW?+l=n#!#WJ5{6+}|Mr$eLxMR}BaNr9&BC1^HLklWMdM6jz??p9|se11_V zjw3T-ZD*X<1AUuhi4YaVOtrAbeIo!Bn6vD?c8cCb^2lIvk5RUEkqvx~fO=TnWHo&* z=z6_}8{-pBa#yJ|Nq!3E-jCe*XVcV*D<5QOs5?CrD_AVP?>l#0pYH^EonS@51^6K|y6e>d9 zwF(-Mbcyg!jQJiHZWUkbcp$uJrt+$oC3S4z@_6bVgVVF?Z_QMb+T9p?_R_0f1)`~H zc4xv-cq&nE7ngS_thpf?wdeIRZo88wP0}vVlBZbu(oLBieZe~n)w^&41y3-|5NPCI zP*6k3p;ZEZe1TFw>&^PTK5q@}$+~??uU*W) z$$w2R)jO;g+82t z_%)4`5kLPR3YRQno#&Ejb5N&CBbOvIUWlVA%vHO8_2rcM>e4P8*Tyk2kI0#xy zR`hT)#Y?-jjN$AG1cIA6;B8Ha&60#i<%>5zF@R5lW5N z#eaeOwxKM11p-`;q?mSFrQ)dN zxI)VNZ$HnJZ^`A4QR!{3zRv5-QSa^QKzE$Y&ZMfT@EIf-Tfd<%U$d6j%goSyq~_0S zKIsBtlf2gNxlA@idj4?$Pk?cmEq~yOIehTwYbdq;+O1uac78wV;)NGYBv^$76jit# zbZ=KtTvk}xH4zFgA8g!k@W`=yp#AX+0~Ue=>e3j-cJ2I&*YB{BZy7AgM&0?wBcXm( z;-F*5qv;*2Q{IVs{!Dbe)5X?QCnce_QxbRTr)h7jvyIL}t~?G)TPJX@F@w~-%zQh) zAeDgcS%O7kXx3a(^q??#<>SSG9ZOjkxyZo?Az|ity*KE9={H%7dNcZh<v+#k%9xg>U zcBRB4m*-hsu0}wFS>xf-lE6=B{RER%@Gp!q1pFCbWRwYDlZQ~VgXS&H94|CqJPfav z;-`@(YU#qRB=W0bOAiRM^t%hTKidkXmMKpSr;|CKjvd$iUJ(b2ZJfIE1bj}g5`_@| zEvlkDXmUR&K5l=e<^fAk$Aw*Ih6t}C9q8*bj72xHn1upsno2$xb=A00tZB{+wWX62 z6nZJDB-aq$7_53R_`>Ra?b5u`P`G$+A58{n?RmP%6Hq(B9uxSBh1ZFsN z*K_K1vJ>b+W>eA`tZGYQjuV4}3nk}ie;WkUA=CjWS zM9#FHdu4!rXy*JN(p}4)+ex`EXbY--AXFramujUd94H`IsHwF;_hsO#1fHzTd(HUEcx=xjK_k%k)t=6 z{Mgx!IA+@O0UjCpN7KV!>W`d5MEai4J!V*&_Pjgn(SF?|p2`(FVuGu1!IocdgiiQf z0-}93e?R0^wNXlKpz_)m@!`I&hd7K}7GF;w<*!!R_hZXH&mTiH-A&w%4>HR+y4Zsu zQr{2x^1+~R7?@80g#g0@(E`9xT?7I+NDTS0*MLBS{&NzYfeS!2p(vzw#~fS`b*j>( zk(b4l1x&~qVI*mW00t)2Cg|n~xSnADzyLJKqj5kN99T;cF!(kgd@&&ODcdCOTFGfk(}RyF2PFCIX?H)J+!?Dxja${N)=6%k ztx&E!ge4T`El6%8KA_7wD@^rnC1=(pfA!TDX{YV$+YKg@=zHP*on7bgdp~JTd_jri z)YNny=C)51kKE>2);6}js?<&JETh&!f?z@u{kBL{oCzenb3$KFunXX@zYuXzwd$zT zFrsdQV0zug8!HbjsUwu~kGAB$>|A(FEvvzeOpWJ)xF@n*)qE#>Gr5JtJ7mtm48_JR z3rQ$r+wBK^z7;-CxjQ+OTq!M(Vuij3-XAB`(#B;fQl^ zd@*g9{*VNRj3GX)j>SN?oS&S`8Y!vL*Qm$mSNqKH@LUy34Uxo7c#CtIMs#+Aty5kf zWR62~^iL8AoM37E&AccZ3G7rt@nwASjZWWY-vM?iU%qP~KFj9toMTc{|2#n|mjj|% z`b;JfZ-{}j|5h@TQ2&xzbjI=nI1L!nb83*|Bs^Z zCX32?G_*+c6-lh>^S07Y10qSRIN>$1n^Jk8CB{LvoEV<*yBZm)d~>uZ_ZNL`Mq`P# zzKfc8-QGBiE`VU(@9G%|`Wzv=$Lygzfjq=mAF7D&p3w9OS|9y4c6c<51h8AN zJPn&D)F{2x282eBN^$L!XzFM2Ln|&AGnach$v(u1Ii|?oHc1^$SBCle+OcQndd9?!5 zFcD69WqH$h`KOG5ENQxx26t1nxGOb2R9UyaY#7rU>X3#b}8H3$rS3~yedY09~jD2{WJC8@nG-^*#23I3qxqjdr(2=X6_CU$o=-W9) zf74a$4|dR(yTcND|KWv;S-G7(?4aqGbVe6$9OF-EkKJ6(X*(BW_8{*?JVPj0EWMB~ zPkrfaAXIrsq-pWQo1@PqXYe8ZTDhfCe?R(hW_|KiE4OfF{7yn z9-8P~X|kqFH6a)$zpkmSnRbKjaDQXf?GYk+**N)#jr|5ifvE2#R_tWvI~%7v$<2r5A&2<9W@q*O+$M%B9}Ltfcj5wC++@ zQugtcUg{%z#s@mBP9dtB3Zc3%*tfMPT+8ICGg+1Iiw=Q#vqa-(bOY~}L_f&#XUjKO&)kW;qu2zLC1BEYHsdp7+ z;!~Dxl}l}fG{#>Py9Dd>TSkT3=ist0Fy^uKv``9{wV$f9NE^~#Gwiap(Ys@qhYBk)XK$A3vnP#N%5}8`D7u<*rZ|u*k%rkClXVlx?B-Q$O zGxP*T{A#)VboBg%fp9!m`ZZHZKNi3`KaZnv0_2nIEWpV7PZrC@D3P27{GGe$Inj;n zObgENkHM}-D}EUc6sDrVTK?4m*`oZmI2lw-%ydsbKYN%QEqhf=>xPC7Y3KXU;si@xnJ38%A(KZ%(kJ5P%YOI6Zaa=}?o^WYYO&LZ*^jS%_5IvwVrwN!ZNGo+U!Ini&UKuRVbrB!$(Ct^x3(1BT)Q$k+LC% zjpBS_#}o;1w(oVu2a)Nhcc@Py7Djo^3Togt2paMPR4io6fz zy;3(9S7g;Zg@6T2;fCJk8L`)$mCyn!n5rSOJwD&qVjOk8OVE=rTt;M3OnMN>HL=+G z0Y+!}Y{Y!Q79M6{X9sFTZnd4A#B-|&;EL!ijZypvTpIlY$Bt9Gd~9nq?loA z8-+uoZe6?~A>a7TfppuoB4Nr)Y2g+1z>H6C=f+Ddqt<&P4ic!L>8ZM~nf=Jpg@rE% zIMc!ISDhy4Z7km_g>U@5u0OLZv08VT{boWt3B*w7pK zT8FVoKcp&=IdwxLp^$k_Q|v}6e|pWtNRN%cLUI+KtKajdb&!(y#&CxGMVeB8w)8s6hI4ySPnFHyh=@b8yr_2lCU=vO{Udi5vvJ}+zeH^*S24GS3 zE@fr1Lo=@}nb!XdwvG_P$l}O)lIUgj*KSns!6IZgEdhn>g^ORJ^M@#w^aS3($p_oW zifwS}M7}{)v9KtdyHAmm02OIpc)(gz^Lzs{}i+XBZ|lp#{a zuI4{dD(dPoIy^GwHpV*cn#K;Um>Jc@)lJ&U*afHzQ8xaOh9i-{mH==USjODd)WzD# z&Cvx6!&tGv<>7y}7%*)B8b;OF9=LHV^*iYA_5Wi70@H+wv73wa@l|AgC=@d;fd4-! z%#~ySIW^#hG;j;~_`Wm4|-0M859tN{Qz z*}1#gTRXVB0;ijRd(@CC)@E*205LGb;nyqK$Nc%}-29jSzi{xFqyGoH07IDm1i%ylKr{t_HJcDZ2#i9YKxjY> z3Ibe*1JgDFI8KBKNB~dFdrWx*aL(yCMhIfc|Gx#$&-VzREGA%J{0vCIJq?3m2p}W? z1OO0P2rLL34nhH_NMJgJ2`E6|Fm;hY$G^h>$^z{kr-3ydToCw( z01%LZ=;IhI2;d9kqhN5LgWuZ~0NOH6RxlnfN6f%L7IxeuiUN`5_Y+ zdH6M8@H&15U|?k9XTbCv1w{fp1aQU3zzG2@1n>kS7l01>HT;x`pD~6g0N;Vrn?U?q zIOg^D_n0#O1dLo@xQdDYJ>L22idF`gCy(bsU_u6nc&wz9!7$7k0#H{f;Nt^;KuQe^ zaP~OQ7!1c)J3yWZ7+^Ax0s%8N{D*@3t|b7bAD1u#!;jStW;TcaXy^O<2LI8P1wh~L zFpky5u{RX}Z3zg>cMw1H4M5amh}M97e^1$hfsP*M*#Tn-lL7&n0TA}%JO?nqlH-&k zFk*hB01b7#i3&8}1O~jH$M1hCvf~Cozi14B9}T%+)ZcMYSFpg3j$u@qz>lVWsK_7P zbHk`apfu=*8U#*!9M{EY#$)RrXxsxBMc;G1fC2J7b*w~@-<$mRn<<#*pK3`C7!2Q= z|Mxuxv7hfHVZZA1f4-suk(LAsK}?OoFpP$PNW%Z`V*G%r1qwoe__!$I|11hDS^kA6 z@P8JA@&hXQ7@`mW@fQt+>BtYn|Lx5$g86UeugiWp7~jA47vFcq4$S!&0{>e9L(rcz z`L4>pe~$*DWNn5qYk)C{sQ|ceq#fM>)q6~qA4i`7uj{{+rGbyGV2n3Tz{+y6b9A$_ zHUWDe_=Wi4ykILgHz!wN2*m!MSNx7HmRukRU~QSXn*!f(`L&jlnFZLy*whwi@n$RBxVz&87> z91@r}{>X#>ITnB!<`?|jT#T*l%w3MZ*{9g;&wb0!GsV{6o`#Y_Ocx4{{i+Z>NEfV literal 0 HcmV?d00001 diff --git a/docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.svg b/docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.svg new file mode 100644 index 0000000000..b393040559 --- /dev/null +++ b/docs/user/examples/strikeslip-2d/figs/step07b_cfcatmip-results.svg @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/examples/strikeslip-2d/step04-varslip.md b/docs/user/examples/strikeslip-2d/step04-varslip.md index abb340a14d..1119f0cb34 100644 --- a/docs/user/examples/strikeslip-2d/step04-varslip.md +++ b/docs/user/examples/strikeslip-2d/step04-varslip.md @@ -24,7 +24,7 @@ Boundary conditions for static coseismic slip. We set the x and y displacement to zero on the +x and -x boundaries and prescribe left-lateral slip that varies along strike. ::: -For greater accuracy in modeling the spatial variation in slip, we use a basis order of 2 for the solution subfields. +For greater accuracy in modeling the spatial variation in slip, we refine the mesh by a factor of 2 and use a basis order of 2 for the solution subfields. ```{code-block} cfg --- @@ -93,12 +93,15 @@ Prescribed left-lateral slip that varies along the strike of the fault. A strike of 0 corresponds to y=0. ::: -We use a `SimpleDB` to define the spatial variation in slip. +We use a `SimpleGridDB` to define the spatial variation in slip. ```{code-block} cfg --- -caption: Prescribed slip parameters for Step 4. +caption: Prescribed slip parameters for Step 4. We refine the fault mesh by a factor of 8 (3 levels of refinement by a factor of 2) so that the output, which uses a basis order of 1, better captures the discretization of slip, which uses a basis order of 2. --- +[pylithapp.problem.interfaces.fault] +observers.observer.refine_levels = 3 + [pylithapp.problem.interfaces.fault.eq_ruptures.rupture] db_auxiliary_field = spatialdata.spatialdb.SimpleDB db_auxiliary_field.description = Fault rupture auxiliary field spatial database diff --git a/docs/user/examples/strikeslip-2d/step05-greensfns.md b/docs/user/examples/strikeslip-2d/step05-greensfns.md index 239ff0a66e..a050fccf03 100644 --- a/docs/user/examples/strikeslip-2d/step05-greensfns.md +++ b/docs/user/examples/strikeslip-2d/step05-greensfns.md @@ -25,14 +25,12 @@ In the fault interfaces section we set the fault type to `FaultCohesiveImpulses` We also use a spatial database to limit the section of the fault where we impose the fault slip impulses to -25 km $\le$ y $\le$ +25 km. :::{important} -**Currently, a basis order of 1 (default) for the slip auxiliary subfield is the only choice that gives accurate results in a slip inversion due to the factors described here.** +**Currently, we recommend a basis order of 1 (default) for the slip auxiliary subfield.** The basis order for the slip auxiliary subfield controls the representation of the slip field for the impulses. For a given impulse, a basis order of 1 will impose unit slip at a vertex with zero slip at all other vertices. -Likewise, a basis order of 0 will attempt to impose unit slip over a cell with zero slip in all other cells; however, this creates a jump in slip at the cell boundaries that cannot be accurately represented by the finite-element solution. -As a result, you should not use a basis order of 0 for the slip auxiliary field. -A basis order of 2 will impose slip at vertices as well as edge degrees of freedom in the cell. -Because PyLith output decimates the basis order to 0 or 1, you should avoid this choice of basis order as well until we provide better ways to output fields discretized with higher order basis functions. +A basis order of 0 will impose unit slip over a cell with zero slip in all other cells; however, this creates jumps in the slip at the cell boundaries and reduces the accuracy of the slip inversion for a given mesh resolution. +A basis order of 2 will impose slip at vertices as well as edge degrees of freedom in the cell; regularization becomes trickier with the higher order discretization, and a basis order of 2 does not always give more accurate results for a given number of impulses. ::: ```{code-block} cfg @@ -112,16 +110,24 @@ We get warnings about unused PETSc options because we do not use time stepping. ## Visualizing the results +In {numref}`fig:example:strikeslip:2d:step05:impulses` we use the `viz/plot_slip_impulses.py` Pyhon script to visualize the slip impulses. In {numref}`fig:example:strikeslip:2d:step05:solution` we use the `pylith_viz` utility to visualize the y displacement field. You can move the slider or use the `p` and `n` keys to change the increment or decrement slip impulses (shown as different time stamps). ```{code-block} console --- -caption: Visualize PyLith output using `pylith_viz`. +caption: Plot the slip impulses and visualize PyLith output using `pylith_viz`. --- +viz/plot_slip_impulses.py pylith_viz --filename=output/step05_greensfns-domain.h5 warp_grid --component=y ``` +:::{figure-md} fig:example:strikeslip:2d:step05:impulses +Slip impulses for the Green's functions in Step 5. + +Slip impulses for the Green's functions in Step 5. +::: + :::{figure-md} fig:example:strikeslip:2d:step05:solution Solution for Step 5. The colors indicate the y displacement, and the deformation is exaggerated by a factor of 1000. diff --git a/docs/user/examples/strikeslip-2d/step06-inversion-leastsquares.md b/docs/user/examples/strikeslip-2d/step06-inversion-leastsquares.md index 8fdd519ae3..5aabd81916 100644 --- a/docs/user/examples/strikeslip-2d/step06-inversion-leastsquares.md +++ b/docs/user/examples/strikeslip-2d/step06-inversion-leastsquares.md @@ -16,7 +16,7 @@ $ ./invert_slip.py $ ./invert_slip.py --help ``` -By default, the inversion code will write the results of the inversion to `output/step06_greensfns-inversion_results.txt`. +By default, the inversion code will write the results of the inversion to `output/step06_inversion-results.txt`. ## Plotting the results @@ -26,18 +26,18 @@ If you are using the PyLith binary, which includes the `matplotlib` Python modul --- caption: Plot the inversion results using the `matplotlib` Python module. --- -$ ./viz/plot_inversion_results.py +$ viz/plot_inversion_results.py ``` :::{figure-md} fig:example:strikeslip:2d:step06:solution -Results of slip inversion in Step 6. +Results of slip inversion in Step 6. Results of slip inversion in Step 6. -The thick black line shows the prescribed slip in Step 4. +The thick black line shows the prescribed slip in Step 4, and the thick gray line shows the raw (exact) slip. The thin colored lines show the slip from the inversion with different penalty factors. ::: ::{tip} -You can pass`--no-gui` as a command line argument to the plotting script turn off displaying the plot window. +You can pass`--no-gui` as a command line argument to the plotting script to turn off displaying the plot window. This is useful if you do not have a matplotlib GUI backend. ::: diff --git a/docs/user/examples/strikeslip-2d/step07-inversion-catmip.md b/docs/user/examples/strikeslip-2d/step07-inversion-catmip.md index c242e813ed..9a5edf6ee6 100644 --- a/docs/user/examples/strikeslip-2d/step07-inversion-catmip.md +++ b/docs/user/examples/strikeslip-2d/step07-inversion-catmip.md @@ -74,10 +74,10 @@ viz/plot_catmip_results.py --catmip-theta=output/step07a_catmip-theta20.bin ``` :::{figure-md} fig:example:strikeslip:2d:step07a:solution -Results of slip inversion in Step 7a. +Results of slip inversion in Step 7a. Results of slip inversion in Step 7a. -The thick black line shows the prescribed slip in Step 4. +The thick black line shows the prescribed slip in Step 4, and the thick gray line shows the raw (exact) slip. The solid orange line shows the median slip, the shaded orange regions shows the median plus and minus one standard deviation, and the dashed lines show the minimum and maximum values. The median values are almost identical to the results with minimal smoothing in Step 6. ::: @@ -157,10 +157,10 @@ viz/plot_catmip_results.py --catmip-theta=output/step07b_cfcatmip-theta1.bin ``` :::{figure-md} fig:example:strikeslip:2d:step07b:solution -Results of slip inversion in Step 7b. +Results of slip inversion in Step 7b. Results of slip inversion in Step 7b. -The thick black line shows the prescribed slip in Step 4. +The thick black line shows the prescribed slip in Step 4, and the thick gray line shows the raw (exact) slip. The solid orange line shows the median slip, the shaded orange regions shows the median plus and minus one standard deviation, and the dashed lines show the minimum and maximum values. The results are almost identical to those in Step 7a. ::: From 71959b415b586b5a0df5302b2b2c819fde5492aa Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:10:35 -0600 Subject: [PATCH 16/18] DOCS: Add discussion of refining output to OutputObservers. --- docs/user/problems/output.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/user/problems/output.md b/docs/user/problems/output.md index 15bb50402c..06517920ef 100644 --- a/docs/user/problems/output.md +++ b/docs/user/problems/output.md @@ -79,6 +79,13 @@ a_z &= a_n n_z + a_h h_z + a_v v_z This transformation is useful for plotting fault tractions and slip in 3D visualization tools such as ParaView that require vectors in the model coordinate system. +*New in v4.2.0* + +Output observers can output information on a finer resolution mesh than the one used in the simulaiton. +This is useful when using a basis order of 2 or greater for the discretization of the solution and writing output at a basis order of 1. +In this case, output using a mesh that is 4-8 times finer and fields discretized using a basis order of 1 (usually required by visualization tools) will do a good job representing the fields with a basis order of 2 on the mesh used in the simulation. +This feature is used in [`examples/strikeslip-2d/step04-varslip`](../examples/strikeslip-2d/step04-varslip.md). + (sec-user-solution-observers)= ### Solution Observers From 4d283db75db1d8e4a87db1673f700aacc6bf9983 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Fri, 18 Oct 2024 15:10:50 -0600 Subject: [PATCH 17/18] Update list of changes. --- CHANGES.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e2f725c72f..7514e18f1d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,16 +7,19 @@ The version numbers are in the form `MAJOR.MINOR.PATCH`, where major releases in ## Version 4.2.0 +* **Changed** + * Updated `examples/strikeslip-2d` Steps 4-7 to use a more realistic slip distribution and mesh refinement in output. + * Updated to PETSc 3.22.0 + * Switch CI from Azure Pipelines to GitHub Actions. * **Added** * Default filenames for progress monitor and parameters file are set from the simulation name like the other output files. * Consistency check for material properties and scales used in nondimensionalization (currently just the shear modulus). * Add section to User Guide on troubleshooting solver issues. -* **Changed** - * Switch CI from Azure Pipelines to GitHub Actions. + * Allow output on a finer resolution mesh than used in the simulation to facilitate accurate representation of fields with a basis order of 2 or greater. * **Fixed** * Fix inconsistency in normal direction on fault surfaces. Orientation was correct but direction was flipped at some locations. This affected local slip direction and the resulting deformation close to the fault. This bug fix was not in version 4.1.3. - * Update autoconf macros for numpy for compatibility with location of include files in numpy version 2.x. + * Update autoconf numpy macros for compatibility with location of include files in numpy version 2.x. ## Version 4.1.3 (2024/07/31) From e4aa7e1d36f30548b90f24b1a8f526e2d30fc171 Mon Sep 17 00:00:00 2001 From: Brad Aagaard Date: Sat, 11 Jan 2025 09:37:58 -0700 Subject: [PATCH 18/18] Update full-scale test to include refining output. --- .../linearelasticity/faults-2d/Makefile.am | 3 ++ .../faults-2d/TestShearNoSlip.py | 26 ++++++++++ .../linearelasticity/faults-2d/meshes.py | 52 +++++++++++++++++++ .../faults-2d/shearnoslip_refineoutput.cfg | 31 +++++++++++ .../shearnoslip_refineoutput_quad.cfg | 16 ++++++ .../shearnoslip_refineoutput_tri.cfg | 16 ++++++ 6 files changed, 144 insertions(+) create mode 100644 tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput.cfg create mode 100644 tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_quad.cfg create mode 100644 tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_tri.cfg diff --git a/tests/fullscale/linearelasticity/faults-2d/Makefile.am b/tests/fullscale/linearelasticity/faults-2d/Makefile.am index c111ba7e10..f33c46e043 100644 --- a/tests/fullscale/linearelasticity/faults-2d/Makefile.am +++ b/tests/fullscale/linearelasticity/faults-2d/Makefile.am @@ -43,6 +43,9 @@ dist_noinst_DATA = \ shearnoslip.cfg \ shearnoslip_quad.cfg \ shearnoslip_tri.cfg \ + shearnoslip_refineoutput.cfg \ + shearnoslip_refineoutput_quad.cfg \ + shearnoslip_refineoutput_tri.cfg \ zeroslipfn.timedb diff --git a/tests/fullscale/linearelasticity/faults-2d/TestShearNoSlip.py b/tests/fullscale/linearelasticity/faults-2d/TestShearNoSlip.py index c5caa5de66..6cc3641fe4 100644 --- a/tests/fullscale/linearelasticity/faults-2d/TestShearNoSlip.py +++ b/tests/fullscale/linearelasticity/faults-2d/TestShearNoSlip.py @@ -103,11 +103,37 @@ def setUp(self): return +# ------------------------------------------------------------------------------------------------- +class TestQuadGmshRefineOutput(TestCase): + + def setUp(self): + self.name = "shearnoslip_refineoutput_quad" + self.mesh = meshes.QuadGmshRefineOutput() + super().setUp() + + TestCase.run_pylith(self, self.name, ["shearnoslip.cfg", "shearnoslip_refineoutput.cfg", "shearnoslip_refineoutput_quad.cfg"]) + return + + +# ------------------------------------------------------------------------------------------------- +class TestTriGmshRefineOutput(TestCase): + + def setUp(self): + self.name = "shearnoslip_refineoutput_tri" + self.mesh = meshes.TriGmshRefineOutput() + super().setUp() + + TestCase.run_pylith(self, self.name, ["shearnoslip.cfg", "shearnoslip_refineoutput.cfg", "shearnoslip_refineoutput_tri.cfg"]) + return + + # ------------------------------------------------------------------------------------------------- def test_cases(): return [ TestQuadGmsh, TestTriGmsh, + TestQuadGmshRefineOutput, + TestTriGmshRefineOutput, ] diff --git a/tests/fullscale/linearelasticity/faults-2d/meshes.py b/tests/fullscale/linearelasticity/faults-2d/meshes.py index cd990f37cf..c6dd00d6f8 100644 --- a/tests/fullscale/linearelasticity/faults-2d/meshes.py +++ b/tests/fullscale/linearelasticity/faults-2d/meshes.py @@ -63,6 +63,58 @@ class QuadGmsh(object): } +class TriGmshRefineOutput(object): + """Mesh information for tri mesh using Gmsh with 1 level of refinement for output. + """ + ENTITIES = { + "domain": MeshEntity(ncells=164*4, ncorners=3, nvertices=361+2*(9+8)), + "points": MeshEntity(ncells=3, ncorners=1, nvertices=3), + + # Materials + "mat_xneg": MeshEntity(ncells=38*4, ncorners=3, nvertices=97), + "mat_xmid": MeshEntity(ncells=38, ncorners=3, nvertices=30), + "mat_xposypos": MeshEntity(ncells=44, ncorners=3, nvertices=31), + "mat_xposyneg": MeshEntity(ncells=44, ncorners=3, nvertices=31), + + # Faults + "fault_xmid": MeshEntity(ncells=8*2, ncorners=2, nvertices=9+8), + "fault_xneg": MeshEntity(ncells=8, ncorners=2, nvertices=9), + + # Boundaries + "bc_xneg": MeshEntity(ncells=8, ncorners=2, nvertices=9), + "bc_xpos": MeshEntity(ncells=8*2, ncorners=2, nvertices=9+8), + "bc_yneg": MeshEntity(ncells=8, ncorners=2, nvertices=9+2), + "bc_ypos": MeshEntity(ncells=8*2, ncorners=2, nvertices=9+8+2), + "boundary_ypos": MeshEntity(ncells=16, ncorners=2, nvertices=17+2), + } + + +class QuadGmshRefineOutput(object): + """Mesh information for quad mesh using Gmsh with 1 level of refinement for output. + """ + ENTITIES = { + "domain": MeshEntity(ncells=100*4, ncorners=4, nvertices=(11+10)**2 + 2*(11+10)), + "points": MeshEntity(ncells=3, ncorners=1, nvertices=3), + + # Materials + "mat_xneg": MeshEntity(ncells=30*4, ncorners=3, nvertices=147), + "mat_xmid": MeshEntity(ncells=20, ncorners=3, nvertices=33), + "mat_xposypos": MeshEntity(ncells=25, ncorners=3, nvertices=36), + "mat_xposyneg": MeshEntity(ncells=25, ncorners=3, nvertices=36), + + # Faults + "fault_xmid": MeshEntity(ncells=20*2, ncorners=2, nvertices=11+10), + "fault_xneg": MeshEntity(ncells=10, ncorners=2, nvertices=11), + + # Boundaries + "bc_xneg": MeshEntity(ncells=10, ncorners=2, nvertices=11), + "bc_xpos": MeshEntity(ncells=20*2, ncorners=2, nvertices=11+10), + "bc_yneg": MeshEntity(ncells=11, ncorners=2, nvertices=11+2), + "bc_ypos": MeshEntity(ncells=11*2, ncorners=2, nvertices=11+10+2), + "boundary_ypos": MeshEntity(ncells=11*2, ncorners=2, nvertices=11+10+2), + } + + class TriCubit(object): """Mesh information for tri mesh using Cubit. """ diff --git a/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput.cfg b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput.cfg new file mode 100644 index 0000000000..329d370471 --- /dev/null +++ b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput.cfg @@ -0,0 +1,31 @@ +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem.solution_observers] +domain.refine_levels = 1 +boundary_ypos.refine_levels = 1 + + +# ---------------------------------------------------------------------- +# materials +# ---------------------------------------------------------------------- +[pylithapp.problem.materials] +mat_xneg.observers.observer.refine_levels = 1 + + +# ---------------------------------------------------------------------- +# faults +# ---------------------------------------------------------------------- +[pylithapp.problem.interfaces] +fault_xmid.observers.observer.refine_levels = 1 + + +# ---------------------------------------------------------------------- +# boundary conditions +# ---------------------------------------------------------------------- +[pylithapp.problem.bc] +bc_xpos.observers.observer.refine_levels = 1 +bc_ypos.observers.observer.refine_levels = 1 + + +# End of file diff --git a/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_quad.cfg b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_quad.cfg new file mode 100644 index 0000000000..79aaa60f3d --- /dev/null +++ b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_quad.cfg @@ -0,0 +1,16 @@ +[pylithapp.metadata] +base = [pylithapp.cfg, shearnoslip.cfg, shearnoslip_refineoutput.cfg] +keywords = [quadrilateral cells] +arguments = [shearnoslip_refineoutput.cfg, shearnoslip_refineoutput_quad.cfg] + +[pylithapp.problem] +defaults.name = shearnoslip_refineoutput_quad + +# ---------------------------------------------------------------------- +# mesh_generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator.reader] +filename = mesh_quad.msh + + +# End of file diff --git a/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_tri.cfg b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_tri.cfg new file mode 100644 index 0000000000..9652448ad5 --- /dev/null +++ b/tests/fullscale/linearelasticity/faults-2d/shearnoslip_refineoutput_tri.cfg @@ -0,0 +1,16 @@ +[pylithapp.metadata] +base = [pylithapp.cfg, shearnoslip.cfg, shearnoslip_refineoutput.cfg] +keywords = [triangular cells] +arguments = [shearnoslip_refineoutput.cfg, shearnoslip_refineoutput_tri.cfg] + +[pylithapp.problem] +defaults.name = shearnoslip_refineoutput_tri + +# ---------------------------------------------------------------------- +# mesh_generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator.reader] +filename = mesh_tri.msh + + +# End of file