From c1861f166f0021a5a17102f8c2b95155dc653f9c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Mon, 12 Jun 2023 17:01:47 -0600 Subject: [PATCH 01/65] Initial commit. Adding in source class. --- .../sources/AuxiliaryFactoryPointForce.cc | 110 ++++++ .../sources/AuxiliaryFactoryPointForce.hh | 60 ++++ libsrc/pylith/sources/Makefile.am | 37 ++ libsrc/pylith/sources/PointForce.cc | 336 ++++++++++++++++++ libsrc/pylith/sources/PointForce.hh | 166 +++++++++ libsrc/pylith/sources/RickerWavelet.cc | 98 +++++ libsrc/pylith/sources/RickerWavelet.hh | 81 +++++ libsrc/pylith/sources/Source.cc | 153 ++++++++ libsrc/pylith/sources/Source.hh | 142 ++++++++ .../sources/SourceTimeFunctionPointForce.cc | 87 +++++ .../sources/SourceTimeFunctionPointForce.hh | 111 ++++++ libsrc/pylith/sources/sourcesfwd.hh | 52 +++ 12 files changed, 1433 insertions(+) create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh create mode 100644 libsrc/pylith/sources/Makefile.am create mode 100644 libsrc/pylith/sources/PointForce.cc create mode 100644 libsrc/pylith/sources/PointForce.hh create mode 100644 libsrc/pylith/sources/RickerWavelet.cc create mode 100644 libsrc/pylith/sources/RickerWavelet.hh create mode 100644 libsrc/pylith/sources/Source.cc create mode 100644 libsrc/pylith/sources/Source.hh create mode 100644 libsrc/pylith/sources/SourceTimeFunctionPointForce.cc create mode 100644 libsrc/pylith/sources/SourceTimeFunctionPointForce.hh create mode 100644 libsrc/pylith/sources/sourcesfwd.hh diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc new file mode 100644 index 0000000000..420b688d0d --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactoryPointForce.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactoryPointForce::AuxiliaryFactoryPointForce(void) { + GenericComponent::setName("auxiliaryfactorypointforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactoryPointForce::~AuxiliaryFactoryPointForce(void) {} + + +// ---------------------------------------------------------------------------- +// Add isotropic permeability subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryPointForce::addMomentTensor(void) { // momentTensor + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTensorPermeability(void)"); + + const char* subfieldName = "moment_tensor"; + const char* componentNames[6] = { + "moment_tensor_xx", + "moment_tensor_yy", + "moment_tensor_zz", + "moment_tensor_xy", + "moment_tensor_yz", + "moment_tensor_xz" + }; + const int tensorSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; + const PylithReal pressureScale = _normalizer->getPressureScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::OTHER; + description.numComponents = tensorSize; + description.componentNames.resize(tensorSize); + for (int i = 0; i < tensorSize; ++i) { + description.componentNames[i] = componentNames[i]; + } // for + description.scale = pressureScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addMomentTensor + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryPointForce::addTimeDelay(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay + + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh new file mode 100644 index 0000000000..de18a30adc --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh @@ -0,0 +1,60 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/AuxiliaryFactoryPointForce.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorypointforce_hh) +#define pylith_sources_auxiliaryfactorypointforce_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField + +class pylith::sources::AuxiliaryFactoryPointForce : public pylith::feassemble::AuxiliaryFactory { + friend class TestAuxiliaryFactoryPointForce; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + AuxiliaryFactoryPointForce(void); + + /// Destructor. + virtual ~AuxiliaryFactoryPointForce(void); + + /// Add fluid density subfield to auxiliary subfields. + void addMomentTensor(void); + + /// Add fluid viscosity subfield to auxiliary subfields. + void addTimeDelay(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + AuxiliaryFactoryPointForce(const AuxiliaryFactoryPointForce &); ///< Not implemented. + const AuxiliaryFactoryPointForce& operator=(const AuxiliaryFactoryPointForce&); ///< Not implemented + +}; // class AuxiliaryFactoryPointForce + +#endif // pylith_sources_auxiliaryfactorypointforce_hh + +// End of file diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am new file mode 100644 index 0000000000..4f17e38f0e --- /dev/null +++ b/libsrc/pylith/sources/Makefile.am @@ -0,0 +1,37 @@ +# -*- Makefile -*- +# +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo + +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2017 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# + +subpackage = sources +include $(top_srcdir)/subpackage.am + +subpkginclude_HEADERS = \ + Source.hh \ + WellboreSource.hh \ + PointForce.hh \ + AuxiliaryFactoryWellboreSource.hh \ + AuxiliaryFactoryPointForce.hh \ + DerivedFactoryPointForce.hh \ + AuxiliaryFactorySourceTime.hh \ + RickerWavelet.hh \ + sourcesfwd.hh + + +noinst_HEADERS = + + +# End of file \ No newline at end of file diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc new file mode 100644 index 0000000000..ec6168fab7 --- /dev/null +++ b/libsrc/pylith/sources/PointForce.cc @@ -0,0 +1,336 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/PointForce.hh" // implementation of object methods + +#include "pylith/sources/SourceTimeFunctionPointForce.hh" // HASA SourceTimeFunctionPointSource +#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // USES AuxiliaryFactoryPointForce +#include "pylith/sources/DerivedFactoryPointForce.hh" // USES DerivedFactoryPointForce +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::PointForce::PointForce(void) : + _sourceTimeFunction(NULL), + _derivedFactory(new pylith::sources::DerivedFactoryPointForce) { + pylith::utils::PyreComponent::setName("pointforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::PointForce::~PointForce(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::PointForce::deallocate(void) { + Source::deallocate(); + + delete _derivedFactory;_derivedFactory = NULL; + _sourceTimeFunction = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Set source time function. +void +pylith::sources::PointForce::setSourceTimeFunction(pylith::sources::SourceTimeFunctionPointForce* const sourceTimeFunction) { + _sourceTimeFunction = sourceTimeFunction; +} // setSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Get bulk source time function. +pylith::sources::SourceTimeFunctionPointForce* +pylith::sources::PointForce::getSourceTimeFunction(void) const { + return _sourceTimeFunction; +} // getSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void +pylith::sources::PointForce::verifyConfiguration(const pylith::topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution="<setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + printf("In PointForce end\n"); + DMView(dmSoln, NULL); + + _setKernelsResidual(integrator, solution); + _setKernelsJacobian(integrator, solution); + _setKernelsUpdateStateVars(integrator, solution); + _setKernelsDerivedField(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field* +pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution="<setLabel("PointForce auxiliary field"); + + assert(_sourceTimeFunction); + pylith::sources::AuxiliaryFactoryPointForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); + + assert(_normalizer); + auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + auxiliaryFactory->addMomentTensor(); // 0 + auxiliaryFactory->addTimeDelay(); // 1 + + _sourceTimeFunction->addAuxiliarySubfields(); + + auxiliaryField->subfieldsSetup(); + auxiliaryField->createDiscretization(); + pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); + auxiliaryField->allocate(); + auxiliaryField->createOutputVector(); + + assert(auxiliaryFactory); + auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("Point auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field* +pylith::sources::PointForce::createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution="<getAuxiliaryFactory(); +} // _getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Update kernel constants. +void +pylith::sources::PointForce::_updateKernelConstants(const PylithReal dt) { + assert(_sourceTimeFunction); + _sourceTimeFunction->updateKernelConstants(&_kernelConstants, dt); +} // _updateKernelConstants + + +// --------------------------------------------------------------------------------------------------------------------- +// Get derived factory associated with physics. +pylith::topology::FieldFactory* +pylith::sources::PointForce::_getDerivedFactory(void) { + return _derivedFactory; +} // _getDerivedFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for RHS residual G(t,s). +void +pylith::sources::PointForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator="< kernels; + + switch (_formulation) { + case QUASISTATIC: { + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + case DYNAMIC: { + // Velocity + const PetscPointFunc g0v = NULL; + const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); + + kernels.resize(1); + kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsResidual + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for RHS Jacobian G(t,s). +void +pylith::sources::PointForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; + _sourceTimeFunction->addKernelsUpdateStateVars(&kernels, coordsys); + + integrator->setKernelsUpdateStateVars(kernels); + + PYLITH_METHOD_END; +} // _setKernelsUpdateStateVars + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for computing derived field. +void +pylith::sources::PointForce::_setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsDerivedField(integrator="< + +#include "pylith/sources/RickerWavelet.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/fekernels/RickerWavelet.hh" // USES RickerWavelet kernels +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::RickerWavelet::RickerWavelet(void) : + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + pylith::utils::PyreComponent::setName("rickerwavelet"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::RickerWavelet::~RickerWavelet(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::RickerWavelet::deallocate(void) { + SourceTimeFunctionPointForce::deallocate(); + + delete _auxiliaryFactory;_auxiliaryFactory = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::sources::AuxiliaryFactoryPointForce* +pylith::sources::RickerWavelet::getAuxiliaryFactory(void) { + return _auxiliaryFactory; +} // getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Add source time subfields to auxiliary field. +void +pylith::sources::RickerWavelet::addAuxiliarySubfields(void) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addAuxiliarySubfields(void)"); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise + // functions (kernels). + + _auxiliaryFactory->addCenterFrequency(); // numA - 1 + + PYLITH_METHOD_END; +} // addAuxiliarySubfields + + +// --------------------------------------------------------------------------------------------------------------------- +// Get g1v kernel for residual, G(t,s). +PetscPointFunc +pylith::sources::RickerWavelet::getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("getKernelg1v_explicit(coordsys="<getSpaceDim(); + PetscPointFunc g1v = + (3 == spaceDim) ? pylith::fekernels::RickerWavelet3D::g1v : + (2 == spaceDim) ? pylith::fekernels::RickerWaveletPlaneStrain::g1v : + NULL; + + PYLITH_METHOD_RETURN(g1v); +} // getKernelResidualStress + + +// End of file diff --git a/libsrc/pylith/sources/RickerWavelet.hh b/libsrc/pylith/sources/RickerWavelet.hh new file mode 100644 index 0000000000..2cada14fbc --- /dev/null +++ b/libsrc/pylith/sources/RickerWavelet.hh @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/RickerWavelet.hh + * + * @brief C++ class for Ricker source time function. + */ + +#if !defined(pylith_materials_rickerwavelet_hh) +#define pylith_materials_rickerwavelet_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/SourceTimeFunctionPointForce.hh" // ISA SourceTimeFunctionPointForce + +class pylith::sources::RickerWavelet : public pylith::sources::SourceTimeFunctionPointForce { + friend class TestRickerWavelet; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + RickerWavelet(void); + + /// Destructor. + ~RickerWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryPointForce* getAuxiliaryFactory(void); + + /** Add source time subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v. + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + RickerWavelet(const RickerWavelet&); ///< Not implemented. + const RickerWavelet& operator=(const RickerWavelet&); /// Not implemented. + +}; // class RickerWavelet + +#endif // pylith_materials_rickerwavelet_hh + +// End of file diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc new file mode 100644 index 0000000000..fcbfd38223 --- /dev/null +++ b/libsrc/pylith/sources/Source.cc @@ -0,0 +1,153 @@ +// -*- C++ -*- +// +// --------------------------------------------------------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// --------------------------------------------------------------------------------------------------------------------- +// + +#include + +#include "Source.hh" // implementation of object methods + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include // USES assert() +#include // USES std::runtime_error + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::Source::Source(void) : + _description(""), + _labelName(""), + _labelValue(1) { + // +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::Source::~Source(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::Source::deallocate(void) { + PYLITH_METHOD_BEGIN; + + pylith::problems::Physics::deallocate(); + + PYLITH_METHOD_END; +} // deallocate + + +// ------------------------------------------------------------------------------------------------ +// Set descriptive label of source. +void +pylith::sources::Source::setDescription(const char* value) { + PYLITH_COMPONENT_DEBUG("setDescription(value="< +pylith::sources::Source::createConstraints(const pylith::topology::Field& solution) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createConstraints(solution="< constraintArray; + + PYLITH_METHOD_RETURN(constraintArray); +} // createConstraints + + +// ------------------------------------------------------------------------------------------------ +// Set point names and coordinates of points . +void +pylith::sources::Source::setPoints(const PylithReal* pointCoords, + const int numPoints, + const int spaceDim, + const char* const* pointNames, + const int numPointNames) { + PYLITH_METHOD_BEGIN; + + assert(pointCoords && pointNames); + assert(numPoints == numPointNames); + + // Copy point coordinates. + const PylithInt size = numPoints * spaceDim; + _pointCoords.resize(size); + for (PylithInt i = 0; i < size; ++i) { + _pointCoords[i] = pointCoords[i]; + } // for + + // Copy point names. + _pointNames.resize(numPointNames); + for (PylithInt i = 0; i < numPointNames; ++i) { + _pointNames[i] = pointNames[i]; + } // for + + PYLITH_METHOD_END; +} // setPoints diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh new file mode 100644 index 0000000000..8955fd704d --- /dev/null +++ b/libsrc/pylith/sources/Source.hh @@ -0,0 +1,142 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/Source.hh + * + * @brief C++ abstract base class for sources. + */ + +#if !defined(pylith_sources_source_hh) +#define pylith_sources_source_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/topology/topologyfwd.hh" +#include "pylith/utils/petscfwd.h" +#include "spatialdata/geocoords/geocoordsfwd.hh" // USES CoordSys +#include "pylith/problems/Physics.hh" // ISA Physics + +#include // HASA std::string + +// Source ------------------------------------------------------------- +/** @brief C++ abstract base class for sources. + * + */ + +class pylith::sources::Source : public pylith::problems::Physics { + friend class TestSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + Source(void); + + /// Destructor. + virtual ~Source(void); + + /// Deallocate PETSc and local data structures. + virtual + void deallocate(void); + + /** Set descriptive label for source. + * + * @param value Label of source. + */ + void setDescription(const char* value); + + /** Get descruptive label of source. + * + * @returns Label of source + */ + const char* getDescription(void) const; + + /** Set name of label marking boundary associated with boundary condition surface. + * + * @param[in] value Name of label for surface (from mesh generator). + */ + void setLabelName(const char* value); + + /** Get name of label marking boundary associated with source location. + * + * @returns Name of label for surface (from mesh generator). + */ + const char* getLabelName(void) const; + + /** Set value of label marking boundary associated with source location. + * + * @param[in] value Value of label for surface (from mesh generator). + */ + void setLabelValue(const int value); + + /** Get value of label marking boundary associated with source location. + * + * @returns Value of label for surface (from mesh generator). + */ + int getLabelValue(void) const; + + /** Set first choice for reference direction to discriminate among tangential directions in 3-D. + * + * @param vec Reference direction unit vector. + * /** Create constraint and set kernels. + * + * @param[in] solution Solution field. + * @returns Constraint if applicable, otherwise NULL. + */ + virtual + std::vector createConstraints(const pylith::topology::Field& solution); + + /** Set coordinates and names of points. + * + * @param[in] points Array of coordinates [numPoints * spaceDim]. + * @param[in] numPoints Number of points. + * @param[in] spaceDim Spatial dimension for coordinates. + * @param[in] pointNames Array with point names. + * @param[in] numPointNames Number of point banes. + */ + void setPoints(const PylithReal* pointCoords, + const int numPoints, + const int spaceDim, + const char* const* pointNames, + const int numPointNames); + + // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// +protected: + + pylith::scalar_array _pointCoords; ///< Array of point coordinates. + pylith::string_vector _pointNames; ///< Array of point names. + std::string _description; ///< Descriptive label for source. + std::string _labelName; ///< Name of label to identify source points in mesh. + int _labelValue; ///< Value of label to identify source points in mesh. + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + pylith::topology::Mesh* _pointMesh; ///< Mesh for points (no cells). + pylith::topology::Field* _pointSoln; ///< Solution field at points. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + Source(const Source&); ///< Not implemented. + const Source& operator=(const Source&); ///< Not implemented + +}; // Source + +#endif // pylith_sources_source_hh + +// End of file diff --git a/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc b/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc new file mode 100644 index 0000000000..3a23fa7b63 --- /dev/null +++ b/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc @@ -0,0 +1,87 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/SourceTimeFunctionPointForce.hh" // implementation of object methods + +#include "pylith/feassemble/Integrator.hh" // USES NEW_JACOBIAN_NEVER + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_DEBUG + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::SourceTimeFunctionPointForce::SourceTimeFunctionPointForce(void) : + _JacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_NEVER) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::SourceTimeFunctionPointForce::~SourceTimeFunctionPointForce(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::SourceTimeFunctionPointForce::deallocate(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Get triggers for needing to compute the elastic constants for the RHS Jacobian. +int +pylith::sources::SourceTimeFunctionPointForce::getJacobianTriggers(void) const { + return _JacobianTriggers; +} // getJacobianTriggers + + +// --------------------------------------------------------------------------------------------------------------------- +// Update kernel constants. +void +pylith::sources::SourceTimeFunctionPointForce::updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("updateKernelConstants(kernelConstants"<* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addKernelsUpdateStateVars(kernels="<* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const; + + /** Update kernel constants. + * + * @param[inout] kernelConstants Array of constants used in integration kernels. + * @param[in] dt Current time step. + */ + virtual + void updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const; + + // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// + + int _JacobianTriggers; ///< Triggers for needing to recompute the RHS Jacobian. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + SourceTimeFunctionPointForce(const SourceTimeFunctionPointForce&); ///< Not implemented. + const SourceTimeFunctionPointForce& operator=(const SourceTimeFunctionPointForce&); /// Not implemented. + +}; // class SourceTimeFunctionPointForce + +#endif // pylith_sources_sourcetimefunctionpointforce_hh + +// End of file diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh new file mode 100644 index 0000000000..b216673a9e --- /dev/null +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -0,0 +1,52 @@ +// -*- C++ -*- +// +// ====================================================================== +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ====================================================================== +// + +/** @file libsrc/sources/sourcesfwd.hh + * + * @brief Forward declarations for PyLith sources objects. + * + * Including this header file eliminates the need to use separate + * forward declarations. + */ + +#if !defined(pylith_sources_sourcesfwd_hh) +#define pylith_sources_sourcesfwd_hh + +namespace pylith { + namespace sources { + // New stuff + class Source; + + class PointForce; + class AuxiliaryFactoryPointForce; + class DerivedFactoryPointForce; + + class SourceTimeFunctionPointForce; + class AuxiliaryFactorySourceTime; + class RickerWavelet; + // class GaussianWavelet; + + // class WellboreSource; + // class AuxiliaryFactoryWellboreSource; + + } // sources +} // pylith + +#endif // pylith_sources_sourcesfwd_hh + +// End of file From 559e175c450f634002a66f87a01162d749b0e26f Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 13 Jun 2023 13:45:11 -0600 Subject: [PATCH 02/65] Rebased on new upstream --- configure.ac | 2 + libsrc/pylith/Makefile.am | 16 + libsrc/pylith/fekernels/GaussianWavelet.cc | 132 +++++++ libsrc/pylith/fekernels/GaussianWavelet.hh | 143 +++++++ libsrc/pylith/fekernels/Makefile.am | 9 +- libsrc/pylith/fekernels/PointForce.cc | 66 ++++ libsrc/pylith/fekernels/PointForce.hh | 83 +++++ libsrc/pylith/fekernels/RickerWavelet.cc | 136 +++++++ libsrc/pylith/fekernels/RickerWavelet.hh | 143 +++++++ libsrc/pylith/fekernels/SquarePulseSource.cc | 64 ++++ libsrc/pylith/fekernels/SquarePulseSource.hh | 83 +++++ libsrc/pylith/fekernels/WellboreSource.cc | 133 +++++++ libsrc/pylith/fekernels/WellboreSource.hh | 104 ++++++ libsrc/pylith/fekernels/fekernelsfwd.hh | 13 + libsrc/pylith/problems/Problem.cc | 55 ++- libsrc/pylith/problems/Problem.hh | 10 + .../AuxiliaryFactoryMomentTensorForce.cc | 110 ++++++ .../AuxiliaryFactoryMomentTensorForce.hh | 60 +++ .../sources/AuxiliaryFactoryPointForce.cc | 63 +--- .../sources/AuxiliaryFactoryPointForce.hh | 11 +- .../sources/AuxiliaryFactorySourceTime.cc | 69 ++++ .../sources/AuxiliaryFactorySourceTime.hh | 55 +++ .../AuxiliaryFactorySquarePulseSource.cc | 71 ++++ .../AuxiliaryFactorySquarePulseSource.hh | 56 +++ .../sources/AuxiliaryFactoryWellboreSource.cc | 276 ++++++++++++++ .../sources/AuxiliaryFactoryWellboreSource.hh | 78 ++++ .../DerivedFactoryMomentTensorForce.cc | 122 ++++++ .../DerivedFactoryMomentTensorForce.hh | 61 +++ libsrc/pylith/sources/GaussianWavelet.cc | 98 +++++ libsrc/pylith/sources/GaussianWavelet.hh | 81 ++++ libsrc/pylith/sources/Makefile.am | 19 +- libsrc/pylith/sources/MomentTensorForce.cc | 336 +++++++++++++++++ libsrc/pylith/sources/MomentTensorForce.hh | 167 +++++++++ libsrc/pylith/sources/PointForce.cc | 271 +++++++------- libsrc/pylith/sources/PointForce.hh | 85 ++--- libsrc/pylith/sources/RickerWavelet.cc | 4 +- libsrc/pylith/sources/RickerWavelet.hh | 6 +- libsrc/pylith/sources/Source.cc | 6 +- libsrc/pylith/sources/Source.hh | 6 +- .../SourceTimeFunctionMomentTensorForce.cc | 87 +++++ .../SourceTimeFunctionMomentTensorForce.hh | 112 ++++++ libsrc/pylith/sources/SquarePulseSource.cc | 339 +++++++++++++++++ libsrc/pylith/sources/SquarePulseSource.hh | 148 ++++++++ libsrc/pylith/sources/WellboreSource.cc | 352 ++++++++++++++++++ libsrc/pylith/sources/WellboreSource.hh | 148 ++++++++ libsrc/pylith/sources/sourcesfwd.hh | 23 +- modulesrc/Makefile.am | 1 + modulesrc/include/physicsarray.i | 42 +++ modulesrc/problems/Problem.i | 8 + modulesrc/sources/GaussianWavelet.i | 67 ++++ modulesrc/sources/Makefile.am | 76 ++++ modulesrc/sources/MomentTensorForce.i | 105 ++++++ modulesrc/sources/PointForce.i | 117 ++++++ modulesrc/sources/RickerWavelet.i | 67 ++++ modulesrc/sources/Source.i | 115 ++++++ .../SourceTimeFunctionMomentTensorForce.i | 84 +++++ .../sources/SourceTimeFunctionPointForce.i | 84 +++++ modulesrc/sources/SquarePulseSource.i | 117 ++++++ modulesrc/sources/WellboreSource.i | 117 ++++++ modulesrc/sources/sources.i | 68 ++++ pylith/Makefile.am | 14 + pylith/problems/Problem.py | 14 + .../sources/AuxSubfieldsMomentTensorForce.py | 62 +++ pylith/sources/AuxSubfieldsPointForce.py | 59 +++ pylith/sources/AuxSubfieldsSourceTime.py | 59 +++ .../sources/AuxSubfieldsSquarePulseSource.py | 59 +++ pylith/sources/AuxSubfieldsWellboreSource.py | 86 +++++ pylith/sources/GaussianWavelet.py | 68 ++++ pylith/sources/MomentTensorForce.py | 77 ++++ pylith/sources/PointForce.py | 71 ++++ pylith/sources/RickerWavelet.py | 68 ++++ pylith/sources/Source.py | 86 +++++ .../SourceTimeFunctionMomentTensorForce.py | 79 ++++ pylith/sources/SquarePulseSource.py | 71 ++++ pylith/sources/WellboreSource.py | 71 ++++ pylith/sources/__init__.py | 37 ++ 76 files changed, 6297 insertions(+), 264 deletions(-) create mode 100644 libsrc/pylith/fekernels/GaussianWavelet.cc create mode 100644 libsrc/pylith/fekernels/GaussianWavelet.hh create mode 100644 libsrc/pylith/fekernels/PointForce.cc create mode 100644 libsrc/pylith/fekernels/PointForce.hh create mode 100644 libsrc/pylith/fekernels/RickerWavelet.cc create mode 100644 libsrc/pylith/fekernels/RickerWavelet.hh create mode 100644 libsrc/pylith/fekernels/SquarePulseSource.cc create mode 100644 libsrc/pylith/fekernels/SquarePulseSource.hh create mode 100644 libsrc/pylith/fekernels/WellboreSource.cc create mode 100644 libsrc/pylith/fekernels/WellboreSource.hh create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh create mode 100644 libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh create mode 100644 libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh create mode 100644 libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc create mode 100644 libsrc/pylith/sources/DerivedFactoryMomentTensorForce.hh create mode 100644 libsrc/pylith/sources/GaussianWavelet.cc create mode 100644 libsrc/pylith/sources/GaussianWavelet.hh create mode 100644 libsrc/pylith/sources/MomentTensorForce.cc create mode 100644 libsrc/pylith/sources/MomentTensorForce.hh create mode 100644 libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc create mode 100644 libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.hh create mode 100644 libsrc/pylith/sources/SquarePulseSource.cc create mode 100644 libsrc/pylith/sources/SquarePulseSource.hh create mode 100644 libsrc/pylith/sources/WellboreSource.cc create mode 100644 libsrc/pylith/sources/WellboreSource.hh create mode 100644 modulesrc/sources/GaussianWavelet.i create mode 100644 modulesrc/sources/Makefile.am create mode 100644 modulesrc/sources/MomentTensorForce.i create mode 100644 modulesrc/sources/PointForce.i create mode 100644 modulesrc/sources/RickerWavelet.i create mode 100644 modulesrc/sources/Source.i create mode 100644 modulesrc/sources/SourceTimeFunctionMomentTensorForce.i create mode 100644 modulesrc/sources/SourceTimeFunctionPointForce.i create mode 100644 modulesrc/sources/SquarePulseSource.i create mode 100644 modulesrc/sources/WellboreSource.i create mode 100644 modulesrc/sources/sources.i create mode 100644 pylith/sources/AuxSubfieldsMomentTensorForce.py create mode 100644 pylith/sources/AuxSubfieldsPointForce.py create mode 100644 pylith/sources/AuxSubfieldsSourceTime.py create mode 100644 pylith/sources/AuxSubfieldsSquarePulseSource.py create mode 100644 pylith/sources/AuxSubfieldsWellboreSource.py create mode 100644 pylith/sources/GaussianWavelet.py create mode 100644 pylith/sources/MomentTensorForce.py create mode 100644 pylith/sources/PointForce.py create mode 100644 pylith/sources/RickerWavelet.py create mode 100644 pylith/sources/Source.py create mode 100644 pylith/sources/SourceTimeFunctionMomentTensorForce.py create mode 100644 pylith/sources/SquarePulseSource.py create mode 100644 pylith/sources/WellboreSource.py create mode 100644 pylith/sources/__init__.py diff --git a/configure.ac b/configure.ac index 3a8d2a0df4..247b20e3b9 100644 --- a/configure.ac +++ b/configure.ac @@ -199,6 +199,7 @@ AC_CONFIG_FILES([Makefile libsrc/pylith/feassemble/Makefile libsrc/pylith/fekernels/Makefile libsrc/pylith/faults/Makefile + libsrc/pylith/sources/Makefile libsrc/pylith/friction/Makefile libsrc/pylith/materials/Makefile libsrc/pylith/meshio/Makefile @@ -211,6 +212,7 @@ AC_CONFIG_FILES([Makefile modulesrc/include/Makefile modulesrc/bc/Makefile modulesrc/faults/Makefile + modulesrc/sources/Makefile modulesrc/feassemble/Makefile modulesrc/friction/Makefile modulesrc/materials/Makefile diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index c575311c28..d9821e5f73 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -15,6 +15,7 @@ SUBDIRS = \ topology \ feassemble \ problems \ + sources \ meshio \ materials \ bc \ @@ -128,6 +129,21 @@ libpylith_la_SOURCES = \ problems/ProgressMonitor.cc \ problems/ProgressMonitorTime.cc \ problems/ProgressMonitorStep.cc \ + sources/AuxiliaryFactoryMomentTensorForce.cc \ + sources/AuxiliaryFactoryPointForce.cc \ + sources/AuxiliaryFactorySourceTime.cc \ + sources/AuxiliaryFactorySquarePulseSource.cc \ + sources/AuxiliaryFactoryWellboreSource.cc \ + sources/DerivedFactoryMomentTensorForce.cc \ + sources/GaussianWavelet.cc \ + sources/MomentTensorForce.cc \ + sources/PointForce.cc \ + sources/RickerWavelet.cc \ + sources/Source.cc \ + sources/SourceTimeFunctionMomentTensorForce.cc \ + sources/SourceTimeFunctionPointForce.cc \ + sources/SquarePulseSource.cc \ + sources/WellboreSource.cc \ topology/Mesh.cc \ topology/MeshOps.cc \ topology/FieldBase.cc \ diff --git a/libsrc/pylith/fekernels/GaussianWavelet.cc b/libsrc/pylith/fekernels/GaussianWavelet.cc new file mode 100644 index 0000000000..fc58d01540 --- /dev/null +++ b/libsrc/pylith/fekernels/GaussianWavelet.cc @@ -0,0 +1,132 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/GaussianWavelet.hh" + +#include // USES assert() +#include // debugging. + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 2D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::GaussianWaveletPlaneStrain::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 2; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; + + // GaussianWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * gaussianwavelet; + } // for +} // g1v + + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 3D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::GaussianWavelet3D::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; + + // GaussianWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * gaussianwavelet; + } // for +} // g1v + + +// End of file diff --git a/libsrc/pylith/fekernels/GaussianWavelet.hh b/libsrc/pylith/fekernels/GaussianWavelet.hh new file mode 100644 index 0000000000..7c854f1ed9 --- /dev/null +++ b/libsrc/pylith/fekernels/GaussianWavelet.hh @@ -0,0 +1,143 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/GaussianWavelet.hh + * + */ + +#if !defined(pylith_fekernels_gaussianwavelet_hh) +#define pylith_fekernels_gaussianwavelet_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 2D. +// ===================================================================================================================== + +class pylith::fekernels::GaussianWaveletPlaneStrain { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // GaussianWaveletPlaneStrain + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 3D. +// ===================================================================================================================== + +class pylith::fekernels::GaussianWavelet3D { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // GaussianWaveletPlaneStrain + +#endif /* pylith_fekernels_gaussianwavelet_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/Makefile.am b/libsrc/pylith/fekernels/Makefile.am index d654a4ed04..2558368be2 100644 --- a/libsrc/pylith/fekernels/Makefile.am +++ b/libsrc/pylith/fekernels/Makefile.am @@ -30,7 +30,14 @@ subpkginclude_HEADERS = \ TimeDependentFn.hh \ NeumannTimeDependent.hh \ AbsorbingDampers.hh \ - FaultCohesiveKin.hh + FaultCohesiveKin.hh \ + IsotropicLinearPoroelasticity.hh \ + Poroelasticity.hh \ + WellboreSource.hh \ + SquarePulseSource.hh \ + RickerWavelet.hh \ + GaussianWavelet.hh \ + PointForce.hh dist_noinst_HEADERS = diff --git a/libsrc/pylith/fekernels/PointForce.cc b/libsrc/pylith/fekernels/PointForce.cc new file mode 100644 index 0000000000..1eabc0fadc --- /dev/null +++ b/libsrc/pylith/fekernels/PointForce.cc @@ -0,0 +1,66 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/PointForce.hh" + +#include // USES assert() +#include // debugging. + +// ---------------------------------------------------------------------- +// f0 entry function for displacement equation: f0u = \dot{u}. +void +pylith::fekernels::PointForce::f0u(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + assert(sOff); + assert(s); + assert(s_t); + assert(f0); + + // Incoming re-packed solution field. + const PylithInt i_displacement = 0; + + // Incoming re-packed auxiliary field. + const PylithInt i_pointForce = 0; + + const PylithScalar *pointForce = &a[aOff[i_pointForce]]; + + for (PylithInt i = 0; i < dim; ++i) { + f0[i] += pointForce[i]; + } // for +} + + +// End of file diff --git a/libsrc/pylith/fekernels/PointForce.hh b/libsrc/pylith/fekernels/PointForce.hh new file mode 100644 index 0000000000..0167d28404 --- /dev/null +++ b/libsrc/pylith/fekernels/PointForce.hh @@ -0,0 +1,83 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/PointForce.hh + * + */ + +#if !defined(pylith_fekernels_PointForce_hh) +#define pylith_fekernels_PointForce_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +class pylith::fekernels::PointForce { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** f0 function for displacement equation + * + */ + static void f0u(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]); + +}; // PointForce + +#endif /* pylith_fekernels_PointForce_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/RickerWavelet.cc b/libsrc/pylith/fekernels/RickerWavelet.cc new file mode 100644 index 0000000000..6f41ae3a56 --- /dev/null +++ b/libsrc/pylith/fekernels/RickerWavelet.cc @@ -0,0 +1,136 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/RickerWavelet.hh" + +#include // USES assert() +#include // debugging. + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 2D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 2; + + // Incoming re-packed solution field. + + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_rickerwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; + + // RickerWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * rickerwavelet; + } // for +} // g1v + + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 3D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::RickerWavelet3D::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_rickerwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; + + // RickerWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * rickerwavelet; + } // for +} // g1v + + +// End of file diff --git a/libsrc/pylith/fekernels/RickerWavelet.hh b/libsrc/pylith/fekernels/RickerWavelet.hh new file mode 100644 index 0000000000..b332240837 --- /dev/null +++ b/libsrc/pylith/fekernels/RickerWavelet.hh @@ -0,0 +1,143 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/RickerWavelet.hh + * + */ + +#if !defined(pylith_fekernels_rickerwavelet_hh) +#define pylith_fekernels_rickerwavelet_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 2D. +// ===================================================================================================================== + +class pylith::fekernels::RickerWaveletPlaneStrain { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // RickerWaveletPlaneStrain + +// ===================================================================================================================== +// Kernels for the Ricker Source Time Function in 3D. +// ===================================================================================================================== + +class pylith::fekernels::RickerWavelet3D { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // RickerWaveletPlaneStrain + +#endif /* pylith_fekernels_rickerwavelet_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/SquarePulseSource.cc b/libsrc/pylith/fekernels/SquarePulseSource.cc new file mode 100644 index 0000000000..b7861c8394 --- /dev/null +++ b/libsrc/pylith/fekernels/SquarePulseSource.cc @@ -0,0 +1,64 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/SquarePulseSource.hh" + +#include // USES assert() +#include // debugging. + +// ---------------------------------------------------------------------- +// f0 entry function for displacement equation: f0u = \dot{u}. +void +pylith::fekernels::SquarePulseSource::f0p(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + assert(sOff); + assert(s); + assert(s_t); + assert(f0); + + // Incoming re-packed solution field. + const PylithInt i_pressure = 1; + + // Incoming re-packed auxiliary field. + const PylithInt i_volumeFlowRate = 0; + + const PylithScalar volumeFlowRate = a[aOff[i_volumeFlowRate]]; + + f0[0] += volumeFlowRate; +} // f0p + + +// End of file diff --git a/libsrc/pylith/fekernels/SquarePulseSource.hh b/libsrc/pylith/fekernels/SquarePulseSource.hh new file mode 100644 index 0000000000..5bdf419c2b --- /dev/null +++ b/libsrc/pylith/fekernels/SquarePulseSource.hh @@ -0,0 +1,83 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/SquarePulseSource.hh + * + */ + +#if !defined(pylith_fekernels_SquarePulseSource_hh) +#define pylith_fekernels_SquarePulseSource_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +class pylith::fekernels::SquarePulseSource +{ + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** f0 function for pressure equation + * + */ + static void f0p(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]); + +}; // SquarePulseSource + +#endif /* pylith_fekernels_SquarePulseSource_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/WellboreSource.cc b/libsrc/pylith/fekernels/WellboreSource.cc new file mode 100644 index 0000000000..a403a65ed7 --- /dev/null +++ b/libsrc/pylith/fekernels/WellboreSource.cc @@ -0,0 +1,133 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/WellboreSource.hh" + +#include // USES assert() +#include // debugging. + +// ---------------------------------------------------------------------- +// f0 entry function for displacement equation: f0u = \dot{u}. +void +pylith::fekernels::WellboreSource::f0p(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + assert(sOff); + assert(s); + assert(s_t); + assert(f0); + + // Incoming re-packed solution field. + const PylithInt i_pressure = 1; + + // Incoming re-packed auxiliary field. + const PylithInt i_fluidDensity = 0; + const PylithInt i_fluidViscosity = 1; + const PylithInt i_isotropicPermeability = 2; + const PylithInt i_wellboreRadius = 3; + const PylithInt i_wellboreLength = 4; + const PylithInt i_wellborePressure = 5; + const PylithInt i_wellboreCharacter = 6; + const PylithInt i_elementDimensions = 7; + + const PylithScalar pressure = s[sOff[i_pressure]]; + + const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; + const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; + const PylithScalar isotropicPermeability = a[aOff[i_isotropicPermeability]]; + const PylithScalar wellboreRadius = a[aOff[i_wellboreRadius]]; + const PylithScalar wellboreLength = a[aOff[i_wellboreLength]]; + const PylithScalar wellborePressure = a[aOff[i_wellborePressure]]; + const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; + const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; + + PylithScalar r_e = 0.28 * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / + ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); + // Well Index, L**3 + PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); + + f0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity) * (pressure - wellborePressure); +} // f0p + + +// ---------------------------------------------------------------------- +// Jf0 function for pressure equation +void +pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal s_tshift, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar Jf0[]) { + // Incoming re-packed auxiliary field. + const PylithInt i_fluidDensity = 0; + const PylithInt i_fluidViscosity = 1; + const PylithInt i_isotropicPermeability = 2; + const PylithInt i_wellboreRadius = 3; + const PylithInt i_wellboreLength = 4; + const PylithInt i_wellboreCharacter = 6; + const PylithInt i_elementDimensions = 7; + + const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; + const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; + const PylithScalar isotropicPermeability = a[aOff[i_isotropicPermeability]]; + const PylithScalar wellboreRadius = a[aOff[i_wellboreRadius]]; + const PylithScalar wellboreLength = a[aOff[i_wellboreLength]]; + const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; + const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; + + PylithScalar r_e = 0.28 * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / + ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); + PylithScalar W = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); + + Jf0[0] += W * wellboreCharacter * (1.0 / fluidViscosity); + +} // Jf0pp + + +// End of file diff --git a/libsrc/pylith/fekernels/WellboreSource.hh b/libsrc/pylith/fekernels/WellboreSource.hh new file mode 100644 index 0000000000..197558342c --- /dev/null +++ b/libsrc/pylith/fekernels/WellboreSource.hh @@ -0,0 +1,104 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/WellboreSource.hh + * + */ + +#if !defined(pylith_fekernels_WellboreSource_hh) +#define pylith_fekernels_WellboreSource_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +class pylith::fekernels::WellboreSource { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** f0 function for pressure equation **/ + static + void f0p(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]); + + /** Jf0 function for pressure **/ + static + void Jf0pp(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal s_tshift, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar Jf0[]); + +}; // WellboreSource + +#endif /* pylith_fekernels_WellboreSource_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/fekernelsfwd.hh b/libsrc/pylith/fekernels/fekernelsfwd.hh index 174fef2b00..56d4b7199f 100644 --- a/libsrc/pylith/fekernels/fekernelsfwd.hh +++ b/libsrc/pylith/fekernels/fekernelsfwd.hh @@ -57,6 +57,19 @@ namespace pylith { class FaultCohesive; class FaultCohesiveKin; + class SquarePulseSource; + class WellboreSource; + + class RickerWavelet; + class RickerWaveletPlaneStrain; + class RickerWavelet3D; + + class GaussianWavelet; + class GaussianWaveletPlaneStrain; + class GaussianWavelet3D; + + class PointForce; + class BoundaryDirections; } // fekernels } // pylith diff --git a/libsrc/pylith/problems/Problem.cc b/libsrc/pylith/problems/Problem.cc index 7575d5ddf2..c0d027f48c 100644 --- a/libsrc/pylith/problems/Problem.cc +++ b/libsrc/pylith/problems/Problem.cc @@ -20,6 +20,7 @@ #include "pylith/materials/Material.hh" // USES Material #include "pylith/faults/FaultCohesive.hh" // USES FaultCohesive #include "pylith/bc/BoundaryCondition.hh" // USES BoundaryCondition +#include "pylith/sources/Source.hh" // USES Source #include "pylith/feassemble/Integrator.hh" // USES Integrator #include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain #include "pylith/feassemble/IntegratorInterface.hh" // USES IntegratorInterface @@ -347,6 +348,25 @@ pylith::problems::Problem::setBoundaryConditions(pylith::bc::BoundaryCondition* } // setBoundaryConditions +// ------------------------------------------------------------------------------------------------ +// Set sources. +void +pylith::problems::Problem::setSources(pylith::sources::Source* sources[], + const int numSources) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("Problem::setSources("<setFormulation(_formulation); } // for + const size_t numSources = _sources.size(); + for (size_t i = 0; i < numSources; ++i) { + assert(_sources[i]); + _sources[i]->setNormalizer(*_normalizer); + _sources[i]->setFormulation(_formulation); + } // for + _Problem::Events::logger.eventEnd(_Problem::Events::preinitialize); PYLITH_METHOD_END; } // preinitialize @@ -436,6 +463,13 @@ pylith::problems::Problem::verifyConfiguration(void) const { _bc[i]->verifyConfiguration(*solution); } // for + // Check to make sure sources are compatible with the solution. + const size_t numSources = _sources.size(); + for (size_t i = 0; i < numSources; ++i) { + assert(_sources[i]); + _sources[i]->verifyConfiguration(*solution); + } // for + _checkMaterialLabels(); assert(_observers); @@ -540,7 +574,7 @@ pylith::problems::Problem::_checkMaterialLabels(void) const { // ------------------------------------------------------------------------------------------------ -// Create array of integrators from materials, interfaces, and boundary conditions. +// Create array of integrators from materials, interfaces, sources, and boundary conditions. void pylith::problems::Problem::_createIntegrators(void) { PYLITH_METHOD_BEGIN; @@ -549,9 +583,10 @@ pylith::problems::Problem::_createIntegrators(void) { const size_t numMaterials = _materials.size(); const size_t numInterfaces = _interfaces.size(); + const size_t numSources = _sources.size(); const size_t numBC = _bc.size(); - const size_t maxSize = numMaterials + numInterfaces + numBC; + const size_t maxSize = numMaterials + numInterfaces + numSources + numBC; _integrators.resize(maxSize); size_t count = 0; @@ -573,6 +608,13 @@ pylith::problems::Problem::_createIntegrators(void) { if (integrator) { _integrators[count++] = integrator;} } // for + for (size_t i = 0; i < numSources; ++i) { + assert(_sources[i]); + pylith::feassemble::Integrator* integrator = _sources[i]->createIntegrator(*solution); + assert(count < maxSize); + if (integrator) { _integrators[count++] = integrator;} + } // for + // Check to make sure boundary conditions are compatible with the solution. for (size_t i = 0; i < numBC; ++i) { assert(_bc[i]); @@ -589,7 +631,7 @@ pylith::problems::Problem::_createIntegrators(void) { // ------------------------------------------------------------------------------------------------ -// Create array of constraints from materials, interfaces, and boundary conditions. +// Create array of constraints from materials, interfaces, sources, and boundary conditions. void pylith::problems::Problem::_createConstraints(void) { PYLITH_METHOD_BEGIN; @@ -598,6 +640,7 @@ pylith::problems::Problem::_createConstraints(void) { const size_t numMaterials = _materials.size(); const size_t numInterfaces = _interfaces.size(); + const size_t numSources = _sources.size(); const size_t numBC = _bc.size(); assert(_integrationData); @@ -620,6 +663,12 @@ pylith::problems::Problem::_createConstraints(void) { } // for + for (size_t i = 0; i < numSources; ++i) { + assert(_sources[i]); + std::vector constraints = _sources[i]->createConstraints(*solution); + _constraints.insert(_constraints.end(), constraints.begin(), constraints.end()); + } // for + for (size_t i = 0; i < numBC; ++i) { assert(_bc[i]); std::vector constraints = _bc[i]->createConstraints(*solution); diff --git a/libsrc/pylith/problems/Problem.hh b/libsrc/pylith/problems/Problem.hh index 32f6ee9158..8fb2bcfcf0 100644 --- a/libsrc/pylith/problems/Problem.hh +++ b/libsrc/pylith/problems/Problem.hh @@ -24,6 +24,7 @@ #include "pylith/materials/materialsfwd.hh" // HOLDSA Material #include "pylith/bc/bcfwd.hh" // HOLDSA BoundaryCondition #include "pylith/faults/faultsfwd.hh" // HOLDSA FaultCohesive +#include "pylith/sources/sourcesfwd.hh" // HOLDSA Source #include "pylith/testing/testingfwd.hh" // MMSTest ISA friend #include "spatialdata/spatialdb/spatialdbfwd.hh" // HASA GravityField @@ -142,6 +143,14 @@ public: void setMaterials(pylith::materials::Material* materials[], const int numMaterials); + /** Set sources. + * + * @param[in] sources Array of sources. + * @param[in] numSource Number of sources. + */ + void setSources(pylith::sources::Source* sources[], + const int numSources); + /** Set boundary conditions. * * @param[in] bc Array of boundary conditions. @@ -182,6 +191,7 @@ protected: spatialdata::spatialdb::GravityField* _gravityField; ///< Gravity field. std::vector _materials; ///< Array of materials. + std::vector _sources; ///< Array of sources. std::vector _bc; ///< Array of boundary conditions. std::vector _interfaces; ///< Array of interior interfaces. diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc new file mode 100644 index 0000000000..b88000cf96 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactoryMomentTensorForce.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactoryMomentTensorForce::AuxiliaryFactoryMomentTensorForce(void) { + GenericComponent::setName("auxiliaryfactorymomenttensorforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactoryMomentTensorForce::~AuxiliaryFactoryMomentTensorForce(void) {} + + +// ---------------------------------------------------------------------------- +// Add isotropic permeability subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // momentTensor + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTensorPermeability(void)"); + + const char* subfieldName = "moment_tensor"; + const char* componentNames[6] = { + "moment_tensor_xx", + "moment_tensor_yy", + "moment_tensor_zz", + "moment_tensor_xy", + "moment_tensor_yz", + "moment_tensor_xz" + }; + const int tensorSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; + const PylithReal pressureScale = _normalizer->getPressureScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::OTHER; + description.numComponents = tensorSize; + description.componentNames.resize(tensorSize); + for (int i = 0; i < tensorSize; ++i) { + description.componentNames[i] = componentNames[i]; + } // for + description.scale = pressureScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addMomentTensor + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay + + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh new file mode 100644 index 0000000000..4a0318dbae --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh @@ -0,0 +1,60 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/AuxiliaryFactoryMomentTensorForce.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorymomenttensorforce_hh) +#define pylith_sources_auxiliaryfactorymomenttensorforce_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField + +class pylith::sources::AuxiliaryFactoryMomentTensorForce : public pylith::feassemble::AuxiliaryFactory { + friend class TestAuxiliaryFactoryMomentTensorForce; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + AuxiliaryFactoryMomentTensorForce(void); + + /// Destructor. + virtual ~AuxiliaryFactoryMomentTensorForce(void); + + /// Add fluid density subfield to auxiliary subfields. + void addMomentTensor(void); + + /// Add fluid viscosity subfield to auxiliary subfields. + void addTimeDelay(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + AuxiliaryFactoryMomentTensorForce(const AuxiliaryFactoryMomentTensorForce &); ///< Not implemented. + const AuxiliaryFactoryMomentTensorForce& operator=(const AuxiliaryFactoryMomentTensorForce&); ///< Not implemented + +}; // class AuxiliaryFactoryMomentTensorForce + +#endif // pylith_sources_auxiliaryfactorymomenttensorforce_hh + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc index 420b688d0d..c941a40904 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc @@ -42,69 +42,38 @@ pylith::sources::AuxiliaryFactoryPointForce::AuxiliaryFactoryPointForce(void) { pylith::sources::AuxiliaryFactoryPointForce::~AuxiliaryFactoryPointForce(void) {} -// ---------------------------------------------------------------------------- -// Add isotropic permeability subfield to auxiliary fields. +// ---------------------------------------------------------------------- +// Add fluid density subfield to auxiliary fields. void -pylith::sources::AuxiliaryFactoryPointForce::addMomentTensor(void) { // momentTensor +pylith::sources::AuxiliaryFactoryPointForce::addPointForce(void) { PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTensorPermeability(void)"); - - const char* subfieldName = "moment_tensor"; - const char* componentNames[6] = { - "moment_tensor_xx", - "moment_tensor_yy", - "moment_tensor_zz", - "moment_tensor_xy", - "moment_tensor_yz", - "moment_tensor_xz" + PYLITH_JOURNAL_DEBUG("addPointForce(void)"); + + const char *subfieldName = "point_force"; + const char* componentNames[3] = { + "point_force_x", + "point_force_y", + "point_force_z", }; - const int tensorSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; const PylithReal pressureScale = _normalizer->getPressureScale(); pylith::topology::Field::Description description; description.label = subfieldName; description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::OTHER; - description.numComponents = tensorSize; - description.componentNames.resize(tensorSize); - for (int i = 0; i < tensorSize; ++i) { + description.vectorFieldType = pylith::topology::Field::VECTOR; + description.numComponents = _spaceDim; + description.componentNames.resize(_spaceDim); + for (int i = 0; i < _spaceDim; ++i) { description.componentNames[i] = componentNames[i]; } // for description.scale = pressureScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addMomentTensor - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time delay of source time function to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryPointForce::addTimeDelay(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); - - const char* subfieldName = "time_delay"; - - pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; + description.validator = pylith::topology::FieldQuery::validatorPositive; _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); PYLITH_METHOD_END; -} // addTimeDelay +} // addFluidDensity // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh index de18a30adc..ac1b629624 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh @@ -18,7 +18,7 @@ /** @file libsrc/sources/AuxiliaryFactoryPointForce.hh * - * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. */ #if !defined(pylith_sources_auxiliaryfactorypointforce_hh) @@ -41,17 +41,14 @@ public: /// Destructor. virtual ~AuxiliaryFactoryPointForce(void); - /// Add fluid density subfield to auxiliary subfields. - void addMomentTensor(void); - - /// Add fluid viscosity subfield to auxiliary subfields. - void addTimeDelay(void); + /// Add point force subfield to auxiliary subfields. + void addPointForce(void); // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: AuxiliaryFactoryPointForce(const AuxiliaryFactoryPointForce &); ///< Not implemented. - const AuxiliaryFactoryPointForce& operator=(const AuxiliaryFactoryPointForce&); ///< Not implemented + const AuxiliaryFactoryPointForce &operator=(const AuxiliaryFactoryPointForce &); ///< Not implemented }; // class AuxiliaryFactoryPointForce diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc new file mode 100644 index 0000000000..8a309acab6 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -0,0 +1,69 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactorySourceTime.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactorySourceTime::AuxiliaryFactorySourceTime(void) { + GenericComponent::setName("auxiliaryfactorysourcetime"); +} // constructor + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactorySourceTime::~AuxiliaryFactorySourceTime(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Add center frequency of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); + + const char* subfieldName = "center_frequency"; + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = 1.0; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addRickerCenterFrequency + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh new file mode 100644 index 0000000000..08e63de7ce --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh @@ -0,0 +1,55 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/AuxiliaryFactorySourceTime.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorysourcetime_hh) +#define pylith_sources_auxiliaryfactorysourcetime_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // ISA AuxiliaryFactoryMomentTensorForce + +class pylith::sources::AuxiliaryFactorySourceTime : public pylith::sources::AuxiliaryFactoryMomentTensorForce { + friend class TestAuxiliaryFactorySourceTime; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + AuxiliaryFactorySourceTime(void); + + /// Destructor. + virtual ~AuxiliaryFactorySourceTime(void); + + /// Add center frequency subfield to auxiliary subfields. + void addCenterFrequency(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + AuxiliaryFactorySourceTime(const AuxiliaryFactorySourceTime &); ///< Not implemented. + const AuxiliaryFactorySourceTime& operator=(const AuxiliaryFactorySourceTime&); ///< Not implemented + +}; // class AuxiliaryFactorySourceTime + +#endif // pylith_sources_auxiliaryfactorysourcetime_hh + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc new file mode 100644 index 0000000000..9c0bae5953 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc @@ -0,0 +1,71 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactorySquarePulseSource.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(void) +{ + GenericComponent::setName("auxiliaryfactorysquarepulsesource"); +} // constructor + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactorySquarePulseSource::~AuxiliaryFactorySquarePulseSource(void) {} + +// ---------------------------------------------------------------------- +// Add fluid density subfield to auxiliary fields. +void pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) +{ // fluidDensity + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addVolumeFlowRate(void)"); + + const char *subfieldName = "volume_flow_rate"; + const PylithReal lengthScale = _normalizer->getLengthScale(); + const PylithReal timeScale = _normalizer->getTimeScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = lengthScale * lengthScale * lengthScale / timeScale; + description.validator = pylith::topology::FieldQuery::validatorPositive; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addFluidDensity + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh new file mode 100644 index 0000000000..a008dcd541 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh @@ -0,0 +1,56 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/AuxiliaryFactorySquarePulseSource.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorysquarepulsesource_hh) +#define pylith_sources_auxiliaryfactorysquarepulsesource_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField + +class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory +{ + friend class TestAuxiliaryFactorySquarePulseSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + /// Default constructor. + AuxiliaryFactorySquarePulseSource(void); + + /// Destructor. + virtual ~AuxiliaryFactorySquarePulseSource(void); + + /// Add fluid density subfield to auxiliary subfields. + void addVolumeFlowRate(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + AuxiliaryFactorySquarePulseSource(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented. + const AuxiliaryFactorySquarePulseSource &operator=(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented + +}; // class AuxiliaryFactorySquarePulseSource + +#endif // pylith_sources_auxiliaryfactorysquarepulsesource_hh + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc new file mode 100644 index 0000000000..5017d305a7 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc @@ -0,0 +1,276 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactoryWellboreSource.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactoryWellboreSource::AuxiliaryFactoryWellboreSource(void) { + GenericComponent::setName("auxiliaryfactorywellboresource"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactoryWellboreSource::~AuxiliaryFactoryWellboreSource(void) {} + + +// ---------------------------------------------------------------------- +// Add fluid density subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addFluidDensity(void) { // fluidDensity + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addFluidDensity(void)"); + + const char* subfieldName = "fluid_density"; + const PylithReal densityScale = _normalizer->getDensityScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = densityScale; + description.validator = pylith::topology::FieldQuery::validatorPositive; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addFluidDensity + + +// ---------------------------------------------------------------------- +// Add fluid viscosity subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addFluidViscosity(void) { // fluidViscosity + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addFluidViscosity(void)"); + + const char* subfieldName = "fluid_viscosity"; + const PylithReal pressureScale = _normalizer->getPressureScale(); + const PylithReal timeScale = _normalizer->getTimeScale(); + const PylithReal viscosityScale = pressureScale*timeScale; + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = viscosityScale; + description.validator = pylith::topology::FieldQuery::validatorPositive; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; + +} // addFluidViscosity + + +// ---------------------------------------------------------------------------- +// Add isotropic permeability subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addIsotropicPermeability(void) { // isotropicPermeablity + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addIsotropicPermeability(void)"); + + const char* subfieldName = "isotropic_permeability"; + + const PylithReal lengthScale = _normalizer->getLengthScale(); + const PylithReal permeabilityScale = lengthScale*lengthScale; + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = permeabilityScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addIsotropicPermeability + + +// ---------------------------------------------------------------------------- +// Add wellbore radius subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreRadius(void) { // wellboreRadius + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addWellboreRadius(void)"); + + const char* subfieldName = "wellbore_radius"; + + const PylithReal lengthScale = _normalizer->getLengthScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = _normalizer->getLengthScale(); + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addWellboreRadius + + +// ---------------------------------------------------------------------------- +// Add wellbore length subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreLength(void) { // wellboreLength + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addWellboreLength(void)"); + + const char* subfieldName = "wellbore_length"; + + const PylithReal lengthScale = _normalizer->getLengthScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = _normalizer->getLengthScale(); + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addWellboreLength + + +// -------------------------------------------------------------------- +// Add wellbore pressure subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addWellborePressure(void) { // wellborePressure + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addWellborePressure(void)"); + + const char* subfieldName = "wellbore_pressure"; + const PylithReal pressureScale = _normalizer->getPressureScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = pressureScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addWellborePressure + + +// ---------------------------------------------------------------------- +// Add wellbore character subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreCharacter(void) { // wellboreCharacter + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addWellboreCharacter(void)"); + + const char* subfieldName = "wellbore_character"; + const PylithReal noScale = 1; + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = noScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addWellboreCharacter + + +// ---------------------------------------------------------------------------- +// Add isotropic permeability subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addElementDimensions(void) { // elementLength + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addElementDimensions(void)"); + + const char* subfieldName = "element_dimensions"; + const char* componentNames[3] = { + "element_x", + "element_y", + "element_z" + }; + const int tensorSize = (3 == _spaceDim) ? 3 : (2 == _spaceDim) ? 2 : 1; + const PylithReal lengthScale = _normalizer->getLengthScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::OTHER; + description.numComponents = tensorSize; + description.componentNames.resize(tensorSize); + for (int i = 0; i < _spaceDim; ++i) { + description.componentNames[i] = componentNames[i]; + } // for + description.scale = _normalizer->getLengthScale(); + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addElementLength + + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh new file mode 100644 index 0000000000..061f7ab3a4 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh @@ -0,0 +1,78 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/AuxiliaryFactoryWellboreSource.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorywellboresource_hh) +#define pylith_sources_auxiliaryfactorywellboresource_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField + +class pylith::sources::AuxiliaryFactoryWellboreSource : public pylith::feassemble::AuxiliaryFactory { + friend class TestAuxiliaryFactoryWellboreSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + AuxiliaryFactoryWellboreSource(void); + + /// Destructor. + virtual ~AuxiliaryFactoryWellboreSource(void); + + /// Add fluid density subfield to auxiliary subfields. + void addFluidDensity(void); + + /// Add fluid viscosity subfield to auxiliary subfields. + void addFluidViscosity(void); + + /// Add isotropic permeability subfield to auxiliary subfields. + void addIsotropicPermeability(void); + + /// Add wellbore radius subfield to auxiliary subfields. + void addWellboreRadius(void); + + /// Add wellbore length subfield to auxiliary subfields. + void addWellboreLength(void); + + /// Add wellbore pressure subfield to auxiliary subfields. + void addWellborePressure(void); + + /// Add wellbore character subfield to auxiliary subfields. + void addWellboreCharacter(void); + + /// Add element dimensions subfield to auxiliary subfields. + void addElementDimensions(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + AuxiliaryFactoryWellboreSource(const AuxiliaryFactoryWellboreSource &); ///< Not implemented. + const AuxiliaryFactoryWellboreSource& operator=(const AuxiliaryFactoryWellboreSource&); ///< Not implemented + +}; // class AuxiliaryFactoryWellboreSource + +#endif // pylith_sources_auxiliaryfactorywellboresource_hh + +// End of file diff --git a/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc new file mode 100644 index 0000000000..0b69f3ffcf --- /dev/null +++ b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc @@ -0,0 +1,122 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "DerivedFactoryMomentTensorForce.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field + +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::DerivedFactoryMomentTensorForce::DerivedFactoryMomentTensorForce(void) { + GenericComponent::setName("derivedfactorymomenttensorforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::DerivedFactoryMomentTensorForce::~DerivedFactoryMomentTensorForce(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Add Cauchy stress subfield to derived field. +void +pylith::sources::DerivedFactoryMomentTensorForce::addCauchyStress(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addCauchyStress(void)"); + + const char* fieldName = "cauchy_stress"; + const char* componentNames[6] = { "stress_xx", "stress_yy", "stress_zz", "stress_xy", "stress_yz", "stress_xz" }; + const int stressSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; + const PylithReal pressureScale = _normalizer->getPressureScale(); + + pylith::topology::Field::Description description; + description.label = fieldName; + description.alias = fieldName; + description.vectorFieldType = (3 == _spaceDim) ? pylith::topology::Field::TENSOR : pylith::topology::Field::OTHER; + description.numComponents = stressSize; + description.componentNames.resize(stressSize); + for (int i = 0; i < stressSize; ++i) { + description.componentNames[i] = componentNames[i]; + } // for + description.scale = pressureScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(fieldName)); + + PYLITH_METHOD_END; +} // addCauchyStress + + +// --------------------------------------------------------------------------------------------------------------------- +// Add Cauchy (infinitesimal) strain subfield to derived fields. +void +pylith::sources::DerivedFactoryMomentTensorForce::addCauchyStrain(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addCauchyStrain(void)"); + + const char* fieldName = "cauchy_strain"; + const char* componentNames[6] = { "strain_xx", "strain_yy", "strain_zz", "strain_xy", "strain_yz", "strain_xz" }; + const int strainSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; + + pylith::topology::Field::Description description; + description.label = fieldName; + description.alias = fieldName; + description.vectorFieldType = (3 == _spaceDim) ? pylith::topology::Field::TENSOR : pylith::topology::Field::OTHER; + description.numComponents = strainSize; + description.componentNames.resize(strainSize); + for (int i = 0; i < strainSize; ++i) { + description.componentNames[i] = componentNames[i]; + } // for + description.scale = 1.0; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(fieldName)); + + PYLITH_METHOD_END; +} // addCauchyStrain + + +// --------------------------------------------------------------------------------------------------------------------- +// Add subfields using discretizations provided. +void +pylith::sources::DerivedFactoryMomentTensorForce::addSubfields(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addSubfields(void)"); + + if (_subfieldDiscretizations.find("cauchy_stress") != _subfieldDiscretizations.end()) { + addCauchyStress(); + } // if + if (_subfieldDiscretizations.find("cauchy_strain") != _subfieldDiscretizations.end()) { + addCauchyStrain(); + } // if + + PYLITH_METHOD_END; + +} + + +// End of file diff --git a/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.hh b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.hh new file mode 100644 index 0000000000..89cf2f124b --- /dev/null +++ b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.hh @@ -0,0 +1,61 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/DerivedFactoryMomentTensorForce.hh + * + * @brief C++ helper class for setting up derived subfields for elastic sources. + */ + +#if !defined(pylith_sources_derivedfactorymomenttensorforce_hh) +#define pylith_sources_derivedfactorymomenttensorforce_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/topology/FieldFactory.hh" // ISA AuxiliaryFactory + +class pylith::sources::DerivedFactoryMomentTensorForce : public pylith::topology::FieldFactory { + friend class TestDerivedFactoryMomentTensorForce; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + DerivedFactoryMomentTensorForce(void); + + /// Destructor. + virtual ~DerivedFactoryMomentTensorForce(void); + + /// Add Cauchy stress subfield to derived field. + void addCauchyStress(void); + + /// Add Cauchy (infinitesimal) strain subfield to derived field. + void addCauchyStrain(void); + + /// Add subfields using discretizations provided. + void addSubfields(void); + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + DerivedFactoryMomentTensorForce(const DerivedFactoryMomentTensorForce &); ///< Not implemented. + const DerivedFactoryMomentTensorForce& operator=(const DerivedFactoryMomentTensorForce&); ///< Not implemented + +}; // class DerivedFactoryMomentTensorForce + +#endif // pylith_materials_derivedfactorymomenttensorforce_hh + +// End of file diff --git a/libsrc/pylith/sources/GaussianWavelet.cc b/libsrc/pylith/sources/GaussianWavelet.cc new file mode 100644 index 0000000000..6ec4ab138a --- /dev/null +++ b/libsrc/pylith/sources/GaussianWavelet.cc @@ -0,0 +1,98 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/GaussianWavelet.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/fekernels/GaussianWavelet.hh" // USES GaussianWavelet kernels +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::GaussianWavelet::GaussianWavelet(void) : + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + pylith::utils::PyreComponent::setName("gaussianwavelet"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::GaussianWavelet::~GaussianWavelet(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::GaussianWavelet::deallocate(void) { + SourceTimeFunctionMomentTensorForce::deallocate(); + + delete _auxiliaryFactory;_auxiliaryFactory = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::sources::AuxiliaryFactoryMomentTensorForce* +pylith::sources::GaussianWavelet::getAuxiliaryFactory(void) { + return _auxiliaryFactory; +} // getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Add source time subfields to auxiliary field. +void +pylith::sources::GaussianWavelet::addAuxiliarySubfields(void) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addAuxiliarySubfields(void)"); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise + // functions (kernels). + + _auxiliaryFactory->addCenterFrequency(); // numA - 1 + + PYLITH_METHOD_END; +} // addAuxiliarySubfields + + +// --------------------------------------------------------------------------------------------------------------------- +// Get g1v kernel for residual, G(t,s). +PetscPointFunc +pylith::sources::GaussianWavelet::getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("getKernelg1v_explicit(coordsys="<getSpaceDim(); + PetscPointFunc g1v = + (3 == spaceDim) ? pylith::fekernels::GaussianWavelet3D::g1v : + (2 == spaceDim) ? pylith::fekernels::GaussianWaveletPlaneStrain::g1v : + NULL; + + PYLITH_METHOD_RETURN(g1v); +} // getKernelResidualStress + + +// End of file diff --git a/libsrc/pylith/sources/GaussianWavelet.hh b/libsrc/pylith/sources/GaussianWavelet.hh new file mode 100644 index 0000000000..6f7520f044 --- /dev/null +++ b/libsrc/pylith/sources/GaussianWavelet.hh @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/GaussianWavelet.hh + * + * @brief C++ class for gaussian source time function. + */ + +#if !defined(pylith_materials_gaussianwavelet_hh) +#define pylith_materials_gaussianwavelet_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // ISA SourceTimeFunctionMomentTensorForce + +class pylith::sources::GaussianWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + friend class TestGaussianWavelet; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + GaussianWavelet(void); + + /// Destructor. + ~GaussianWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v. + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + GaussianWavelet(const GaussianWavelet&); ///< Not implemented. + const GaussianWavelet& operator=(const GaussianWavelet&); /// Not implemented. + +}; // class GaussianWavelet + +#endif // pylith_materials_gaussianwavelet_hh + +// End of file diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index 4f17e38f0e..02ae68fd25 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -4,8 +4,8 @@ # # Brad T. Aagaard, U.S. Geological Survey # Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo - +# Matthew G. Knepley, University of Chicago +# # This code was developed as part of the Computational Infrastructure # for Geodynamics (http://geodynamics.org). # @@ -21,17 +21,24 @@ include $(top_srcdir)/subpackage.am subpkginclude_HEADERS = \ Source.hh \ + MomentTensorForce.hh \ WellboreSource.hh \ - PointForce.hh \ + SquarePulseSource.hh \ + AuxiliaryFactorySquarePulseSource.hh \ + AuxiliaryFactoryMomentTensorForce.hh \ AuxiliaryFactoryWellboreSource.hh \ - AuxiliaryFactoryPointForce.hh \ - DerivedFactoryPointForce.hh \ AuxiliaryFactorySourceTime.hh \ + DerivedFactoryMomentTensorForce.hh \ RickerWavelet.hh \ + GaussianWavelet.hh \ + PointForce.hh \ + AuxiliaryFactoryPointForce.hh \ + SourceTimeFunctionMomentTensorForce.hh \ + SourceTimeFunctionPointForce.hh \ sourcesfwd.hh noinst_HEADERS = -# End of file \ No newline at end of file +# End of file diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc new file mode 100644 index 0000000000..74ee2c1584 --- /dev/null +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -0,0 +1,336 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/MomentTensorForce.hh" // implementation of object methods + +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // HASA SourceTimeFunctionMomentTensorSource +#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce +#include "pylith/sources/DerivedFactoryMomentTensorForce.hh" // USES DerivedFactoryMomentTensorForce +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::MomentTensorForce::MomentTensorForce(void) : + _sourceTimeFunction(NULL), + _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce) { + pylith::utils::PyreComponent::setName("momenttensorforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::MomentTensorForce::~MomentTensorForce(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::MomentTensorForce::deallocate(void) { + Source::deallocate(); + + delete _derivedFactory;_derivedFactory = NULL; + _sourceTimeFunction = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Set source time function. +void +pylith::sources::MomentTensorForce::setSourceTimeFunction(pylith::sources::SourceTimeFunctionMomentTensorForce* const sourceTimeFunction) { + _sourceTimeFunction = sourceTimeFunction; +} // setSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Get bulk source time function. +pylith::sources::SourceTimeFunctionMomentTensorForce* +pylith::sources::MomentTensorForce::getSourceTimeFunction(void) const { + return _sourceTimeFunction; +} // getSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void +pylith::sources::MomentTensorForce::verifyConfiguration(const pylith::topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution="<setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + printf("In MomentTensorForce end\n"); + DMView(dmSoln, NULL); + + _setKernelsResidual(integrator, solution); + _setKernelsJacobian(integrator, solution); + _setKernelsUpdateStateVars(integrator, solution); + _setKernelsDerivedField(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field* +pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution="<setLabel("MomentTensorForce auxiliary field"); + + assert(_sourceTimeFunction); + pylith::sources::AuxiliaryFactoryMomentTensorForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); + + assert(_normalizer); + auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + auxiliaryFactory->addMomentTensor(); // 0 + auxiliaryFactory->addTimeDelay(); // 1 + + _sourceTimeFunction->addAuxiliarySubfields(); + + auxiliaryField->subfieldsSetup(); + auxiliaryField->createDiscretization(); + pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); + auxiliaryField->allocate(); + auxiliaryField->createOutputVector(); + + assert(auxiliaryFactory); + auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("MomentTensor auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field* +pylith::sources::MomentTensorForce::createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution="<getAuxiliaryFactory(); +} // _getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Update kernel constants. +void +pylith::sources::MomentTensorForce::_updateKernelConstants(const PylithReal dt) { + assert(_sourceTimeFunction); + _sourceTimeFunction->updateKernelConstants(&_kernelConstants, dt); +} // _updateKernelConstants + + +// --------------------------------------------------------------------------------------------------------------------- +// Get derived factory associated with physics. +pylith::topology::FieldFactory* +pylith::sources::MomentTensorForce::_getDerivedFactory(void) { + return _derivedFactory; +} // _getDerivedFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for RHS residual G(t,s). +void +pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator="< kernels; + + switch (_formulation) { + case QUASISTATIC: { + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + case DYNAMIC: { + // Velocity + const PetscPointFunc g0v = NULL; + const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); + + kernels.resize(1); + kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsResidual + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for RHS Jacobian G(t,s). +void +pylith::sources::MomentTensorForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; + _sourceTimeFunction->addKernelsUpdateStateVars(&kernels, coordsys); + + integrator->setKernelsUpdateStateVars(kernels); + + PYLITH_METHOD_END; +} // _setKernelsUpdateStateVars + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for computing derived field. +void +pylith::sources::MomentTensorForce::_setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsDerivedField(integrator="<setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); printf("In PointForce end\n"); @@ -163,8 +194,6 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field& sol _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); - _setKernelsUpdateStateVars(integrator, solution); - _setKernelsDerivedField(integrator, solution); PYLITH_METHOD_RETURN(integrator); } // createIntegrator @@ -172,39 +201,35 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field& sol // --------------------------------------------------------------------------------------------------------------------- // Create auxiliary field. -pylith::topology::Field* -pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh) { +pylith::topology::Field * +pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution="<setLabel("PointForce auxiliary field"); - assert(_sourceTimeFunction); - pylith::sources::AuxiliaryFactoryPointForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); - assert(_normalizer); - auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - auxiliaryFactory->addMomentTensor(); // 0 - auxiliaryFactory->addTimeDelay(); // 1 - - _sourceTimeFunction->addAuxiliarySubfields(); + // :ATTENTION: In quasi-static problems, the time scale is usually quite large + // (order of tens to hundreds of years), which means that the density scale is very large, + // and the acceleration scale is very small. Nevertheless, density times gravitational + // acceleration will have a scale of pressure divided by length and should be within a few orders + // of magnitude of 1. - auxiliaryField->subfieldsSetup(); - auxiliaryField->createDiscretization(); - pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); - auxiliaryField->allocate(); - auxiliaryField->createOutputVector(); + // add in aux specific to square pulse + _auxiliaryFactory->addPointForce(); // 0 - assert(auxiliaryFactory); - auxiliaryFactory->setValuesFromDB(); + assert(_auxiliaryFactory); + _auxiliaryFactory->setValuesFromDB(); // Debug option - auxiliaryField->view("Point auxiliary field."); + auxiliaryField->view("PointForce auxiliary field."); PYLITH_METHOD_RETURN(auxiliaryField); } // createAuxiliaryField @@ -212,11 +237,11 @@ pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field& // --------------------------------------------------------------------------------------------------------------------- // Create derived field. -pylith::topology::Field* -pylith::sources::PointForce::createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh) { +pylith::topology::Field * +pylith::sources::PointForce::createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution="<getAuxiliaryFactory(); + return _auxiliaryFactory; } // _getAuxiliaryFactory // --------------------------------------------------------------------------------------------------------------------- -// Update kernel constants. +// Set kernels for LHS residual F(t,s,\dot{s}). void -pylith::sources::PointForce::_updateKernelConstants(const PylithReal dt) { - assert(_sourceTimeFunction); - _sourceTimeFunction->updateKernelConstants(&_kernelConstants, dt); -} // _updateKernelConstants - - -// --------------------------------------------------------------------------------------------------------------------- -// Get derived factory associated with physics. -pylith::topology::FieldFactory* -pylith::sources::PointForce::_getDerivedFactory(void) { - return _derivedFactory; -} // _getDerivedFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for RHS residual G(t,s). -void -pylith::sources::PointForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { +pylith::sources::PointForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator="< kernels; switch (_formulation) { - case QUASISTATIC: { + case QUASISTATIC: + { + // Displacement + const PetscPointFunc f0u = pylith::fekernels::PointForce::f0u; + const PetscPointFunc f1u = NULL; + + kernels.resize(1); + kernels[0] = ResidualKernels("displacement", pylith::feassemble::Integrator::LHS, f0u, f1u); break; } // QUASISTATIC case DYNAMIC_IMEX: - case DYNAMIC: { - // Velocity - const PetscPointFunc g0v = NULL; - const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); - - kernels.resize(1); - kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + { + break; + } // DYNAMIC + case DYNAMIC: + { break; } // DYNAMIC default: @@ -286,51 +298,44 @@ pylith::sources::PointForce::_setKernelsResidual(pylith::feassemble::IntegratorD // --------------------------------------------------------------------------------------------------------------------- -// Set kernels for RHS Jacobian G(t,s). +// Set kernels for LHS Jacobian F(t,s,\dot{s}). void -pylith::sources::PointForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { +pylith::sources::PointForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; - _sourceTimeFunction->addKernelsUpdateStateVars(&kernels, coordsys); - - integrator->setKernelsUpdateStateVars(kernels); - - PYLITH_METHOD_END; -} // _setKernelsUpdateStateVars + std::vector kernels; + switch (_formulation) { + case QUASISTATIC: + { + const PetscPointJac Jf0uu = NULL; + const PetscPointJac Jf1uu = NULL; + const PetscPointJac Jf2uu = NULL; + const PetscPointJac Jf3uu = NULL; -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for computing derived field. -void -pylith::sources::PointForce::_setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsDerivedField(integrator="<setKernelsJacobian(kernels, solution); PYLITH_METHOD_END; -} // _setKernelsDerivedField +} // _setKernelsJacobian // End of file diff --git a/libsrc/pylith/sources/PointForce.hh b/libsrc/pylith/sources/PointForce.hh index 0b8ffb5f85..085e24171d 100644 --- a/libsrc/pylith/sources/PointForce.hh +++ b/libsrc/pylith/sources/PointForce.hh @@ -43,23 +43,35 @@ public: /// Deallocate PETSc and local data structures. void deallocate(void); - /** Set source time function. + /** Set time history database. * - * @param[in] sourceTimeFunction Source time function for point force. + * @param[in] db Time history database. */ - void setSourceTimeFunction(pylith::sources::SourceTimeFunctionPointForce* const sourceTimeFunction); + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - /** Get source time function. + /** Get time history database. * - * @returns Source time function for point force. + * @preturns Time history database. */ - pylith::sources::SourceTimeFunctionPointForce* getSourceTimeFunction(void) const; + const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; /** Verify configuration is acceptable. * * @param[in] solution Solution field. */ - void verifyConfiguration(const pylith::topology::Field& solution) const; + void verifyConfiguration(const pylith::topology::Field &solution) const; /** Create integrator and set kernels. * @@ -67,7 +79,7 @@ public: * * @returns Integrator if applicable, otherwise NULL. */ - pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); + pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); /** Create auxiliary field. * @@ -76,8 +88,8 @@ public: * * @returns Auxiliary field if applicable, otherwise NULL. */ - pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); + pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); /** Create derived field. * @@ -86,8 +98,8 @@ public: * * @returns Derived field if applicable, otherwise NULL. */ - pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); + pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// protected: @@ -96,19 +108,7 @@ protected: * * @return Auxiliary factory for physics object. */ - pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); - - /** Update kernel constants. - * - * @param[in] dt Current time step. - */ - void _updateKernelConstants(const PylithReal dt); - - /** Get derived factory associated with physics. - * - * @return Derived factory for physics object. - */ - pylith::topology::FieldFactory* _getDerivedFactory(void); + pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: @@ -118,44 +118,31 @@ private: * @param[out] integrator Integrator for source. * @param[in] solution Solution field. */ - void _setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const pylith::topology::Field& solution) const; + void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; /** Set kernels for Jacobian. * * @param[out] integrator Integrator for source. * @param[in] solution Solution field. */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, - const pylith::topology::Field& solution) const; - - /** Set kernels for computing updated state variables in auxiliary field. - * - * @param[out] integrator Integrator for material. - * @param[in] solution Solution field. - */ - void _setKernelsUpdateStateVars(pylith::feassemble::IntegratorDomain* integrator, - const pylith::topology::Field& solution) const; - - /** Set kernels for computing derived field. - * - * @param[out] integrator Integrator for material. - * @param[in] solution Solution field. - */ - void _setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, - const pylith::topology::Field& solution) const; + void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: - pylith::sources::SourceTimeFunctionPointForce* _sourceTimeFunction; ///< Source time function for point force. - pylith::sources::DerivedFactoryPointForce* _derivedFactory; ///< Factory for creating derived fields. + bool _useInertia; ///< Flag to include inertial term. + spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. + pylith::sources::AuxiliaryFactoryPointForce *_auxiliaryFactory; ///< Factory for auxiliary subfields. + + bool _useTimeHistory; ///< Use time history term. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: - PointForce(const PointForce&); ///< Not implemented. - const PointForce& operator=(const PointForce&); /// Not implemented. + PointForce(const PointForce &); ///< Not implemented. + const PointForce &operator=(const PointForce &); /// Not implemented. }; diff --git a/libsrc/pylith/sources/RickerWavelet.cc b/libsrc/pylith/sources/RickerWavelet.cc index dcc73abb87..97f8c1cf39 100644 --- a/libsrc/pylith/sources/RickerWavelet.cc +++ b/libsrc/pylith/sources/RickerWavelet.cc @@ -48,7 +48,7 @@ pylith::sources::RickerWavelet::~RickerWavelet(void) { // Deallocate PETSc and local data structures. void pylith::sources::RickerWavelet::deallocate(void) { - SourceTimeFunctionPointForce::deallocate(); + SourceTimeFunctionMomentTensorForce::deallocate(); delete _auxiliaryFactory;_auxiliaryFactory = NULL; } // deallocate @@ -56,7 +56,7 @@ pylith::sources::RickerWavelet::deallocate(void) { // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. -pylith::sources::AuxiliaryFactoryPointForce* +pylith::sources::AuxiliaryFactoryMomentTensorForce* pylith::sources::RickerWavelet::getAuxiliaryFactory(void) { return _auxiliaryFactory; } // getAuxiliaryFactory diff --git a/libsrc/pylith/sources/RickerWavelet.hh b/libsrc/pylith/sources/RickerWavelet.hh index 2cada14fbc..a426363129 100644 --- a/libsrc/pylith/sources/RickerWavelet.hh +++ b/libsrc/pylith/sources/RickerWavelet.hh @@ -26,9 +26,9 @@ #include "sourcesfwd.hh" // forward declarations -#include "pylith/sources/SourceTimeFunctionPointForce.hh" // ISA SourceTimeFunctionPointForce +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // ISA SourceTimeFunctionMomentTensorForce -class pylith::sources::RickerWavelet : public pylith::sources::SourceTimeFunctionPointForce { +class pylith::sources::RickerWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { friend class TestRickerWavelet; // unit testing // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -47,7 +47,7 @@ public: * * @return Auxiliary factory for physics object. */ - pylith::sources::AuxiliaryFactoryPointForce* getAuxiliaryFactory(void); + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); /** Add source time subfields to auxiliary field. * diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index fcbfd38223..15a8c7a409 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -4,7 +4,7 @@ // // Brad T. Aagaard, U.S. Geological Survey // Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo +// Matthew G. Knepley, University of Chicago // // This code was developed as part of the Computational Infrastructure // for Geodynamics (http://geodynamics.org). @@ -54,7 +54,6 @@ pylith::sources::Source::deallocate(void) { PYLITH_METHOD_END; } // deallocate - // ------------------------------------------------------------------------------------------------ // Set descriptive label of source. void @@ -151,3 +150,6 @@ pylith::sources::Source::setPoints(const PylithReal* pointCoords, PYLITH_METHOD_END; } // setPoints + + +// End of file diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 8955fd704d..0499cd58c5 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -4,7 +4,7 @@ // // Brad T. Aagaard, U.S. Geological Survey // Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo +// Matthew G. Knepley, University of Chicago // // This code was developed as part of the Computational Infrastructure // for Geodynamics (http://geodynamics.org). @@ -92,7 +92,7 @@ public: /** Set first choice for reference direction to discriminate among tangential directions in 3-D. * * @param vec Reference direction unit vector. - * /** Create constraint and set kernels. + /** Create constraint and set kernels. * * @param[in] solution Solution field. * @returns Constraint if applicable, otherwise NULL. @@ -122,7 +122,7 @@ protected: std::string _description; ///< Descriptive label for source. std::string _labelName; ///< Name of label to identify source points in mesh. int _labelValue; ///< Value of label to identify source points in mesh. - + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc new file mode 100644 index 0000000000..c00e736b50 --- /dev/null +++ b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc @@ -0,0 +1,87 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // implementation of object methods + +#include "pylith/feassemble/Integrator.hh" // USES NEW_JACOBIAN_NEVER + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_DEBUG + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::SourceTimeFunctionMomentTensorForce::SourceTimeFunctionMomentTensorForce(void) : + _JacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_NEVER) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::SourceTimeFunctionMomentTensorForce::~SourceTimeFunctionMomentTensorForce(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::SourceTimeFunctionMomentTensorForce::deallocate(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Get triggers for needing to compute the elastic constants for the RHS Jacobian. +int +pylith::sources::SourceTimeFunctionMomentTensorForce::getJacobianTriggers(void) const { + return _JacobianTriggers; +} // getJacobianTriggers + + +// --------------------------------------------------------------------------------------------------------------------- +// Update kernel constants. +void +pylith::sources::SourceTimeFunctionMomentTensorForce::updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("updateKernelConstants(kernelConstants"<* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addKernelsUpdateStateVars(kernels="<* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const; + + /** Update kernel constants. + * + * @param[inout] kernelConstants Array of constants used in integration kernels. + * @param[in] dt Current time step. + */ + virtual + void updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const; + + // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// + + int _JacobianTriggers; ///< Triggers for needing to recompute the RHS Jacobian. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + SourceTimeFunctionMomentTensorForce(const SourceTimeFunctionMomentTensorForce&); ///< Not implemented. + const SourceTimeFunctionMomentTensorForce& operator=(const SourceTimeFunctionMomentTensorForce&); /// Not + /// implemented. + +}; // class SourceTimeFunctionMomentTensorForce + +#endif // pylith_sources_sourcetimefunctionmomenttensorforce_hh + +// End of file diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc new file mode 100644 index 0000000000..fe6b65f309 --- /dev/null +++ b/libsrc/pylith/sources/SquarePulseSource.cc @@ -0,0 +1,339 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/SquarePulseSource.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySquarePulseSource.hh" // USES AuxiliaryFactorySquarePulseSource +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps + +#include "pylith/fekernels/SquarePulseSource.hh" // USES SquarePulseSource kernels + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::SquarePulseSource::SquarePulseSource(void) : _useInertia(false), + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource) +{ + pylith::utils::PyreComponent::setName("squarepulsesource"); +} // constructor + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::SquarePulseSource::~SquarePulseSource(void) +{ + deallocate(); +} // destructor + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void pylith::sources::SquarePulseSource::deallocate(void) +{ + Source::deallocate(); + + delete _auxiliaryFactory; + _auxiliaryFactory = NULL; +} // deallocate + +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) +{ + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); + + _dbTimeHistory = th; +} // setTimeHistoryDB + +// --------------------------------------------------------------------------------------------------------------------- +// Get time history database. +const spatialdata::spatialdb::TimeHistory * +pylith::sources::SquarePulseSource::getTimeHistoryDB(void) +{ + return _dbTimeHistory; +} // getTimeHistoryDB + +// --------------------------------------------------------------------------------------------------------------------- +// Use time history term in time history expression. +void pylith::sources::SquarePulseSource::useTimeHistory(const bool value) +{ + PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); + + _useTimeHistory = value; +} // useTimeHistory + +// --------------------------------------------------------------------------------------------------------------------- +// Get flag associated with using time history term in time history expression. +bool pylith::sources::SquarePulseSource::useTimeHistory(void) const +{ + return _useTimeHistory; +} // useTimeHistory + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); + + // Verify solution contains expected fields. + if (!solution.hasSubfield("pressure")) + { + throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'SquarePulseSource'."); + } // if + + PYLITH_METHOD_END; +} // verifyConfiguration + +// --------------------------------------------------------------------------------------------------------------------- +// Create integrator and set kernels. +pylith::feassemble::Integrator * +pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); + + printf("In SquarePulseSource begin\n"); + DMView(solution.getDM(), NULL); + PetscErrorCode err; + PetscDM dmSoln = solution.getDM(); + assert(dmSoln); + // transform points of source to mesh coordinates in python + // DM from solution + Vec vecPoints; + DMLabel label; + PetscSF sfPoints = NULL; + const PetscInt *localPoints; + const PetscSFNode *remotePoints; + PetscInt numRoots = -1, numLeaves, dim, d; + PetscMPIInt rank; + PetscScalar *a; + + err = DMGetCoordinateDim(dmSoln, &dim); + PYLITH_CHECK_ERROR(err); + err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, + &_pointCoords[0], &vecPoints); + PYLITH_CHECK_ERROR(err); + + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); + // Erzatz from ex17 + // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); + // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); + // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + // for (d = 0; d < _pointCoords.size(); ++d) { + // a[d] = _pointCoords[d]; + // } + // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + + err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); + PYLITH_CHECK_ERROR(err); + err = VecDestroy(&vecPoints); + PYLITH_CHECK_ERROR(err); + err = DMCreateLabel(dmSoln, getLabelName()); + PYLITH_CHECK_ERROR(err); + err = DMGetLabel(dmSoln, getLabelName(), &label); + PYLITH_CHECK_ERROR(err); + err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); + PYLITH_CHECK_ERROR(err); + err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); + PYLITH_CHECK_ERROR(err); + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); + for (PetscInt p = 0; p < numLeaves; ++p) + { + if (remotePoints[p].rank == rank) + { + err = DMLabelSetValue(label, remotePoints[p].index, 2); + PYLITH_CHECK_ERROR(err); + } + } // for + err = PetscSFDestroy(&sfPoints); + PYLITH_CHECK_ERROR(err); + + pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); + assert(integrator); + integrator->setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + printf("In SquarePulseSource end\n"); + DMView(dmSoln, NULL); + + _setKernelsResidual(integrator, solution); + _setKernelsJacobian(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field * +pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); + + pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); + assert(auxiliaryField); + auxiliaryField->setLabel("SquarePulseSource auxiliary field"); + + assert(_normalizer); + _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + // :ATTENTION: In quasi-static problems, the time scale is usually quite large + // (order of tens to hundreds of years), which means that the density scale is very large, + // and the acceleration scale is very small. Nevertheless, density times gravitational + // acceleration will have a scale of pressure divided by length and should be within a few orders + // of magnitude of 1. + + // add in aux specific to square pulse + _auxiliaryFactory->addVolumeFlowRate(); // 0 + + assert(_auxiliaryFactory); + _auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("SquarePulse auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field * +pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); + + PYLITH_METHOD_RETURN(NULL); +} // createDerivedField + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::feassemble::AuxiliaryFactory * +pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) +{ + return _auxiliaryFactory; +} // _getAuxiliaryFactory + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for LHS residual F(t,s,\dot{s}). +void pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); + + const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + + std::vector kernels; + + switch (_formulation) + { + case QUASISTATIC: + { + // Pressure + const PetscPointFunc f0p = pylith::fekernels::SquarePulseSource::f0p; + const PetscPointFunc f1p = NULL; + + kernels.resize(1); + kernels[0] = ResidualKernels("pressure", pylith::feassemble::Integrator::LHS, f0p, f1p); + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + { + break; + } // DYNAMIC + case DYNAMIC: + { + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsResidual + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for LHS Jacobian F(t,s,\dot{s}). +void pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); + + const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + + std::vector kernels; + + switch (_formulation) + { + case QUASISTATIC: + { + const PetscPointJac Jf0pp = NULL; + const PetscPointJac Jf1pp = NULL; + const PetscPointJac Jf2pp = NULL; + const PetscPointJac Jf3pp = NULL; + + kernels.resize(1); + const EquationPart equationPart = pylith::feassemble::Integrator::LHS; + kernels[0] = JacobianKernels("pressure", "pressure", equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); + break; + } // QUASISTATIC + case DYNAMIC: + case DYNAMIC_IMEX: + { + break; + } // DYNAMIC_IMEX + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsJacobian(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsJacobian + +// End of file diff --git a/libsrc/pylith/sources/SquarePulseSource.hh b/libsrc/pylith/sources/SquarePulseSource.hh new file mode 100644 index 0000000000..24940de773 --- /dev/null +++ b/libsrc/pylith/sources/SquarePulseSource.hh @@ -0,0 +1,148 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/SquarePulseSource.hh + * + * @brief C++ class for solving squarepulsesource equation. + */ + +#if !defined(pylith_sources_squarepulsesource_hh) +#define pylith_sources_squarepulsesource_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/Source.hh" // ISA Source + +class pylith::sources::SquarePulseSource : public pylith::sources::Source +{ + friend class TestSquarePulseSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + /// Default constructor. + SquarePulseSource(void); + + /// Destructor. + ~SquarePulseSource(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field &solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// +protected: + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + /** Set kernels for residual. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + /** Set kernels for Jacobian. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + bool _useInertia; ///< Flag to include inertial term. + spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. + pylith::sources::AuxiliaryFactorySquarePulseSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. + + bool _useTimeHistory; ///< Use time history term. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + SquarePulseSource(const SquarePulseSource &); ///< Not implemented. + const SquarePulseSource &operator=(const SquarePulseSource &); /// Not implemented. +}; + +// class SquarePulseSource + +#endif // pylith_sources_squarepulsesource_hh + +// End of file diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc new file mode 100644 index 0000000000..c7eb935947 --- /dev/null +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -0,0 +1,352 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/WellboreSource.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // USES AuxiliaryFactoryWellboreSource +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps + +#include "pylith/fekernels/WellboreSource.hh" // USES WellboreSource kernels + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::WellboreSource::WellboreSource(void) : _useInertia(false), + _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryWellboreSource) +{ + pylith::utils::PyreComponent::setName("wellboresource"); +} // constructor + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::WellboreSource::~WellboreSource(void) +{ + deallocate(); +} // destructor + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void pylith::sources::WellboreSource::deallocate(void) +{ + Source::deallocate(); + + delete _auxiliaryFactory; + _auxiliaryFactory = NULL; +} // deallocate + +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void pylith::sources::WellboreSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) +{ + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); + + _dbTimeHistory = th; +} // setTimeHistoryDB + +// --------------------------------------------------------------------------------------------------------------------- +// Get time history database. +const spatialdata::spatialdb::TimeHistory * +pylith::sources::WellboreSource::getTimeHistoryDB(void) +{ + return _dbTimeHistory; +} // getTimeHistoryDB + +// --------------------------------------------------------------------------------------------------------------------- +// Use time history term in time history expression. +void pylith::sources::WellboreSource::useTimeHistory(const bool value) +{ + PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); + + _useTimeHistory = value; +} // useTimeHistory + +// --------------------------------------------------------------------------------------------------------------------- +// Get flag associated with using time history term in time history expression. +bool pylith::sources::WellboreSource::useTimeHistory(void) const +{ + return _useTimeHistory; +} // useTimeHistory + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void pylith::sources::WellboreSource::verifyConfiguration(const pylith::topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); + + // Verify solution contains expected fields. + if (!solution.hasSubfield("pressure")) + { + throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'WellboreSource'."); + } // if + + PYLITH_METHOD_END; +} // verifyConfiguration + +// --------------------------------------------------------------------------------------------------------------------- +// Create integrator and set kernels. +pylith::feassemble::Integrator * +pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field &solution) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); + + printf("In WellboreSource begin\n"); + DMView(solution.getDM(), NULL); + PetscErrorCode err; + PetscDM dmSoln = solution.getDM(); + assert(dmSoln); + // transform points of source to mesh coordinates in python + // DM from solution + Vec vecPoints; + DMLabel label; + PetscSF sfPoints = NULL; + const PetscInt *localPoints; + const PetscSFNode *remotePoints; + PetscInt numRoots = -1, numLeaves, dim, d; + PetscMPIInt rank; + PetscScalar *a; + + err = DMGetCoordinateDim(dmSoln, &dim); + PYLITH_CHECK_ERROR(err); + err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, + &_pointCoords[0], &vecPoints); + PYLITH_CHECK_ERROR(err); + + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); + // Erzatz from ex17 + // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); + // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); + // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + // for (d = 0; d < _pointCoords.size(); ++d) { + // a[d] = _pointCoords[d]; + // } + // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + + err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); + PYLITH_CHECK_ERROR(err); + err = VecDestroy(&vecPoints); + PYLITH_CHECK_ERROR(err); + err = DMCreateLabel(dmSoln, getLabelName()); + PYLITH_CHECK_ERROR(err); + err = DMGetLabel(dmSoln, getLabelName(), &label); + PYLITH_CHECK_ERROR(err); + err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); + PYLITH_CHECK_ERROR(err); + err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); + PYLITH_CHECK_ERROR(err); + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); + for (PetscInt p = 0; p < numLeaves; ++p) + { + if (remotePoints[p].rank == rank) + { + err = DMLabelSetValue(label, remotePoints[p].index, 2); + PYLITH_CHECK_ERROR(err); + } + } // for + err = PetscSFDestroy(&sfPoints); + PYLITH_CHECK_ERROR(err); + + pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); + assert(integrator); + integrator->setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + printf("In WellboreSource end\n"); + DMView(dmSoln, NULL); + + _setKernelsResidual(integrator, solution); + _setKernelsJacobian(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field * +pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); + + pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); + assert(auxiliaryField); + auxiliaryField->setLabel("WellboreSource auxiliary field"); + + assert(_normalizer); + _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + // :ATTENTION: In quasi-static problems, the time scale is usually quite large + // (order of tens to hundreds of years), which means that the density scale is very large, + // and the acceleration scale is very small. Nevertheless, density times gravitational + // acceleration will have a scale of pressure divided by length and should be within a few orders + // of magnitude of 1. + + // add in aux specific to peaceman + _auxiliaryFactory->addFluidDensity(); // 0 + _auxiliaryFactory->addFluidViscosity(); // 1 + _auxiliaryFactory->addIsotropicPermeability(); // 2 + _auxiliaryFactory->addWellboreRadius(); // 3 + _auxiliaryFactory->addWellboreLength(); // 4 + _auxiliaryFactory->addWellborePressure(); // 5 + _auxiliaryFactory->addWellboreCharacter(); // 6 + _auxiliaryFactory->addElementDimensions(); // 7 + + auxiliaryField->subfieldsSetup(); + auxiliaryField->createDiscretization(); + pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); + auxiliaryField->allocate(); + auxiliaryField->createOutputVector(); + + assert(_auxiliaryFactory); + _auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("Wellbore auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field * +pylith::sources::WellboreSource::createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); + + PYLITH_METHOD_RETURN(NULL); +} // createDerivedField + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::feassemble::AuxiliaryFactory * +pylith::sources::WellboreSource::_getAuxiliaryFactory(void) +{ + return _auxiliaryFactory; +} // _getAuxiliaryFactory + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for LHS residual F(t,s,\dot{s}). +void pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); + + const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + + std::vector kernels; + + switch (_formulation) + { + case QUASISTATIC: + { + // Pressure + const PetscPointFunc f0p = pylith::fekernels::WellboreSource::f0p; + const PetscPointFunc f1p = NULL; + + kernels.resize(1); + kernels[0] = ResidualKernels("pressure", pylith::feassemble::Integrator::LHS, f0p, f1p); + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + { + break; + } // DYNAMIC + case DYNAMIC: + { + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsResidual + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for LHS Jacobian F(t,s,\dot{s}). +void pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const +{ + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); + + const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + + std::vector kernels; + + switch (_formulation) + { + case QUASISTATIC: + { + const PetscPointJac Jf0pp = pylith::fekernels::WellboreSource::Jf0pp; + const PetscPointJac Jf1pp = NULL; + const PetscPointJac Jf2pp = NULL; + const PetscPointJac Jf3pp = NULL; + + kernels.resize(1); + const EquationPart equationPart = pylith::feassemble::Integrator::LHS; + kernels[0] = JacobianKernels("pressure", "pressure", equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); + break; + } // QUASISTATIC + case DYNAMIC: + case DYNAMIC_IMEX: + { + break; + } // DYNAMIC_IMEX + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsJacobian(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsJacobian + +// End of file diff --git a/libsrc/pylith/sources/WellboreSource.hh b/libsrc/pylith/sources/WellboreSource.hh new file mode 100644 index 0000000000..5fcbc5a96f --- /dev/null +++ b/libsrc/pylith/sources/WellboreSource.hh @@ -0,0 +1,148 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/WellboreSource.hh + * + * @brief C++ class for solving wellboresource equation. + */ + +#if !defined(pylith_sources_wellboresource_hh) +#define pylith_sources_wellboresource_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/Source.hh" // ISA Source + +class pylith::sources::WellboreSource : public pylith::sources::Source +{ + friend class TestWellboreSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + /// Default constructor. + WellboreSource(void); + + /// Destructor. + ~WellboreSource(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field &solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// +protected: + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + /** Set kernels for residual. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + /** Set kernels for Jacobian. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + bool _useInertia; ///< Flag to include inertial term. + spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. + pylith::sources::AuxiliaryFactoryWellboreSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. + + bool _useTimeHistory; ///< Use time history term. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + WellboreSource(const WellboreSource &); ///< Not implemented. + const WellboreSource &operator=(const WellboreSource &); /// Not implemented. +}; + +// class WellboreSource + +#endif // pylith_sources_wellboresource_hh + +// End of file diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh index b216673a9e..ad59acca0c 100644 --- a/libsrc/pylith/sources/sourcesfwd.hh +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -4,7 +4,7 @@ // // Brad T. Aagaard, U.S. Geological Survey // Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo +// Matthew G. Knepley, University of Chicago // // This code was developed as part of the Computational Infrastructure // for Geodynamics (http://geodynamics.org). @@ -32,17 +32,24 @@ namespace pylith { // New stuff class Source; - class PointForce; - class AuxiliaryFactoryPointForce; - class DerivedFactoryPointForce; + class MomentTensorForce; + class AuxiliaryFactoryMomentTensorForce; + class DerivedFactoryMomentTensorForce; - class SourceTimeFunctionPointForce; + class SourceTimeFunctionMomentTensorForce; class AuxiliaryFactorySourceTime; class RickerWavelet; - // class GaussianWavelet; + class GaussianWavelet; + + class PointForce; + class SourceTimeFunctionPointForce; + class AuxiliaryFactoryPointForce; + + class SquarePulseSource; + class AuxiliaryFactorySquarePulseSource; - // class WellboreSource; - // class AuxiliaryFactoryWellboreSource; + class WellboreSource; + class AuxiliaryFactoryWellboreSource; } // sources } // pylith diff --git a/modulesrc/Makefile.am b/modulesrc/Makefile.am index 148f94b645..280fa28219 100644 --- a/modulesrc/Makefile.am +++ b/modulesrc/Makefile.am @@ -19,6 +19,7 @@ SUBDIRS = \ mpi \ problems \ scales \ + sources \ topology \ utils diff --git a/modulesrc/include/physicsarray.i b/modulesrc/include/physicsarray.i index fd129f27f9..65e4c832b2 100644 --- a/modulesrc/include/physicsarray.i +++ b/modulesrc/include/physicsarray.i @@ -80,6 +80,48 @@ delete[] $1; } +// ---------------------------------------------------------------------- +// List of sources. +%typemap(in)(pylith::sources::Source *sources[], + const int numSources) +{ + // Check to make sure input is a list. + if (PyList_Check($input)) + { + const int size = PyList_Size($input); + $2 = size; + $1 = (size > 0) ? new pylith::sources::Source *[size] : 0; + for (int i = 0; i < size; i++) + { + PyObject *s = PyList_GetItem($input, i); + pylith::sources::Source *sources = 0; + int err = SWIG_ConvertPtr(s, (void **)&sources, + $descriptor(pylith::sources::Source *), + 0); + if (SWIG_IsOK(err)) + $1[i] = (pylith::sources::Source *)sources; + else + { + PyErr_SetString(PyExc_TypeError, "List must contain sources."); + delete[] $1; + return NULL; + } // if + } // for + } + else + { + PyErr_SetString(PyExc_TypeError, "Expected list of sources."); + return NULL; + } // if/else +} // typemap(in) [List of sources.] + +// This cleans up the array we malloc'd before the function call +%typemap(freearg)(pylith::sources::Source *sources[], + const int numSources) +{ + delete[] $1; +} + // ---------------------------------------------------------------------- // List of initial conditions. %typemap(in) (pylith::problems::InitialCondition* ic[], diff --git a/modulesrc/problems/Problem.i b/modulesrc/problems/Problem.i index 0f69b249b2..bfa1278507 100644 --- a/modulesrc/problems/Problem.i +++ b/modulesrc/problems/Problem.i @@ -107,6 +107,14 @@ public: void setMaterials(pylith::materials::Material* materials[], const int numMaterials); + /** Set sources. + * + * @param[in] sources Array of sources. + * @param[in] numSource Number of sources. + */ + void setSources(pylith::sources::Source* sources[], + const int numSources); + /** Set boundary conditions. * * @param[in] bc Array of boundary conditions. diff --git a/modulesrc/sources/GaussianWavelet.i b/modulesrc/sources/GaussianWavelet.i new file mode 100644 index 0000000000..1878df9253 --- /dev/null +++ b/modulesrc/sources/GaussianWavelet.i @@ -0,0 +1,67 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/GaussianWavelet.i + * + * Python interface to C++ GaussianWavelet. + */ + +namespace pylith { + namespace sources { + class GaussianWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + GaussianWavelet(void); + + /// Destructor. + ~GaussianWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time function subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v + . + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + }; + + // class GaussianWavelet + + } // sources +} // pylith + +// End of file diff --git a/modulesrc/sources/Makefile.am b/modulesrc/sources/Makefile.am new file mode 100644 index 0000000000..3ec50b593d --- /dev/null +++ b/modulesrc/sources/Makefile.am @@ -0,0 +1,76 @@ +# -*- Makefile -*- +# +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2017 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# + +subpackage = sources +include $(top_srcdir)/subpackage.am +include $(top_srcdir)/modulesrc/module.am + +subpkgpython_LTLIBRARIES = _sources.la + +subpkgpython_PYTHON = sources.py + +swig_sources = \ + sources.i \ + ../problems/Physics.i \ + Source.i \ + WellboreSource.i \ + SquarePulseSource.i \ + PointForce.i \ + MomentTensorForce.i \ + SourceTimeFunctionMomentTensorForce.i \ + RickerWavelet.i \ + GaussianWavelet.i \ + ../utils/PyreComponent.i + +swigincludedir = $(pkgdatadir)/swig/$(subpackage) +swiginclude_HEADERS = \ + Source.i + +swig_generated = \ + sources_wrap.cxx \ + sources.py + +_sources_la_LDFLAGS = -module -avoid-version \ + -g $(AM_LDFLAGS) $(PYTHON_LA_LDFLAGS) + +dist__sources_la_SOURCES = $(swig_sources) $(swig_generated) + +_sources_la_LIBADD = \ + $(top_builddir)/libsrc/pylith/libpylith.la \ + -lspatialdata \ + $(PETSC_LIB) \ + $(PYTHON_BLDLIBRARY) $(PYTHON_LIBS) $(PYTHON_SYSLIBS) +if ENABLE_CUBIT + _sources_la_LIBADD += -lnetcdf +endif + +if ENABLE_SWIG +$(srcdir)/sources_wrap.cxx $(srcdir)/sources.py: $(swig_sources) + $(SWIG) $(PETSC_CC_INCLUDES) -Wall -c++ -python $< +else +$(srcdir)/sources_wrap.cxx $(srcdir)/sources.py: + $(error Missing SWIG generated files. Make sure SWIG is installed and reconfigure with --enable-swig) +endif + + +MAINTAINERCLEANFILES = \ + $(srcdir)/sources_wrap.cxx \ + $(srcdir)/sources.py + + +# End of file diff --git a/modulesrc/sources/MomentTensorForce.i b/modulesrc/sources/MomentTensorForce.i new file mode 100644 index 0000000000..0816632f61 --- /dev/null +++ b/modulesrc/sources/MomentTensorForce.i @@ -0,0 +1,105 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2016 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/MomentTensorForce.i + * + * Python interface to C++ MomentTensorForce. + */ + +namespace pylith { + namespace sources { + class MomentTensorForce : public pylith::sources::Source { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + MomentTensorForce(void); + + /// Destructor. + ~MomentTensorForce(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set source time function. + * + * @param[in] sourceTimeFunction Source time function for point force. + */ + void setSourceTimeFunction(pylith::sources::SourceTimeFunctionMomentTensorForce* const sourceTimeFunction); + + /** Get source time function. + * + * @returns Source time function for point force. + */ + pylith::sources::SourceTimeFunctionMomentTensorForce* getSourceTimeFunction(void) const; + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field& solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// +protected: + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); + + /** Update kernel constants. + * + * @param[in] dt Current time step. + */ + void _updateKernelConstants(const PylithReal dt); + + }; // class MomentTensorForce + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/PointForce.i b/modulesrc/sources/PointForce.i new file mode 100644 index 0000000000..19bb15fe16 --- /dev/null +++ b/modulesrc/sources/PointForce.i @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2016 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/PointForce.i + * + * Python interface to C++ PointForce. + */ + +namespace pylith { + namespace sources { + class PointForce : public pylith::sources::Source { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + PointForce(void); + + /// Destructor. + ~PointForce(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field& solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// +protected: + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); + + /** Update kernel constants. + * + * @param[in] dt Current time step. + */ + void _updateKernelConstants(const PylithReal dt); + + }; // class PointForce + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/RickerWavelet.i b/modulesrc/sources/RickerWavelet.i new file mode 100644 index 0000000000..06510d028b --- /dev/null +++ b/modulesrc/sources/RickerWavelet.i @@ -0,0 +1,67 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/RickerWavelet.i + * + * Python interface to C++ RickerWavelet. + */ + +namespace pylith { + namespace sources { + class RickerWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + RickerWavelet(void); + + /// Destructor. + ~RickerWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time function subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v + . + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + }; + + // class RickerWavelet + + } // sources +} // pylith + +// End of file diff --git a/modulesrc/sources/Source.i b/modulesrc/sources/Source.i new file mode 100644 index 0000000000..61cc48d75d --- /dev/null +++ b/modulesrc/sources/Source.i @@ -0,0 +1,115 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2016 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/Source.i + * + * Python interface to C++ abstract base class Source. + */ + +namespace pylith { + namespace sources { + class Source : public pylith::problems::Physics { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /** Default constructor. + * + * @param dimension Spatial dimension associated with source. + */ + Source(const int dimension); + + /// Destructor. + virtual ~Source(void); + + /// Deallocate PETSc and local data structures. + virtual + void deallocate(void); + + /** Set descriptive label for source. + * + * @param value Label of source. + */ + void setDescription(const char* value); + + /** Get descruptive label of source. + * + * @returns Label of source + */ + const char* getDescription(void) const; + + /** Set name of label marking source. + * + * @param[in] value Name of label for source (from mesh generator). + */ + void setLabelName(const char* value); + + /** Get name of label marking boundary associated with boundary condition surface. + * + * @returns Name of label for source (from mesh generator). + */ + const char* getLabelName(void) const; + + /** Set value of label marking source. + * + * @param[in] value Value of label for source (from mesh generator). + */ + void setLabelValue(const int value); + + /** Get value of label marking source. + * + * @returns Value of label for source (from mesh generator). + */ + int getLabelValue(void) const; + + /** Create constraint and set kernels. + * + * @param[in] solution Solution field. + * @returns Constraint if applicable, otherwise NULL. + */ + virtual + std::vector createConstraints(const pylith::topology::Field& solution); + + /** Set coordinates and names of points. + * + * @param[in] points Array of coordinates [numPoints * spaceDim]. + * @param[in] numPoints Number of points. + * @param[in] spaceDim Spatial dimension for coordinates. + * @param[in] pointNames Array with point names. + * @param[in] numPointNames Number of point names. + */ + %apply(double* IN_ARRAY2, int DIM1, int DIM2) { + (const PylithReal* pointCoords, + const int numPoints, + const int spaceDim) + }; + %apply(const char* const* string_list, const int list_len){ + (const char* const* pointNames, const int numPointNames) + }; + void setPoints(const PylithReal* pointCoords, + const int numPoints, + const int spaceDim, + const char* const* pointNames, + const int numPointNames); + %clear(const PylithReal* pointCoords, const int numPoints, const int spaceDim); + %clear(const char* const* pointNames, const int numPointNames); + }; // class Source + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/SourceTimeFunctionMomentTensorForce.i b/modulesrc/sources/SourceTimeFunctionMomentTensorForce.i new file mode 100644 index 0000000000..a9cc95feab --- /dev/null +++ b/modulesrc/sources/SourceTimeFunctionMomentTensorForce.i @@ -0,0 +1,84 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/SourceTimeFunctionMomentTensorForce.i + * + * Python interface to C++ abstract base class SourceTimeFunctionMomentTensorForce. + */ + +namespace pylith { + namespace sources { + class SourceTimeFunctionMomentTensorForce : public pylith::utils::PyreComponent { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SourceTimeFunctionMomentTensorForce(void); + + /// Destructor. + virtual ~SourceTimeFunctionMomentTensorForce(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + virtual + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void) = 0; + + /// Add sourcetimefunction subfields to auxiliary field. + virtual + void addAuxiliarySubfields(void) = 0; + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return RHS residual kernel for stress. + */ + virtual + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const = 0; + + /** Add kernels for updating state variables. + * + * @param[inout] kernels Array of kernels for updating state variables. + * @param[in] coordsys Coordinate system. + */ + virtual + void addKernelsUpdateStateVars(std::vector* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const; + + /** Update kernel constants. + * + * @param[inout] kernelConstants Array of constants used in integration kernels. + * @param[in] dt Current time step. + */ + virtual + void updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const; + + }; + + // class SourceTimeFunctionMomentTensorForce + + } // sources +} // pylith + +// End of file diff --git a/modulesrc/sources/SourceTimeFunctionPointForce.i b/modulesrc/sources/SourceTimeFunctionPointForce.i new file mode 100644 index 0000000000..6fe8e1f56e --- /dev/null +++ b/modulesrc/sources/SourceTimeFunctionPointForce.i @@ -0,0 +1,84 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/SourceTimeFunctionPointForce.i + * + * Python interface to C++ abstract base class SourceTimeFunctionPointForce. + */ + +namespace pylith { + namespace sources { + class SourceTimeFunctionPointForce : public pylith::utils::PyreComponent { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SourceTimeFunctionPointForce(void); + + /// Destructor. + virtual ~SourceTimeFunctionPointForce(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + virtual + pylith::sources::AuxiliaryFactoryPointForce* getAuxiliaryFactory(void) = 0; + + /// Add sourcetimefunction subfields to auxiliary field. + virtual + void addAuxiliarySubfields(void) = 0; + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return RHS residual kernel for stress. + */ + virtual + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const = 0; + + /** Add kernels for updating state variables. + * + * @param[inout] kernels Array of kernels for updating state variables. + * @param[in] coordsys Coordinate system. + */ + virtual + void addKernelsUpdateStateVars(std::vector* kernels, + const spatialdata::geocoords::CoordSys* coordsys) const; + + /** Update kernel constants. + * + * @param[inout] kernelConstants Array of constants used in integration kernels. + * @param[in] dt Current time step. + */ + virtual + void updateKernelConstants(pylith::real_array* kernelConstants, + const PylithReal dt) const; + + }; + + // class SourceTimeFunctionPointForce + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/SquarePulseSource.i b/modulesrc/sources/SquarePulseSource.i new file mode 100644 index 0000000000..15d0239390 --- /dev/null +++ b/modulesrc/sources/SquarePulseSource.i @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2016 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/SquarePulseSource.i + * + * Python interface to C++ SquarePulseSource. + */ + +namespace pylith { + namespace sources { + class SquarePulseSource : public pylith::sources::Source { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SquarePulseSource(void); + + /// Destructor. + ~SquarePulseSource(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field& solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// +protected: + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); + + /** Update kernel constants. + * + * @param[in] dt Current time step. + */ + void _updateKernelConstants(const PylithReal dt); + + }; // class SquarePulseSource + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/WellboreSource.i b/modulesrc/sources/WellboreSource.i new file mode 100644 index 0000000000..7de30528d3 --- /dev/null +++ b/modulesrc/sources/WellboreSource.i @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2016 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/WellboreSource.i + * + * Python interface to C++ WellboreSource. + */ + +namespace pylith { + namespace sources { + class WellboreSource : public pylith::sources::Source { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + WellboreSource(void); + + /// Destructor. + ~WellboreSource(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field& solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// +protected: + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); + + /** Update kernel constants. + * + * @param[in] dt Current time step. + */ + void _updateKernelConstants(const PylithReal dt); + + }; // class WellboreSource + + } // sources +} // pylith + +// End of file \ No newline at end of file diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i new file mode 100644 index 0000000000..541ee08ea1 --- /dev/null +++ b/modulesrc/sources/sources.i @@ -0,0 +1,68 @@ +// ====================================================================== +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ====================================================================== +// +// SWIG interface +%module sources + +// Header files for module C++ code +%{ +#include "pylith/sources/Source.hh" +#include "pylith/sources/WellboreSource.hh" +#include "pylith/sources/SquarePulseSource.hh" +#include "pylith/sources/PointForce.hh" +#include "pylith/sources/MomentTensorForce.hh" +#include "pylith/sources/RickerWavelet.hh" +#include "pylith/sources/GaussianWavelet.hh" +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" + +#include "pylith/utils/arrayfwd.hh" +%} + +%include "exception.i" +%exception { + try { + $action + } catch (const std::exception& err) { + SWIG_exception(SWIG_RuntimeError, err.what()); + } // try/catch + } // exception + +%include "typemaps.i" +%include "../include/scalartypemaps.i" +%include "../include/chararray.i" + +// Numpy interface stuff +%{ +#define SWIG_FILE_WITH_INIT +%} +%include "../include/numpy.i" +%init %{ +import_array(); +%} + +// Interfaces +%include "../utils/PyreComponent.i" +%include "../problems/Physics.i" + +%include "Source.i" +%include "WellboreSource.i" +%include "SquarePulseSource.i" +%include "PointForce.i" +%include "MomentTensorForce.i" +%include "SourceTimeFunctionMomentTensorForce.i" +%include "RickerWavelet.i" +%include "GaussianWavelet.i" + +// End of file diff --git a/pylith/Makefile.am b/pylith/Makefile.am index 9ed0b30bc9..71892dda1d 100644 --- a/pylith/Makefile.am +++ b/pylith/Makefile.am @@ -139,6 +139,20 @@ EXTRA_DIST = \ scales/QuasistaticPoroelasticity.py \ scales/QuasistaticElasticity.py \ scales/__init__.py \ + sources/WellboreSource.py \ + sources/SquarePulseSource.py \ + sources/SourceTimeFunctionMomentTensorForce.py \ + sources/Source.py \ + sources/RickerWavelet.py \ + sources/PointForce.py \ + sources/MomentTensorForce.py \ + sources/GaussianWavelet.py \ + sources/AuxSubfieldsWellboreSource.py \ + sources/AuxSubfieldsSquarePulseSource.py \ + sources/AuxSubfieldsSourceTime.py \ + sources/AuxSubfieldsPointForce.py \ + sources/AuxSubfieldsMomentTensorForce.py \ + sources/__init__.py \ testing/FullTestApp.py \ testing/SolutionPoints.py \ testing/TestCases.py \ diff --git a/pylith/problems/Problem.py b/pylith/problems/Problem.py index e63213fbf1..dcda28f447 100644 --- a/pylith/problems/Problem.py +++ b/pylith/problems/Problem.py @@ -39,6 +39,12 @@ def faultFactory(name): return facility(name, family="fault", factory=FaultCohesiveKin) +def sourceFactory(name): + """Factory for source items. + """ + from pythia.pyre.inventory import facility + from pylith.sources.WellboreSource import WellboreSource + return facility(name, family="source", factory=WellboreSource) def observerFactory(name): """Factory for output items.""" @@ -121,6 +127,9 @@ class Problem(PetscComponent, ModuleProblem): "Interior surfaces with constraints or constitutive models." ) + sources = pythia.pyre.inventory.facilityArray("sources", itemFactory=sourceFactory, factory=EmptyBin) + sources.meta['tip'] = "Point sources." + from pylith.problems.SingleObserver import SingleSolnObserver observers = pythia.pyre.inventory.facilityArray( @@ -191,6 +200,11 @@ def preinitialize(self, mesh): interface.preinitialize(self) ModuleProblem.setInterfaces(self, self.interfaces.components()) + # Preinitialize Sources + for source in self.sources.components(): + source.preinitialize(self) + ModuleProblem.setSources(self, self.sources.components()) + # Preinitialize observers. for observer in self.observers.components(): observer.preinitialize(self) diff --git a/pylith/sources/AuxSubfieldsMomentTensorForce.py b/pylith/sources/AuxSubfieldsMomentTensorForce.py new file mode 100644 index 0000000000..6d71e827a4 --- /dev/null +++ b/pylith/sources/AuxSubfieldsMomentTensorForce.py @@ -0,0 +1,62 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/AuxSubfieldsMomentTensorForce.py +# +# @brief Python container for momenttensorforce equation subfields. + +from pylith.utils.PetscComponent import PetscComponent + + +class AuxSubfieldsMomentTensorForce(PetscComponent): + """Python container for momenttensorforce equation subfields. + + FACTORY: auxiliary_subfields + """ + + import pythia.pyre.inventory + + from pylith.topology.Subfield import Subfield + + momentTensor = pythia.pyre.inventory.facility("moment_tensor", family="auxiliary_subfield", factory=Subfield) + momentTensor.meta['tip'] = "Moment tensor subfield." + + TimeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) + TimeDelay.meta['tip'] = "time delay subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="auxsubfieldsmomenttensorforce"): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="auxiliary_subfields") + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _configure(self): + PetscComponent._configure(self) + return + + +# FACTORIES //////////////////////////////////////////////////////////// + +def auxiliary_subfields(): + """Factory associated with AuxSubfieldsMomentTensorForce. + """ + return AuxSubfieldsMomentTensorForce() + + +# End of file diff --git a/pylith/sources/AuxSubfieldsPointForce.py b/pylith/sources/AuxSubfieldsPointForce.py new file mode 100644 index 0000000000..395a9dc9d2 --- /dev/null +++ b/pylith/sources/AuxSubfieldsPointForce.py @@ -0,0 +1,59 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Vuffalo + +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/AuxSubfieldsPointForce.py +# +# @brief Python container for pointforce equation subfields. + +from pylith.utils.PetscComponent import PetscComponent + + +class AuxSubfieldsPointForce(PetscComponent): + """Python container for pointforce equation subfields. + + FACTORY: auxiliary_subfields + """ + + import pythia.pyre.inventory + + from pylith.topology.Subfield import Subfield + + pointForce = pythia.pyre.inventory.facility("point_force", family="auxiliary_subfield", factory=Subfield) + pointForce.meta['tip'] = "Point Force subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="auxsubfieldspointforce"): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="auxiliary_subfields") + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _configure(self): + PetscComponent._configure(self) + return + + +# FACTORIES //////////////////////////////////////////////////////////// + +def auxiliary_subfields(): + """Factory associated with AuxSubfieldsPointForce. + """ + return AuxSubfieldsPointForce() + + +# End of file diff --git a/pylith/sources/AuxSubfieldsSourceTime.py b/pylith/sources/AuxSubfieldsSourceTime.py new file mode 100644 index 0000000000..8b3df75454 --- /dev/null +++ b/pylith/sources/AuxSubfieldsSourceTime.py @@ -0,0 +1,59 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/AuxSubfieldsSourceTime.py +# +# @brief Python container for SourceTime equation subfields. + +from pylith.utils.PetscComponent import PetscComponent + + +class AuxSubfieldsSourceTime(PetscComponent): + """Python container for SourceTime equation subfields. + + FACTORY: auxiliary_subfields + """ + + import pythia.pyre.inventory + + from pylith.topology.Subfield import Subfield + + CenterFrequency = pythia.pyre.inventory.facility("center_frequency", family="auxiliary_subfield", factory=Subfield) + CenterFrequency.meta['tip'] = "center frequency subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="auxsubfieldssourcetime"): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="auxiliary_subfields") + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _configure(self): + PetscComponent._configure(self) + return + + +# FACTORIES //////////////////////////////////////////////////////////// + +def auxiliary_subfields(): + """Factory associated with AuxSubfieldsSourceTime. + """ + return AuxSubfieldsSourceTime() + + +# End of file diff --git a/pylith/sources/AuxSubfieldsSquarePulseSource.py b/pylith/sources/AuxSubfieldsSquarePulseSource.py new file mode 100644 index 0000000000..e821b93b12 --- /dev/null +++ b/pylith/sources/AuxSubfieldsSquarePulseSource.py @@ -0,0 +1,59 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/AuxSubfieldsSquarePulseSource.py +# +# @brief Python container for squarepulsesource equation subfields. + +from pylith.utils.PetscComponent import PetscComponent + + +class AuxSubfieldsSquarePulseSource(PetscComponent): + """Python container for squarepulsesource equation subfields. + + FACTORY: auxiliary_subfields + """ + + import pythia.pyre.inventory + + from pylith.topology.Subfield import Subfield + + volumeFlowRate = pythia.pyre.inventory.facility("volume_flow_rate", family="auxiliary_subfield", factory=Subfield) + volumeFlowRate.meta['tip'] = "Volume Flow Rate subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="auxsubfieldssquarepulsesource"): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="auxiliary_subfields") + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _configure(self): + PetscComponent._configure(self) + return + + +# FACTORIES //////////////////////////////////////////////////////////// + +def auxiliary_subfields(): + """Factory associated with AuxSubfieldsSquarePulseSource. + """ + return AuxSubfieldsSquarePulseSource() + + +# End of file diff --git a/pylith/sources/AuxSubfieldsWellboreSource.py b/pylith/sources/AuxSubfieldsWellboreSource.py new file mode 100644 index 0000000000..f464a6f9ba --- /dev/null +++ b/pylith/sources/AuxSubfieldsWellboreSource.py @@ -0,0 +1,86 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/AuxSubfieldsWellboreSource.py +# +# @brief Python container for wellboresource equation subfields. + +from pylith.utils.PetscComponent import PetscComponent + + +class AuxSubfieldsWellboreSource(PetscComponent): + """Python container for wellboresource equation subfields. + + FACTORY: auxiliary_subfields + """ + + import pythia.pyre.inventory + + from pylith.topology.Subfield import Subfield + + fluidDensity = pythia.pyre.inventory.facility("fluid_density", family="auxiliary_subfield", factory=Subfield) + fluidDensity.meta['tip'] = "Fluid density subfield." + + fluidViscosity = pythia.pyre.inventory.facility("fluid_viscosity", family="auxiliary_subfield", factory=Subfield) + fluidViscosity.meta['tip'] = "Fluid viscosity subfield." + + isotropicPermeability = pythia.pyre.inventory.facility( + "isotropic_permeability", family="auxiliary_subfield", factory=Subfield) + isotropicPermeability.meta['tip'] = "Isotropic permeability subfield." + + wellboreRadius = pythia.pyre.inventory.facility( + "wellbore_radius", family="auxiliary_subfield", factory=Subfield) + wellboreRadius.meta['tip'] = "Wellbore radius subfield." + + wellboreLength = pythia.pyre.inventory.facility( + "wellbore_length", family="auxiliary_subfield", factory=Subfield) + wellboreLength.meta['tip'] = "Wellbore length subfield." + + wellboreCharacter = pythia.pyre.inventory.facility( + "wellbore_character", family="auxiliary_subfield", factory=Subfield) + wellboreCharacter.meta['tip'] = "Wellbore character subfield." + + wellborePressure = pythia.pyre.inventory.facility( + "wellbore_pressure", family="auxiliary_subfield", factory=Subfield) + wellborePressure.meta['tip'] = "Wellbore pressure subfield." + + elementDimensions = pythia.pyre.inventory.facility( + "element_dimensions", family="auxiliary_subfield", factory=Subfield) + elementDimensions.meta['tip'] = "Element dimension subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="auxsubfieldswellboresource"): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="auxiliary_subfields") + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _configure(self): + PetscComponent._configure(self) + return + + +# FACTORIES //////////////////////////////////////////////////////////// + +def auxiliary_subfields(): + """Factory associated with AuxSubfieldsWellboreSource. + """ + return AuxSubfieldsWellboreSource() + + +# End of file diff --git a/pylith/sources/GaussianWavelet.py b/pylith/sources/GaussianWavelet.py new file mode 100644 index 0000000000..dffd096b14 --- /dev/null +++ b/pylith/sources/GaussianWavelet.py @@ -0,0 +1,68 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2021 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/GaussianWavelet.py +# +# @brief Python source time functiof for a gaussian wavelet. +# +# Factory: momenttensorforce_sourcetimefunction + +from .SourceTimeFunctionMomentTensorForce import SourceTimeFunctionMomentTensorForce +from .sources import GaussianWavelet as ModuleGaussianWavelet + + +class GaussianWavelet(SourceTimeFunctionMomentTensorForce, ModuleGaussianWavelet): + """Python source time function for ricker source. + + FACTORY: momenttensorforce_sourcetimefunction + """ + + import pythia.pyre.inventory + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="gaussianwavelet"): + """Constructor. + """ + SourceTimeFunctionMomentTensorForce.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSourceTime import AuxSubfieldsSourceTime + self.auxiliarySubfields = AuxSubfieldsSourceTime("auxiliary_subfields") + + def preinitialize(self, problem): + SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) + + + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _createModuleObj(self): + """Call constructor for module object for access to C++ object. + """ + ModuleGaussianWavelet.__init__(self) + + +# FACTORIES //////////////////////////////////////////////////////////// + +def momenttensorforce_sourcetimefunction(): + """Factory associated with GaussianWavelet. + """ + return GaussianWavelet() + + +# End of file diff --git a/pylith/sources/MomentTensorForce.py b/pylith/sources/MomentTensorForce.py new file mode 100644 index 0000000000..078e3af546 --- /dev/null +++ b/pylith/sources/MomentTensorForce.py @@ -0,0 +1,77 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/MomentTensorForce.py +# +# @brief Python object for solving the momenttensorforce equation. +# +# Factory: source + +from pylith.sources.RickerWavelet import RickerWavelet +from .Source import Source +from .sources import MomentTensorForce as ModuleMomentTensorForce + + +class MomentTensorForce(Source, ModuleMomentTensorForce): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + source_time_function = pythia.pyre.inventory.facility("source_time_function", family="momenttensorforce_sourcetimefunction", factory=RickerWavelet) + source_time_function.meta['tip'] = "Source time function for momenttensor force." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="momenttensorforce"): + """Constructor. + """ + Source.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsMomentTensorForce import AuxSubfieldsMomentTensorForce + self.auxiliarySubfields = AuxSubfieldsMomentTensorForce("auxiliary_subfields") + + + def preinitialize(self, problem): + """Setup source. + """ + self.source_time_function.preinitialize(problem) + Source.preinitialize(self, problem) + + self.source_time_function.addAuxiliarySubfields(self, problem) + + return + + def _createModuleObj(self): + """Create handle to C++ MomentTensorForce. + """ + ModuleMomentTensorForce.__init__(self) + ModuleMomentTensorForce.setSourceTimeFunction(self, self.source_time_function) # Material sets auxiliary db in source_time_function. + return + + +# Factories + +def source(): + """Factory associated with MomentTensorForce. + """ + return MomentTensorForce() + + +# End of file diff --git a/pylith/sources/PointForce.py b/pylith/sources/PointForce.py new file mode 100644 index 0000000000..53f71d8b26 --- /dev/null +++ b/pylith/sources/PointForce.py @@ -0,0 +1,71 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/PointForce.py +# +# @brief Python object for solving the pointforce equation. +# +# Factory: source + +from .Source import Source +from .sources import PointForce as ModulePointForce + + +class PointForce(Source, ModulePointForce): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="pointforce"): + """Constructor. + """ + Source.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsPointForce import AuxSubfieldsPointForce + self.auxiliarySubfields = AuxSubfieldsPointForce("auxiliary_subfields") + + + def preinitialize(self, problem): + """Setup source. + """ + Source.preinitialize(self, problem) + + + return + + def _createModuleObj(self): + """Create handle to C++ PointForce. + """ + ModulePointForce.__init__(self) + return + + +# Factories + +def source(): + """Factory associated with PointForce. + """ + return PointForce() + + +# End of file diff --git a/pylith/sources/RickerWavelet.py b/pylith/sources/RickerWavelet.py new file mode 100644 index 0000000000..90bc5ed943 --- /dev/null +++ b/pylith/sources/RickerWavelet.py @@ -0,0 +1,68 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2021 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/RickerWavelet.py +# +# @brief Python source time functiof for a ricker wavelet. +# +# Factory: pointforce_sourcetimefunction + +from .SourceTimeFunctionMomentTensorForce import SourceTimeFunctionMomentTensorForce +from .sources import RickerWavelet as ModuleRickerWavelet + + +class RickerWavelet(SourceTimeFunctionMomentTensorForce, ModuleRickerWavelet): + """Python source time function for ricker source. + + FACTORY: pointforce_sourcetimefunction + """ + + import pythia.pyre.inventory + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="rickerwavelet"): + """Constructor. + """ + SourceTimeFunctionMomentTensorForce.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSourceTime import AuxSubfieldsSourceTime + self.auxiliarySubfields = AuxSubfieldsSourceTime("auxiliary_subfields") + + def preinitialize(self, problem): + SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) + + + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _createModuleObj(self): + """Call constructor for module object for access to C++ object. + """ + ModuleRickerWavelet.__init__(self) + + +# FACTORIES //////////////////////////////////////////////////////////// + +def pointforce_sourcetimefunction(): + """Factory associated with RickerWavelet. + """ + return RickerWavelet() + + +# End of file diff --git a/pylith/sources/Source.py b/pylith/sources/Source.py new file mode 100644 index 0000000000..0da20cec68 --- /dev/null +++ b/pylith/sources/Source.py @@ -0,0 +1,86 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/Source.py +# +# @brief Python abstract base class for managing input and out put +# sources not necessarily pertaining to domain boundaries +# +# Factory: source + +from pylith.problems.Physics import Physics +from .sources import Source as ModuleSource + + +def validateDescription(value): + """Validate description. + """ + if 0 == len(value): + raise ValueError("Description for material not specified.") + return value + + +class Source(Physics, ModuleSource): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + description = pythia.pyre.inventory.str("description", default="", validator=validateDescription) + description.meta['tip'] = "Descriptive label for material." + + labelName = pythia.pyre.inventory.str("label", default="source-id", validator=pythia.pyre.inventory.choice(["source-id"])) + labelName.meta['tip'] = "Name of label for source. Currently only 'source-id' is allowed." + + labelValue = pythia.pyre.inventory.int("label_value", default=1) + labelValue.meta['tip'] = "Value of label identifying source." + + from pylith.meshio.PointsList import PointsList + reader = pythia.pyre.inventory.facility("reader", factory=PointsList, family="points_list") + reader.meta['tip'] = "Reader for points list." + + def __init__(self, name="source"): + """Constructor. + """ + Physics.__init__(self, name) + return + + def preinitialize(self, problem): + """Setup source. + """ + Physics.preinitialize(self, problem) + ModuleSource.setDescription(self, self.description) + ModuleSource.setLabelName(self, self.labelName) + ModuleSource.setLabelValue(self, self.labelValue) + + sourceNames, sourceCoords = self.reader.read() + + # Convert to mesh coordinate system + from spatialdata.geocoords.Converter import convert + convert(sourceCoords, problem.mesh().getCoordSys(), self.reader.coordsys) + + # Nondimensionalize + if hasattr(problem.normalizer,'lengthScale'): + sourceCoords /= problem.normalizer.lengthScale.value + else: + sourceCoords /= (problem.normalizer.shearWaveSpeed.value * problem.normalizer.wavePeriod.value) + + ModuleSource.setPoints(self, sourceCoords, sourceNames) + return + + +# End of file diff --git a/pylith/sources/SourceTimeFunctionMomentTensorForce.py b/pylith/sources/SourceTimeFunctionMomentTensorForce.py new file mode 100644 index 0000000000..21c181f40b --- /dev/null +++ b/pylith/sources/SourceTimeFunctionMomentTensorForce.py @@ -0,0 +1,79 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2021 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/SourceTimeFunctionMomentTensorForce.py +# +# @brief Python material for isotropic, linearly elastic, plane +# strain material. +# +# Factory: momenttensorforce_sourcetimefunction + +from pylith.utils.PetscComponent import PetscComponent +from .sources import SourceTimeFunctionMomentTensorForce as ModuleSourceTimeFunction + + +class SourceTimeFunctionMomentTensorForce(PetscComponent, ModuleSourceTimeFunction): + """Python object for sourcetimefunction of a momenttensor source. + + FACTORY: momenttensorforce_sourcetimefunction + """ + import pythia.pyre.inventory + + from pylith.topology.Subfield import subfieldFactory + from pylith.utils.EmptyBin import EmptyBin + + auxiliarySubfields = pythia.pyre.inventory.facilityArray( + "auxiliary_subfields", itemFactory=subfieldFactory, factory=EmptyBin) + auxiliarySubfields.meta['tip'] = "Discretization information for physical properties and state variables." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name): + """Constructor. + """ + PetscComponent.__init__(self, name, facility="sourcetimefunctionmomenttensorforce") + return + + def preinitialize(self, problem): + from pylith.mpi.Communicator import mpi_comm_world + comm = mpi_comm_world() + if 0 == comm.rank: + self._info.log( + "Performing minimal initialization of momenttensorforce sourcetimefunction '%s'." % self.aliases[-1]) + + self._createModuleObj() + return + + def addAuxiliarySubfields(self, material, problem): + for subfield in self.auxiliarySubfields.components(): + fieldName = subfield.aliases[-1] + descriptor = subfield.getTraitDescriptor("quadrature_order") + if hasattr(descriptor.locator, "source") and descriptor.locator.source == "default": + quadOrder = problem.defaults.quadOrder + else: + quadOrder = subfield.quadOrder + material.setAuxiliarySubfieldDiscretization(fieldName, subfield.basisOrder, quadOrder, subfield.dimension, + subfield.cellBasis, subfield.feSpace, subfield.isBasisContinuous) + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _createModuleObj(self): + """Call constructor for module object for access to C++ object. + """ + raise NotImplementedError("Implement in derived class.") + + +# End of file diff --git a/pylith/sources/SquarePulseSource.py b/pylith/sources/SquarePulseSource.py new file mode 100644 index 0000000000..4132db454b --- /dev/null +++ b/pylith/sources/SquarePulseSource.py @@ -0,0 +1,71 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/SquarePulseSource.py +# +# @brief Python object for solving the squarepulsesource equation. +# +# Factory: source + +from .Source import Source +from .sources import SquarePulseSource as ModuleSquarePulseSource + + +class SquarePulseSource(Source, ModuleSquarePulseSource): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="squarepulsesource"): + """Constructor. + """ + Source.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSquarePulseSource import AuxSubfieldsSquarePulseSource + self.auxiliarySubfields = AuxSubfieldsSquarePulseSource("auxiliary_subfields") + + + def preinitialize(self, problem): + """Setup source. + """ + Source.preinitialize(self, problem) + + + return + + def _createModuleObj(self): + """Create handle to C++ SquarePulseSource. + """ + ModuleSquarePulseSource.__init__(self) + return + + +# Factories + +def source(): + """Factory associated with SquarePulseSource. + """ + return SquarePulseSource() + + +# End of file diff --git a/pylith/sources/WellboreSource.py b/pylith/sources/WellboreSource.py new file mode 100644 index 0000000000..cf1bad6a60 --- /dev/null +++ b/pylith/sources/WellboreSource.py @@ -0,0 +1,71 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/WellboreSource.py +# +# @brief Python object for solving the wellboresource equation. +# +# Factory: source + +from .Source import Source +from .sources import WellboreSource as ModuleWellboreSource + + +class WellboreSource(Source, ModuleWellboreSource): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="wellboresource"): + """Constructor. + """ + Source.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsWellboreSource import AuxSubfieldsWellboreSource + self.auxiliarySubfields = AuxSubfieldsWellboreSource("auxiliary_subfields") + + + def preinitialize(self, problem): + """Setup source. + """ + Source.preinitialize(self, problem) + + + return + + def _createModuleObj(self): + """Create handle to C++ WellboreSource. + """ + ModuleWellboreSource.__init__(self) + return + + +# Factories + +def source(): + """Factory associated with WellboreSource. + """ + return WellboreSource() + + +# End of file diff --git a/pylith/sources/__init__.py b/pylith/sources/__init__.py new file mode 100644 index 0000000000..f14e0fbcc2 --- /dev/null +++ b/pylith/sources/__init__.py @@ -0,0 +1,37 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2017 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# + +# @file pylith/sources/__init__" + +# @brief Python PyLith sources module initialization + +__all__ = [ + "Source", + "AuxSubfieldsWellboreSource", + "WellboreSource", + "SquarePulseSource", + "PointForce", + "AuxSubfieldsPointForce", + "MomentTensorForce", + "AuxSubfieldsMomentTensorForce", + "SourceTimeFunctionMomentTensorForce", + "AuxSubfieldsSourceTime", + "RickerWavelet", + "GaussianWavelet" +] + + +# End of file From a0584a9ba2a3e4d3ab759db2243cf2eccbadff0c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 13 Jun 2023 16:10:23 -0600 Subject: [PATCH 03/65] Fixed STF nomenclature and added files to makefile --- libsrc/pylith/Makefile.am | 5 +++++ pylith/sources/RickerWavelet.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index d9821e5f73..be663db147 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -70,6 +70,11 @@ libpylith_la_SOURCES = \ fekernels/Tensor.cc \ fekernels/IsotropicLinearGenMaxwell.cc \ fekernels/IsotropicPowerLaw.cc \ + fekernels/GaussianWavelet.cc \ + fekernels/PointForce.cc \ + fekernels/RickerWavelet.cc \ + fekernels/SquarePulseSource.cc \ + fekernels/WellboreSource.cc \ materials/Material.cc \ materials/Elasticity.cc \ materials/RheologyElasticity.cc \ diff --git a/pylith/sources/RickerWavelet.py b/pylith/sources/RickerWavelet.py index 90bc5ed943..c986e52e78 100644 --- a/pylith/sources/RickerWavelet.py +++ b/pylith/sources/RickerWavelet.py @@ -59,7 +59,7 @@ def _createModuleObj(self): # FACTORIES //////////////////////////////////////////////////////////// -def pointforce_sourcetimefunction(): +def momenttensorforce_sourcetimefunction(): """Factory associated with RickerWavelet. """ return RickerWavelet() From 8327dfd2a7e9e16c549a5757a1e54787c475e5a3 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 13 Jun 2023 16:41:26 -0600 Subject: [PATCH 04/65] Issue with identifing point for source in parallel --- libsrc/pylith/sources/MomentTensorForce.cc | 3 ++- libsrc/pylith/sources/PointForce.cc | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 74ee2c1584..99a60dd0ea 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -124,7 +124,7 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie PetscScalar *a; err = DMGetCoordinateDim(dmSoln, &dim);PYLITH_CHECK_ERROR(err); - err = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, + err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); // Debug @@ -141,6 +141,7 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints);PYLITH_CHECK_ERROR(err); + err = PetscSFView(sfPoints, NULL);PYLITH_CHECK_ERROR(err); err = VecDestroy(&vecPoints);PYLITH_CHECK_ERROR(err); err = DMCreateLabel(dmSoln,getLabelName());PYLITH_CHECK_ERROR(err); err = DMGetLabel(dmSoln,getLabelName(), &label);PYLITH_CHECK_ERROR(err); diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc index a249383dd1..67fa514825 100644 --- a/libsrc/pylith/sources/PointForce.cc +++ b/libsrc/pylith/sources/PointForce.cc @@ -145,8 +145,9 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field &sol err = DMGetCoordinateDim(dmSoln, &dim); PYLITH_CHECK_ERROR(err); - err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, - &_pointCoords[0], &vecPoints); + err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), + &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); + PYLITH_CHECK_ERROR(err); // Debug From 458b22499555ffbca3a54f7ac7df5fa95e35c120 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 13:25:20 -0600 Subject: [PATCH 05/65] Added Square Wavelet for testing --- libsrc/pylith/Makefile.am | 1 + libsrc/pylith/fekernels/GaussianWavelet.cc | 8 +- libsrc/pylith/fekernels/RickerWavelet.cc | 88 ++++++----- libsrc/pylith/fekernels/SquareWavelet.cc | 138 +++++++++++++++++ libsrc/pylith/fekernels/SquareWavelet.hh | 143 ++++++++++++++++++ .../AuxiliaryFactoryMomentTensorForce.hh | 6 +- libsrc/pylith/sources/Makefile.am | 1 + libsrc/pylith/sources/SquareWavelet.cc | 98 ++++++++++++ libsrc/pylith/sources/SquareWavelet.hh | 81 ++++++++++ libsrc/pylith/sources/sourcesfwd.hh | 1 + modulesrc/sources/MomentTensorForce.i | 4 +- modulesrc/sources/SquareWavelet.i | 67 ++++++++ modulesrc/sources/sources.i | 2 + pylith/Makefile.am | 1 + pylith/sources/AuxSubfieldsPointForce.py | 4 + pylith/sources/MomentTensorForce.py | 2 +- pylith/sources/PointForce.py | 1 + pylith/sources/SquareWavelet.py | 68 +++++++++ pylith/sources/__init__.py | 1 + 19 files changed, 664 insertions(+), 51 deletions(-) create mode 100644 libsrc/pylith/fekernels/SquareWavelet.cc create mode 100644 libsrc/pylith/fekernels/SquareWavelet.hh create mode 100644 libsrc/pylith/sources/SquareWavelet.cc create mode 100644 libsrc/pylith/sources/SquareWavelet.hh create mode 100644 modulesrc/sources/SquareWavelet.i create mode 100644 pylith/sources/SquareWavelet.py diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index be663db147..ba7da24f3f 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -143,6 +143,7 @@ libpylith_la_SOURCES = \ sources/GaussianWavelet.cc \ sources/MomentTensorForce.cc \ sources/PointForce.cc \ + sources/SquareWavelet.cc \ sources/RickerWavelet.cc \ sources/Source.cc \ sources/SourceTimeFunctionMomentTensorForce.cc \ diff --git a/libsrc/pylith/fekernels/GaussianWavelet.cc b/libsrc/pylith/fekernels/GaussianWavelet.cc index fc58d01540..5193f0cdcf 100644 --- a/libsrc/pylith/fekernels/GaussianWavelet.cc +++ b/libsrc/pylith/fekernels/GaussianWavelet.cc @@ -24,7 +24,7 @@ #include // debugging. // ===================================================================================================================== -// Kernels for the Ricker Source Time Function in 2D. +// Kernels for the Gaussian Source Time Function in 2D. // ===================================================================================================================== // ---------------------------------------------------------------------- @@ -69,7 +69,9 @@ pylith::fekernels::GaussianWaveletPlaneStrain::g1v(const PylithInt dim, PylithScalar rt = t - timeDelay; PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); - + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %d\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %d\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "gaussianWavelet %d\n", (double)gaussianwavelet); for (PylithInt i = 0; i < dim*dim; ++i) { g1[i] -= momentTensor[i] * gaussianwavelet; } // for @@ -77,7 +79,7 @@ pylith::fekernels::GaussianWaveletPlaneStrain::g1v(const PylithInt dim, // ===================================================================================================================== -// Kernels for the Ricker Source Time Function in 3D. +// Kernels for the Gaussian Source Time Function in 3D. // ===================================================================================================================== // ---------------------------------------------------------------------- diff --git a/libsrc/pylith/fekernels/RickerWavelet.cc b/libsrc/pylith/fekernels/RickerWavelet.cc index 6f41ae3a56..5921f106d4 100644 --- a/libsrc/pylith/fekernels/RickerWavelet.cc +++ b/libsrc/pylith/fekernels/RickerWavelet.cc @@ -31,23 +31,23 @@ // g1 entry function for velocity equation void pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { assert(sOff); assert(s); assert(g1); @@ -56,12 +56,11 @@ pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, // Incoming re-packed solution field. - // Incoming re-packed auxiliary field. const PylithInt i_momentTensor = 0; const PylithInt i_timeDelay = 1; const PylithInt i_rickerwaveletCenterFrequency = numA - 1; - + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; const PylithScalar timeDelay = a[aOff[i_timeDelay]]; const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; @@ -69,11 +68,17 @@ pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, // RickerWavelet source time function (time domain) PylithScalar rt = t - timeDelay; - PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * - PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); for (PylithInt i = 0; i < dim*dim; ++i) { g1[i] -= momentTensor[i] * rickerwavelet; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); } // for } // g1v @@ -86,23 +91,23 @@ pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, // g1 entry function for velocity equation void pylith::fekernels::RickerWavelet3D::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { assert(sOff); assert(s); assert(g1); @@ -111,12 +116,11 @@ pylith::fekernels::RickerWavelet3D::g1v(const PylithInt dim, // Incoming re-packed solution field. - // Incoming re-packed auxiliary field. const PylithInt i_momentTensor = 0; const PylithInt i_timeDelay = 1; const PylithInt i_rickerwaveletCenterFrequency = numA - 1; - + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; const PylithScalar timeDelay = a[aOff[i_timeDelay]]; const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; @@ -124,8 +128,8 @@ pylith::fekernels::RickerWavelet3D::g1v(const PylithInt dim, // RickerWavelet source time function (time domain) PylithScalar rt = t - timeDelay; - PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * - PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); for (PylithInt i = 0; i < dim*dim; ++i) { g1[i] -= momentTensor[i] * rickerwavelet; diff --git a/libsrc/pylith/fekernels/SquareWavelet.cc b/libsrc/pylith/fekernels/SquareWavelet.cc new file mode 100644 index 0000000000..3296517025 --- /dev/null +++ b/libsrc/pylith/fekernels/SquareWavelet.cc @@ -0,0 +1,138 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +#include + +#include "pylith/fekernels/SquareWavelet.hh" + +#include // USES assert() +#include // debugging. + +// ===================================================================================================================== +// Kernels for the Square Source Time Function in 2D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::SquareWaveletPlaneStrain::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 2; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_squarewaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; + + // SquareWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)squarewaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "squareWavelet %f\n", (double)squarewavelet); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * squarewavelet; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - square\n", (int)i, (double)g1[i]); + } // for +} // g1v + + +// ===================================================================================================================== +// Kernels for the Square Source Time Function in 3D. +// ===================================================================================================================== + +// ---------------------------------------------------------------------- +// g1 entry function for velocity equation +void +pylith::fekernels::SquareWavelet3D::g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_squarewaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; + + // SquareWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * squarewavelet; + } // for +} // g1v + + +// End of file diff --git a/libsrc/pylith/fekernels/SquareWavelet.hh b/libsrc/pylith/fekernels/SquareWavelet.hh new file mode 100644 index 0000000000..842c5997c6 --- /dev/null +++ b/libsrc/pylith/fekernels/SquareWavelet.hh @@ -0,0 +1,143 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/SquareWavelet.hh + * + */ + +#if !defined(pylith_fekernels_squarewavelet_hh) +#define pylith_fekernels_squarewavelet_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +// ===================================================================================================================== +// Kernels for the Square Source Time Function in 2D. +// ===================================================================================================================== + +class pylith::fekernels::SquareWaveletPlaneStrain { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // SquareWaveletPlaneStrain + +// ===================================================================================================================== +// Kernels for the Square Source Time Function in 3D. +// ===================================================================================================================== + +class pylith::fekernels::SquareWavelet3D { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // SquareWaveletPlaneStrain + +#endif /* pylith_fekernels_squarewavelet_hh */ + +/* End of file */ diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh index 4a0318dbae..024ee4f78d 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh @@ -18,7 +18,7 @@ /** @file libsrc/sources/AuxiliaryFactoryMomentTensorForce.hh * - * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. + * @brief C++ helper class for setting up auxiliary subfields for the moment tensor force equation. */ #if !defined(pylith_sources_auxiliaryfactorymomenttensorforce_hh) @@ -41,10 +41,10 @@ public: /// Destructor. virtual ~AuxiliaryFactoryMomentTensorForce(void); - /// Add fluid density subfield to auxiliary subfields. + /// Add moment tensor subfield to auxiliary subfields. void addMomentTensor(void); - /// Add fluid viscosity subfield to auxiliary subfields. + /// Add time delay subfield to auxiliary subfields. void addTimeDelay(void); // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index 02ae68fd25..f51f3b46ce 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -29,6 +29,7 @@ subpkginclude_HEADERS = \ AuxiliaryFactoryWellboreSource.hh \ AuxiliaryFactorySourceTime.hh \ DerivedFactoryMomentTensorForce.hh \ + SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ PointForce.hh \ diff --git a/libsrc/pylith/sources/SquareWavelet.cc b/libsrc/pylith/sources/SquareWavelet.cc new file mode 100644 index 0000000000..027cea68d7 --- /dev/null +++ b/libsrc/pylith/sources/SquareWavelet.cc @@ -0,0 +1,98 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/SquareWavelet.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/fekernels/SquareWavelet.hh" // USES SquareWavelet kernels +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::SquareWavelet::SquareWavelet(void) : + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + pylith::utils::PyreComponent::setName("squarewavelet"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::SquareWavelet::~SquareWavelet(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::SquareWavelet::deallocate(void) { + SourceTimeFunctionMomentTensorForce::deallocate(); + + delete _auxiliaryFactory;_auxiliaryFactory = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::sources::AuxiliaryFactoryMomentTensorForce* +pylith::sources::SquareWavelet::getAuxiliaryFactory(void) { + return _auxiliaryFactory; +} // getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Add source time subfields to auxiliary field. +void +pylith::sources::SquareWavelet::addAuxiliarySubfields(void) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addAuxiliarySubfields(void)"); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise + // functions (kernels). + + _auxiliaryFactory->addCenterFrequency(); // numA - 1 + + PYLITH_METHOD_END; +} // addAuxiliarySubfields + + +// --------------------------------------------------------------------------------------------------------------------- +// Get g1v kernel for residual, G(t,s). +PetscPointFunc +pylith::sources::SquareWavelet::getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("getKernelg1v_explicit(coordsys="<getSpaceDim(); + PetscPointFunc g1v = + (3 == spaceDim) ? pylith::fekernels::SquareWavelet3D::g1v : + (2 == spaceDim) ? pylith::fekernels::SquareWaveletPlaneStrain::g1v : + NULL; + + PYLITH_METHOD_RETURN(g1v); +} // getKernelResidualStress + + +// End of file diff --git a/libsrc/pylith/sources/SquareWavelet.hh b/libsrc/pylith/sources/SquareWavelet.hh new file mode 100644 index 0000000000..f5149d7524 --- /dev/null +++ b/libsrc/pylith/sources/SquareWavelet.hh @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/SquareWavelet.hh + * + * @brief C++ class for Square source time function. + */ + +#if !defined(pylith_materials_squarewavelet_hh) +#define pylith_materials_squarewavelet_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // ISA SourceTimeFunctionMomentTensorForce + +class pylith::sources::SquareWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + friend class TestSquareWavelet; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SquareWavelet(void); + + /// Destructor. + ~SquareWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v. + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + SquareWavelet(const SquareWavelet&); ///< Not implemented. + const SquareWavelet& operator=(const SquareWavelet&); /// Not implemented. + +}; // class SquareWavelet + +#endif // pylith_materials_squarewavelet_hh + +// End of file diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh index ad59acca0c..f792bec2cc 100644 --- a/libsrc/pylith/sources/sourcesfwd.hh +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -38,6 +38,7 @@ namespace pylith { class SourceTimeFunctionMomentTensorForce; class AuxiliaryFactorySourceTime; + class SquareWavelet; class RickerWavelet; class GaussianWavelet; diff --git a/modulesrc/sources/MomentTensorForce.i b/modulesrc/sources/MomentTensorForce.i index 0816632f61..b4fca5fe50 100644 --- a/modulesrc/sources/MomentTensorForce.i +++ b/modulesrc/sources/MomentTensorForce.i @@ -38,13 +38,13 @@ public: /** Set source time function. * - * @param[in] sourceTimeFunction Source time function for point force. + * @param[in] sourceTimeFunction Source time function for moment tensor force. */ void setSourceTimeFunction(pylith::sources::SourceTimeFunctionMomentTensorForce* const sourceTimeFunction); /** Get source time function. * - * @returns Source time function for point force. + * @returns Source time function for moment tensor force. */ pylith::sources::SourceTimeFunctionMomentTensorForce* getSourceTimeFunction(void) const; diff --git a/modulesrc/sources/SquareWavelet.i b/modulesrc/sources/SquareWavelet.i new file mode 100644 index 0000000000..5afa1dddf6 --- /dev/null +++ b/modulesrc/sources/SquareWavelet.i @@ -0,0 +1,67 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/SquareWavelet.i + * + * Python interface to C++ SquareWavelet. + */ + +namespace pylith { + namespace sources { + class SquareWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SquareWavelet(void); + + /// Destructor. + ~SquareWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time function subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v + . + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + }; + + // class SquareWavelet + + } // sources +} // pylith + +// End of file diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i index 541ee08ea1..ea2e3db9bb 100644 --- a/modulesrc/sources/sources.i +++ b/modulesrc/sources/sources.i @@ -23,6 +23,7 @@ #include "pylith/sources/SquarePulseSource.hh" #include "pylith/sources/PointForce.hh" #include "pylith/sources/MomentTensorForce.hh" +#include "pylith/sources/SquareWavelet.hh" #include "pylith/sources/RickerWavelet.hh" #include "pylith/sources/GaussianWavelet.hh" #include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" @@ -62,6 +63,7 @@ import_array(); %include "PointForce.i" %include "MomentTensorForce.i" %include "SourceTimeFunctionMomentTensorForce.i" +%include "SquareWavelet.i" %include "RickerWavelet.i" %include "GaussianWavelet.i" diff --git a/pylith/Makefile.am b/pylith/Makefile.am index 71892dda1d..97ae30f110 100644 --- a/pylith/Makefile.am +++ b/pylith/Makefile.am @@ -143,6 +143,7 @@ EXTRA_DIST = \ sources/SquarePulseSource.py \ sources/SourceTimeFunctionMomentTensorForce.py \ sources/Source.py \ + sources/SquareWavelet.py \ sources/RickerWavelet.py \ sources/PointForce.py \ sources/MomentTensorForce.py \ diff --git a/pylith/sources/AuxSubfieldsPointForce.py b/pylith/sources/AuxSubfieldsPointForce.py index 395a9dc9d2..91345d3898 100644 --- a/pylith/sources/AuxSubfieldsPointForce.py +++ b/pylith/sources/AuxSubfieldsPointForce.py @@ -33,6 +33,10 @@ class AuxSubfieldsPointForce(PetscComponent): pointForce = pythia.pyre.inventory.facility("point_force", family="auxiliary_subfield", factory=Subfield) pointForce.meta['tip'] = "Point Force subfield." + TimeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) + TimeDelay.meta['tip'] = "time delay subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="auxsubfieldspointforce"): diff --git a/pylith/sources/MomentTensorForce.py b/pylith/sources/MomentTensorForce.py index 078e3af546..8dd57add15 100644 --- a/pylith/sources/MomentTensorForce.py +++ b/pylith/sources/MomentTensorForce.py @@ -33,7 +33,7 @@ class MomentTensorForce(Source, ModuleMomentTensorForce): import pythia.pyre.inventory source_time_function = pythia.pyre.inventory.facility("source_time_function", family="momenttensorforce_sourcetimefunction", factory=RickerWavelet) - source_time_function.meta['tip'] = "Source time function for momenttensor force." + source_time_function.meta['tip'] = "Source time function for moment tensor force." # PUBLIC METHODS ///////////////////////////////////////////////////// diff --git a/pylith/sources/PointForce.py b/pylith/sources/PointForce.py index 53f71d8b26..dff7509335 100644 --- a/pylith/sources/PointForce.py +++ b/pylith/sources/PointForce.py @@ -57,6 +57,7 @@ def _createModuleObj(self): """Create handle to C++ PointForce. """ ModulePointForce.__init__(self) + ModuleMomentTensorForce.setSourceTimeFunction(self, self.source_time_function) # Material sets auxiliary db in source_time_function. return diff --git a/pylith/sources/SquareWavelet.py b/pylith/sources/SquareWavelet.py new file mode 100644 index 0000000000..c8a879e97b --- /dev/null +++ b/pylith/sources/SquareWavelet.py @@ -0,0 +1,68 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2021 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/SquareWavelet.py +# +# @brief Python source time functiof for a square wavelet. +# +# Factory: pointforce_sourcetimefunction + +from .SourceTimeFunctionMomentTensorForce import SourceTimeFunctionMomentTensorForce +from .sources import SquareWavelet as ModuleSquareWavelet + + +class SquareWavelet(SourceTimeFunctionMomentTensorForce, ModuleSquareWavelet): + """Python source time function for square source. + + FACTORY: pointforce_sourcetimefunction + """ + + import pythia.pyre.inventory + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="squarewavelet"): + """Constructor. + """ + SourceTimeFunctionMomentTensorForce.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSourceTime import AuxSubfieldsSourceTime + self.auxiliarySubfields = AuxSubfieldsSourceTime("auxiliary_subfields") + + def preinitialize(self, problem): + SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) + + + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _createModuleObj(self): + """Call constructor for module object for access to C++ object. + """ + ModuleSquareWavelet.__init__(self) + + +# FACTORIES //////////////////////////////////////////////////////////// + +def momenttensorforce_sourcetimefunction(): + """Factory associated with SquareWavelet. + """ + return SquareWavelet() + + +# End of file diff --git a/pylith/sources/__init__.py b/pylith/sources/__init__.py index f14e0fbcc2..837c625920 100644 --- a/pylith/sources/__init__.py +++ b/pylith/sources/__init__.py @@ -29,6 +29,7 @@ "AuxSubfieldsMomentTensorForce", "SourceTimeFunctionMomentTensorForce", "AuxSubfieldsSourceTime", + "SquareWavelet", "RickerWavelet", "GaussianWavelet" ] From ab046c0e168927e3df35f4429e5af134e7d933ac Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 15:54:05 -0600 Subject: [PATCH 06/65] Added listing for squarewavelet classes --- libsrc/pylith/Makefile.am | 1 + libsrc/pylith/fekernels/Makefile.am | 1 + libsrc/pylith/fekernels/fekernelsfwd.hh | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index ba7da24f3f..f546abac4f 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -70,6 +70,7 @@ libpylith_la_SOURCES = \ fekernels/Tensor.cc \ fekernels/IsotropicLinearGenMaxwell.cc \ fekernels/IsotropicPowerLaw.cc \ + fekernels/SquareWavelet.cc \ fekernels/GaussianWavelet.cc \ fekernels/PointForce.cc \ fekernels/RickerWavelet.cc \ diff --git a/libsrc/pylith/fekernels/Makefile.am b/libsrc/pylith/fekernels/Makefile.am index 2558368be2..3875836334 100644 --- a/libsrc/pylith/fekernels/Makefile.am +++ b/libsrc/pylith/fekernels/Makefile.am @@ -35,6 +35,7 @@ subpkginclude_HEADERS = \ Poroelasticity.hh \ WellboreSource.hh \ SquarePulseSource.hh \ + SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ PointForce.hh diff --git a/libsrc/pylith/fekernels/fekernelsfwd.hh b/libsrc/pylith/fekernels/fekernelsfwd.hh index 56d4b7199f..33fc94d255 100644 --- a/libsrc/pylith/fekernels/fekernelsfwd.hh +++ b/libsrc/pylith/fekernels/fekernelsfwd.hh @@ -60,6 +60,10 @@ namespace pylith { class SquarePulseSource; class WellboreSource; + class SquareWavelet; + class SquareWaveletPlaneStrain; + class SquareWavelet3D; + class RickerWavelet; class RickerWaveletPlaneStrain; class RickerWavelet3D; From 6766e726203cc4b9b1bf3a08373858721a295980 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 17:22:26 -0600 Subject: [PATCH 07/65] Added lumped LHS mass matrix for MT source --- libsrc/pylith/sources/MomentTensorForce.cc | 50 ++++++++- libsrc/pylith/sources/WellboreSource.cc | 117 +++++++++++---------- 2 files changed, 104 insertions(+), 63 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 99a60dd0ea..854b929903 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -27,6 +27,7 @@ #include "pylith/topology/Mesh.hh" // USES Mesh #include "pylith/topology/Field.hh" // USES Field::SubfieldInfo #include "pylith/topology/FieldOps.hh" // USES FieldOps +#include "pylith/fekernels/DispVel.hh" // USES DispVel kernels #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* @@ -104,7 +105,7 @@ pylith::sources::MomentTensorForce::verifyConfiguration(const pylith::topology:: // --------------------------------------------------------------------------------------------------------------------- // Create integrator and set kernels. pylith::feassemble::Integrator* -pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Field& solution) { +pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Field &solution) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution="< kernels; - + std::vector kernels(1); switch (_formulation) { case QUASISTATIC: { break; @@ -271,7 +271,6 @@ pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::Inte const PetscPointFunc g0v = NULL; const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); - kernels.resize(1); kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); break; } // DYNAMIC @@ -293,10 +292,51 @@ pylith::sources::MomentTensorForce::_setKernelsJacobian(pylith::feassemble::Inte const topology::Field& solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; + + switch (_formulation) { + case QUASISTATIC: { + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + case DYNAMIC: { + typedef pylith::feassemble::JacobianValues::JacobianKernel ValueKernel; + std::vector valueKernelsJacobian(2); + std::vector valueKernelsPrecond; + valueKernelsJacobian[0] = ValueKernel("displacement", "displacement", pylith::feassemble::JacobianValues::blockDiag_tshift); + valueKernelsJacobian[1] = ValueKernel("velocity", "velocity", pylith::feassemble::JacobianValues::blockDiag_tshift); + integrator->setKernelsJacobian(valueKernelsJacobian, valueKernelsPrecond); + + const PetscPointJac Jf0uu = pylith::fekernels::DispVel::Jg0uv; + const PetscPointJac Jf1uu = NULL; + const PetscPointJac Jf2uu = NULL; + const PetscPointJac Jf3uu = NULL; + + const PetscPointJac Jf0vv = pylith::fekernels::DispVel::Jg0uv; + const PetscPointJac Jf1vv = NULL; + const PetscPointJac Jf2vv = NULL; + const PetscPointJac Jf3vv = NULL; + + integrator->setLHSJacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_TIME_STEP_CHANGE); + + kernels.resize(2); + const EquationPart equationPart = pylith::feassemble::Integrator::LHS_LUMPED_INV; + kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); + kernels[1] = JacobianKernels("velocity", "velocity", equationPart, Jf0vv, Jf1vv, Jf2vv, Jf3vv); + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + integrator->setKernelsJacobian(kernels, solution); PYLITH_METHOD_END; + } // _setKernelsJacobian diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc index c7eb935947..be654be7d6 100644 --- a/libsrc/pylith/sources/WellboreSource.cc +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -21,17 +21,17 @@ #include "pylith/sources/WellboreSource.hh" // implementation of object methods #include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // USES AuxiliaryFactoryWellboreSource -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/fekernels/WellboreSource.hh" // USES WellboreSource kernels -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include // USES typeid() @@ -45,82 +45,85 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::WellboreSource::WellboreSource(void) : _useInertia(false), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryWellboreSource) -{ + _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryWellboreSource) { pylith::utils::PyreComponent::setName("wellboresource"); } // constructor + // --------------------------------------------------------------------------------------------------------------------- // Destructor. -pylith::sources::WellboreSource::~WellboreSource(void) -{ +pylith::sources::WellboreSource::~WellboreSource(void) { deallocate(); } // destructor + // --------------------------------------------------------------------------------------------------------------------- // Deallocate PETSc and local data structures. -void pylith::sources::WellboreSource::deallocate(void) -{ +void +pylith::sources::WellboreSource::deallocate(void) { Source::deallocate(); delete _auxiliaryFactory; _auxiliaryFactory = NULL; } // deallocate + // --------------------------------------------------------------------------------------------------------------------- // Set time history database. -void pylith::sources::WellboreSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) -{ +void +pylith::sources::WellboreSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); _dbTimeHistory = th; } // setTimeHistoryDB + // --------------------------------------------------------------------------------------------------------------------- // Get time history database. const spatialdata::spatialdb::TimeHistory * -pylith::sources::WellboreSource::getTimeHistoryDB(void) -{ +pylith::sources::WellboreSource::getTimeHistoryDB(void) { return _dbTimeHistory; } // getTimeHistoryDB + // --------------------------------------------------------------------------------------------------------------------- // Use time history term in time history expression. -void pylith::sources::WellboreSource::useTimeHistory(const bool value) -{ +void +pylith::sources::WellboreSource::useTimeHistory(const bool value) { PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); _useTimeHistory = value; } // useTimeHistory + // --------------------------------------------------------------------------------------------------------------------- // Get flag associated with using time history term in time history expression. -bool pylith::sources::WellboreSource::useTimeHistory(void) const -{ +bool +pylith::sources::WellboreSource::useTimeHistory(void) const { return _useTimeHistory; } // useTimeHistory + // --------------------------------------------------------------------------------------------------------------------- // Verify configuration is acceptable. -void pylith::sources::WellboreSource::verifyConfiguration(const pylith::topology::Field &solution) const -{ +void +pylith::sources::WellboreSource::verifyConfiguration(const pylith::topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) - { + if (!solution.hasSubfield("pressure")) { throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'WellboreSource'."); } // if PYLITH_METHOD_END; } // verifyConfiguration + // --------------------------------------------------------------------------------------------------------------------- // Create integrator and set kernels. pylith::feassemble::Integrator * -pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field &solution) -{ +pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field &solution) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); @@ -140,11 +143,10 @@ pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field PetscMPIInt rank; PetscScalar *a; - err = DMGetCoordinateDim(dmSoln, &dim); - PYLITH_CHECK_ERROR(err); - err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, - &_pointCoords[0], &vecPoints); - PYLITH_CHECK_ERROR(err); + err = DMGetCoordinateDim(dmSoln, &dim);PYLITH_CHECK_ERROR(err); + + err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), + &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); // Debug // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); @@ -173,10 +175,8 @@ pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field PYLITH_CHECK_ERROR(err); // Debug // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); - for (PetscInt p = 0; p < numLeaves; ++p) - { - if (remotePoints[p].rank == rank) - { + for (PetscInt p = 0; p < numLeaves; ++p) { + if (remotePoints[p].rank == rank) { err = DMLabelSetValue(label, remotePoints[p].index, 2); PYLITH_CHECK_ERROR(err); } @@ -197,12 +197,12 @@ pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field PYLITH_METHOD_RETURN(integrator); } // createIntegrator + // --------------------------------------------------------------------------------------------------------------------- // Create auxiliary field. pylith::topology::Field * pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) -{ + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); @@ -222,14 +222,14 @@ pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Fi // of magnitude of 1. // add in aux specific to peaceman - _auxiliaryFactory->addFluidDensity(); // 0 - _auxiliaryFactory->addFluidViscosity(); // 1 + _auxiliaryFactory->addFluidDensity(); // 0 + _auxiliaryFactory->addFluidViscosity(); // 1 _auxiliaryFactory->addIsotropicPermeability(); // 2 - _auxiliaryFactory->addWellboreRadius(); // 3 - _auxiliaryFactory->addWellboreLength(); // 4 - _auxiliaryFactory->addWellborePressure(); // 5 - _auxiliaryFactory->addWellboreCharacter(); // 6 - _auxiliaryFactory->addElementDimensions(); // 7 + _auxiliaryFactory->addWellboreRadius(); // 3 + _auxiliaryFactory->addWellboreLength(); // 4 + _auxiliaryFactory->addWellborePressure(); // 5 + _auxiliaryFactory->addWellboreCharacter(); // 6 + _auxiliaryFactory->addElementDimensions(); // 7 auxiliaryField->subfieldsSetup(); auxiliaryField->createDiscretization(); @@ -246,31 +246,32 @@ pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Fi PYLITH_METHOD_RETURN(auxiliaryField); } // createAuxiliaryField + // --------------------------------------------------------------------------------------------------------------------- // Create derived field. pylith::topology::Field * pylith::sources::WellboreSource::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) -{ + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); PYLITH_METHOD_RETURN(NULL); } // createDerivedField + // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. pylith::feassemble::AuxiliaryFactory * -pylith::sources::WellboreSource::_getAuxiliaryFactory(void) -{ +pylith::sources::WellboreSource::_getAuxiliaryFactory(void) { return _auxiliaryFactory; } // _getAuxiliaryFactory + // --------------------------------------------------------------------------------------------------------------------- // Set kernels for LHS residual F(t,s,\dot{s}). -void pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const -{ +void +pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); @@ -278,8 +279,7 @@ void pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::In std::vector kernels; - switch (_formulation) - { + switch (_formulation) { case QUASISTATIC: { // Pressure @@ -308,11 +308,12 @@ void pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::In PYLITH_METHOD_END; } // _setKernelsResidual + // --------------------------------------------------------------------------------------------------------------------- // Set kernels for LHS Jacobian F(t,s,\dot{s}). -void pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const -{ +void +pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); @@ -320,8 +321,7 @@ void pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::In std::vector kernels; - switch (_formulation) - { + switch (_formulation) { case QUASISTATIC: { const PetscPointJac Jf0pp = pylith::fekernels::WellboreSource::Jf0pp; @@ -349,4 +349,5 @@ void pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::In PYLITH_METHOD_END; } // _setKernelsJacobian + // End of file From 67f3626c0d3833551a11c0f0b154ce8f79a5296a Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 22:28:42 -0600 Subject: [PATCH 08/65] removed local source label functions --- libsrc/pylith/sources/Source.cc | 25 +------------------------ libsrc/pylith/sources/Source.hh | 28 ++-------------------------- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 15a8c7a409..36dba6ce37 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -54,6 +54,7 @@ pylith::sources::Source::deallocate(void) { PYLITH_METHOD_END; } // deallocate + // ------------------------------------------------------------------------------------------------ // Set descriptive label of source. void @@ -86,30 +87,6 @@ pylith::sources::Source::setLabelName(const char* value) { } // setLabelName -// ------------------------------------------------------------------------------------------------ -// Get name of label marking material. -const char* -pylith::sources::Source::getLabelName(void) const { - return _labelName.c_str(); -} // getLabelName - - -// ------------------------------------------------------------------------------------------------ -// Set value of label marking material. -void -pylith::sources::Source::setLabelValue(const int value) { - _labelValue = value; -} // setLabelValue - - -// ------------------------------------------------------------------------------------------------ -// Get value of label marking material. -int -pylith::sources::Source::getLabelValue(void) const { - return _labelValue; -} // getLabelValue - - // --------------------------------------------------------------------------------------------------------------------- // Create constraint and set kernels. std::vector diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 0499cd58c5..f9cf62997b 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -65,34 +65,10 @@ public: */ const char* getDescription(void) const; - /** Set name of label marking boundary associated with boundary condition surface. - * - * @param[in] value Name of label for surface (from mesh generator). - */ - void setLabelName(const char* value); - - /** Get name of label marking boundary associated with source location. - * - * @returns Name of label for surface (from mesh generator). - */ - const char* getLabelName(void) const; - - /** Set value of label marking boundary associated with source location. - * - * @param[in] value Value of label for surface (from mesh generator). - */ - void setLabelValue(const int value); - - /** Get value of label marking boundary associated with source location. - * - * @returns Value of label for surface (from mesh generator). - */ - int getLabelValue(void) const; - /** Set first choice for reference direction to discriminate among tangential directions in 3-D. * * @param vec Reference direction unit vector. - /** Create constraint and set kernels. + * /** Create constraint and set kernels. * * @param[in] solution Solution field. * @returns Constraint if applicable, otherwise NULL. @@ -122,7 +98,7 @@ protected: std::string _description; ///< Descriptive label for source. std::string _labelName; ///< Name of label to identify source points in mesh. int _labelValue; ///< Value of label to identify source points in mesh. - + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: From 0057d4d8ec101a1dc51cf323d825efcf0f91db57 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 22:38:31 -0600 Subject: [PATCH 09/65] Removed other label function from source --- libsrc/pylith/sources/Source.cc | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 36dba6ce37..cd7e2d58d9 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -73,20 +73,6 @@ pylith::sources::Source::getDescription(void) const { } // getDescription -// ------------------------------------------------------------------------------------------------ -// Set name of label marking material. -void -pylith::sources::Source::setLabelName(const char* value) { - PYLITH_COMPONENT_DEBUG("setLabelName(value="< From 7976afa637349f0a244a4683cb32e98e924ab43c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 23:12:23 -0600 Subject: [PATCH 10/65] Moved coordinate to label assignment to function in Source.cc --- libsrc/pylith/sources/MomentTensorForce.cc | 98 +++++----- libsrc/pylith/sources/Source.cc | 56 ++++++ libsrc/pylith/sources/Source.hh | 4 + libsrc/pylith/sources/SquarePulseSource.cc | 212 +++++++++++---------- libsrc/pylith/sources/WellboreSource.cc | 118 ++++++------ 5 files changed, 278 insertions(+), 210 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 854b929903..8652540068 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -109,59 +109,59 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution="<setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); - printf("In MomentTensorForce end\n"); - DMView(dmSoln, NULL); _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index cd7e2d58d9..04747909d0 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -115,4 +115,60 @@ pylith::sources::Source::setPoints(const PylithReal* pointCoords, } // setPoints +// ------------------------------------------------------------------------------------------------ +// Convert cartesian positions to a labeled source +void +pylith::sources::Source::locateSource(const pylith::topology::Field& solution) { + printf("In MomentTensorForce begin\n"); + DMView(solution.getDM(), NULL); + PetscErrorCode err; + PetscDM dmSoln = solution.getDM();assert(dmSoln); + // transform points of source to mesh coordinates in python + // DM from solution + Vec vecPoints; + DMLabel label; + PetscSF sfPoints = NULL; + const PetscInt *localPoints; + const PetscSFNode *remotePoints; + PetscInt numRoots = -1, numLeaves, dim, d; + PetscMPIInt rank; + PetscScalar *a; + + err = DMGetCoordinateDim(dmSoln, &dim);PYLITH_CHECK_ERROR(err); + err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), + &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); + + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); + // Erzatz from ex17 + // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); + // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); + // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + // for (d = 0; d < _pointCoords.size(); ++d) { + // a[d] = _pointCoords[d]; + // } + // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + + err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints);PYLITH_CHECK_ERROR(err); + err = PetscSFView(sfPoints, NULL);PYLITH_CHECK_ERROR(err); + err = VecDestroy(&vecPoints);PYLITH_CHECK_ERROR(err); + err = DMCreateLabel(dmSoln,getLabelName());PYLITH_CHECK_ERROR(err); + err = DMGetLabel(dmSoln,getLabelName(), &label);PYLITH_CHECK_ERROR(err); + err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints);PYLITH_CHECK_ERROR(err); + err = MPI_Comm_rank(PetscObjectComm((PetscObject) dmSoln), &rank);PYLITH_CHECK_ERROR(err); + // Debug + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); + for (PetscInt p = 0; p < numLeaves; ++p) { + if (remotePoints[p].rank == rank) { + err = DMLabelSetValue(label, remotePoints[p].index, 2);PYLITH_CHECK_ERROR(err); + } + } // for + err = PetscSFDestroy(&sfPoints);PYLITH_CHECK_ERROR(err); + printf("In MomentTensorForce end\n"); + DMView(dmSoln, NULL); +} + + // End of file diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index f9cf62997b..8e637a38db 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -90,6 +90,10 @@ public: const char* const* pointNames, const int numPointNames); + /** Assign source label from coordinates. + */ + void locateSource(const pylith::topology::Field& solution); + // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// protected: diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc index fe6b65f309..608329e414 100644 --- a/libsrc/pylith/sources/SquarePulseSource.cc +++ b/libsrc/pylith/sources/SquarePulseSource.cc @@ -21,17 +21,17 @@ #include "pylith/sources/SquarePulseSource.hh" // implementation of object methods #include "pylith/sources/AuxiliaryFactorySquarePulseSource.hh" // USES AuxiliaryFactorySquarePulseSource -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/fekernels/SquarePulseSource.hh" // USES SquarePulseSource kernels -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include // USES typeid() @@ -45,151 +45,156 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::SquarePulseSource::SquarePulseSource(void) : _useInertia(false), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource) -{ + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource) { pylith::utils::PyreComponent::setName("squarepulsesource"); } // constructor + // --------------------------------------------------------------------------------------------------------------------- // Destructor. -pylith::sources::SquarePulseSource::~SquarePulseSource(void) -{ +pylith::sources::SquarePulseSource::~SquarePulseSource(void) { deallocate(); } // destructor + // --------------------------------------------------------------------------------------------------------------------- // Deallocate PETSc and local data structures. -void pylith::sources::SquarePulseSource::deallocate(void) -{ +void +pylith::sources::SquarePulseSource::deallocate(void) { Source::deallocate(); delete _auxiliaryFactory; _auxiliaryFactory = NULL; } // deallocate + // --------------------------------------------------------------------------------------------------------------------- // Set time history database. -void pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) -{ +void +pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); _dbTimeHistory = th; } // setTimeHistoryDB + // --------------------------------------------------------------------------------------------------------------------- // Get time history database. const spatialdata::spatialdb::TimeHistory * -pylith::sources::SquarePulseSource::getTimeHistoryDB(void) -{ +pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { return _dbTimeHistory; } // getTimeHistoryDB + // --------------------------------------------------------------------------------------------------------------------- // Use time history term in time history expression. -void pylith::sources::SquarePulseSource::useTimeHistory(const bool value) -{ +void +pylith::sources::SquarePulseSource::useTimeHistory(const bool value) { PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); _useTimeHistory = value; } // useTimeHistory + // --------------------------------------------------------------------------------------------------------------------- // Get flag associated with using time history term in time history expression. -bool pylith::sources::SquarePulseSource::useTimeHistory(void) const -{ +bool +pylith::sources::SquarePulseSource::useTimeHistory(void) const { return _useTimeHistory; } // useTimeHistory + // --------------------------------------------------------------------------------------------------------------------- // Verify configuration is acceptable. -void pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const -{ +void +pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) - { + if (!solution.hasSubfield("pressure")) { throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'SquarePulseSource'."); } // if PYLITH_METHOD_END; } // verifyConfiguration + // --------------------------------------------------------------------------------------------------------------------- // Create integrator and set kernels. pylith::feassemble::Integrator * -pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) -{ +pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - printf("In SquarePulseSource begin\n"); - DMView(solution.getDM(), NULL); - PetscErrorCode err; - PetscDM dmSoln = solution.getDM(); - assert(dmSoln); - // transform points of source to mesh coordinates in python - // DM from solution - Vec vecPoints; - DMLabel label; - PetscSF sfPoints = NULL; - const PetscInt *localPoints; - const PetscSFNode *remotePoints; - PetscInt numRoots = -1, numLeaves, dim, d; - PetscMPIInt rank; - PetscScalar *a; - - err = DMGetCoordinateDim(dmSoln, &dim); - PYLITH_CHECK_ERROR(err); - err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, - &_pointCoords[0], &vecPoints); - PYLITH_CHECK_ERROR(err); - - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); - // Erzatz from ex17 - // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); - // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); - // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - // for (d = 0; d < _pointCoords.size(); ++d) { - // a[d] = _pointCoords[d]; - // } - // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - - err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); - PYLITH_CHECK_ERROR(err); - err = VecDestroy(&vecPoints); - PYLITH_CHECK_ERROR(err); - err = DMCreateLabel(dmSoln, getLabelName()); - PYLITH_CHECK_ERROR(err); - err = DMGetLabel(dmSoln, getLabelName(), &label); - PYLITH_CHECK_ERROR(err); - err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); - PYLITH_CHECK_ERROR(err); - err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); - PYLITH_CHECK_ERROR(err); - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); - for (PetscInt p = 0; p < numLeaves; ++p) - { - if (remotePoints[p].rank == rank) - { - err = DMLabelSetValue(label, remotePoints[p].index, 2); - PYLITH_CHECK_ERROR(err); - } - } // for - err = PetscSFDestroy(&sfPoints); - PYLITH_CHECK_ERROR(err); + // printf("In SquarePulseSource begin\n"); + // DMView(solution.getDM(), NULL); + // PetscErrorCode err; + // PetscDM dmSoln = solution.getDM(); + // assert(dmSoln); + // // transform points of source to mesh coordinates in python + // // DM from solution + // Vec vecPoints; + // DMLabel label; + // PetscSF sfPoints = NULL; + // const PetscInt *localPoints; + // const PetscSFNode *remotePoints; + // PetscInt numRoots = -1, numLeaves, dim, d; + // PetscMPIInt rank; + // PetscScalar *a; + + // err = DMGetCoordinateDim(dmSoln, &dim); + // PYLITH_CHECK_ERROR(err); + // err = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dmSoln), dim, _pointCoords.size(), PETSC_DECIDE, + // &_pointCoords[0], &vecPoints); + // PYLITH_CHECK_ERROR(err); + + // // Debug + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); + // // Erzatz from ex17 + // // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); + // // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); + // // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + // // for (d = 0; d < _pointCoords.size(); ++d) { + // // a[d] = _pointCoords[d]; + // // } + // // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + + // err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); + // PYLITH_CHECK_ERROR(err); + // err = VecDestroy(&vecPoints); + // PYLITH_CHECK_ERROR(err); + // err = DMCreateLabel(dmSoln, getLabelName()); + // PYLITH_CHECK_ERROR(err); + // err = DMGetLabel(dmSoln, getLabelName(), &label); + // PYLITH_CHECK_ERROR(err); + // err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); + // PYLITH_CHECK_ERROR(err); + // err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); + // PYLITH_CHECK_ERROR(err); + // // Debug + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); + // for (PetscInt p = 0; p < numLeaves; ++p) + // { + // if (remotePoints[p].rank == rank) + // { + // err = DMLabelSetValue(label, remotePoints[p].index, 2); + // PYLITH_CHECK_ERROR(err); + // } + // } // for + // err = PetscSFDestroy(&sfPoints); + // PYLITH_CHECK_ERROR(err); + + pylith::sources::Source::locateSource(solution); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); integrator->setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); - printf("In SquarePulseSource end\n"); - DMView(dmSoln, NULL); + // printf("In SquarePulseSource end\n"); + // DMView(dmSoln, NULL); _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); @@ -197,12 +202,12 @@ pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Fie PYLITH_METHOD_RETURN(integrator); } // createIntegrator + // --------------------------------------------------------------------------------------------------------------------- // Create auxiliary field. pylith::topology::Field * pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) -{ + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); @@ -233,31 +238,32 @@ pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology: PYLITH_METHOD_RETURN(auxiliaryField); } // createAuxiliaryField + // --------------------------------------------------------------------------------------------------------------------- // Create derived field. pylith::topology::Field * pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) -{ + const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); PYLITH_METHOD_RETURN(NULL); } // createDerivedField + // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. pylith::feassemble::AuxiliaryFactory * -pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) -{ +pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { return _auxiliaryFactory; } // _getAuxiliaryFactory + // --------------------------------------------------------------------------------------------------------------------- // Set kernels for LHS residual F(t,s,\dot{s}). -void pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const -{ +void +pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); @@ -265,8 +271,7 @@ void pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble: std::vector kernels; - switch (_formulation) - { + switch (_formulation) { case QUASISTATIC: { // Pressure @@ -295,11 +300,12 @@ void pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble: PYLITH_METHOD_END; } // _setKernelsResidual + // --------------------------------------------------------------------------------------------------------------------- // Set kernels for LHS Jacobian F(t,s,\dot{s}). -void pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const -{ +void +pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); @@ -307,8 +313,7 @@ void pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble: std::vector kernels; - switch (_formulation) - { + switch (_formulation) { case QUASISTATIC: { const PetscPointJac Jf0pp = NULL; @@ -336,4 +341,5 @@ void pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble: PYLITH_METHOD_END; } // _setKernelsJacobian + // End of file diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc index be654be7d6..874fb5089a 100644 --- a/libsrc/pylith/sources/WellboreSource.cc +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -127,69 +127,71 @@ pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - printf("In WellboreSource begin\n"); - DMView(solution.getDM(), NULL); - PetscErrorCode err; - PetscDM dmSoln = solution.getDM(); - assert(dmSoln); - // transform points of source to mesh coordinates in python - // DM from solution - Vec vecPoints; - DMLabel label; - PetscSF sfPoints = NULL; - const PetscInt *localPoints; - const PetscSFNode *remotePoints; - PetscInt numRoots = -1, numLeaves, dim, d; - PetscMPIInt rank; - PetscScalar *a; - - err = DMGetCoordinateDim(dmSoln, &dim);PYLITH_CHECK_ERROR(err); - - err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), - &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); - - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); - // Erzatz from ex17 - // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); - // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); - // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - // for (d = 0; d < _pointCoords.size(); ++d) { - // a[d] = _pointCoords[d]; - // } - // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - - err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); - PYLITH_CHECK_ERROR(err); - err = VecDestroy(&vecPoints); - PYLITH_CHECK_ERROR(err); - err = DMCreateLabel(dmSoln, getLabelName()); - PYLITH_CHECK_ERROR(err); - err = DMGetLabel(dmSoln, getLabelName(), &label); - PYLITH_CHECK_ERROR(err); - err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); - PYLITH_CHECK_ERROR(err); - err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); - PYLITH_CHECK_ERROR(err); - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); - for (PetscInt p = 0; p < numLeaves; ++p) { - if (remotePoints[p].rank == rank) { - err = DMLabelSetValue(label, remotePoints[p].index, 2); - PYLITH_CHECK_ERROR(err); - } - } // for - err = PetscSFDestroy(&sfPoints); - PYLITH_CHECK_ERROR(err); + // printf("In WellboreSource begin\n"); + // DMView(solution.getDM(), NULL); + // PetscErrorCode err; + // PetscDM dmSoln = solution.getDM(); + // assert(dmSoln); + // // transform points of source to mesh coordinates in python + // // DM from solution + // Vec vecPoints; + // DMLabel label; + // PetscSF sfPoints = NULL; + // const PetscInt *localPoints; + // const PetscSFNode *remotePoints; + // PetscInt numRoots = -1, numLeaves, dim, d; + // PetscMPIInt rank; + // PetscScalar *a; + + // err = DMGetCoordinateDim(dmSoln, &dim);PYLITH_CHECK_ERROR(err); + + // err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), + // &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); + + // // Debug + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); + // // Erzatz from ex17 + // // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); + // // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); + // // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + // // for (d = 0; d < _pointCoords.size(); ++d) { + // // a[d] = _pointCoords[d]; + // // } + // // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); + + // err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); + // PYLITH_CHECK_ERROR(err); + // err = VecDestroy(&vecPoints); + // PYLITH_CHECK_ERROR(err); + // err = DMCreateLabel(dmSoln, getLabelName()); + // PYLITH_CHECK_ERROR(err); + // err = DMGetLabel(dmSoln, getLabelName(), &label); + // PYLITH_CHECK_ERROR(err); + // err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); + // PYLITH_CHECK_ERROR(err); + // err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); + // PYLITH_CHECK_ERROR(err); + // // Debug + // // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); + // for (PetscInt p = 0; p < numLeaves; ++p) { + // if (remotePoints[p].rank == rank) { + // err = DMLabelSetValue(label, remotePoints[p].index, 2); + // PYLITH_CHECK_ERROR(err); + // } + // } // for + // err = PetscSFDestroy(&sfPoints); + // PYLITH_CHECK_ERROR(err); + + pylith::sources::Source::locateSource(solution); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); integrator->setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); - printf("In WellboreSource end\n"); - DMView(dmSoln, NULL); + // printf("In WellboreSource end\n"); + // DMView(dmSoln, NULL); _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); From 5ab9a4c6e74c73b51a856b8f84a92552b5d2618f Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 14 Jun 2023 23:17:51 -0600 Subject: [PATCH 11/65] First work on user selectable subfields for moment tensor sources --- libsrc/pylith/sources/Source.cc | 24 ++++++++++++++++++++++++ libsrc/pylith/sources/Source.hh | 13 +++++++++++++ modulesrc/sources/Source.i | 24 ++++++------------------ pylith/sources/Source.py | 4 ++++ 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 04747909d0..1f1b852ae0 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -73,6 +73,30 @@ pylith::sources::Source::getDescription(void) const { } // getDescription +// ------------------------------------------------------------------------------------------------ +// Set name of solution subfield associated with boundary condition. +void +pylith::sources::Source::setSubfieldName(const char* value) { + PYLITH_COMPONENT_DEBUG("setSubfieldName(value="< diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 8e637a38db..017b97f538 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -73,6 +73,19 @@ public: * @param[in] solution Solution field. * @returns Constraint if applicable, otherwise NULL. */ + + /** Set name of solution subfield associated with boundary condition. + * + * @param[in] value Name of solution subfield. + */ + void setSubfieldName(const char* value); + + /** Get name of solution subfield associated with boundary condition. + * + * @preturn Name of solution subfield. + */ + const char* getSubfieldName(void) const; + virtual std::vector createConstraints(const pylith::topology::Field& solution); diff --git a/modulesrc/sources/Source.i b/modulesrc/sources/Source.i index 61cc48d75d..de8639d413 100644 --- a/modulesrc/sources/Source.i +++ b/modulesrc/sources/Source.i @@ -52,29 +52,17 @@ public: */ const char* getDescription(void) const; - /** Set name of label marking source. + /** Set name of solution subfield associated with source. * - * @param[in] value Name of label for source (from mesh generator). + * @param[in] value Name of solution subfield. */ - void setLabelName(const char* value); + void setSubfieldName(const char* value); - /** Get name of label marking boundary associated with boundary condition surface. + /** Get name of solution subfield associated with source. * - * @returns Name of label for source (from mesh generator). + * @preturn Name of solution subfield. */ - const char* getLabelName(void) const; - - /** Set value of label marking source. - * - * @param[in] value Value of label for source (from mesh generator). - */ - void setLabelValue(const int value); - - /** Get value of label marking source. - * - * @returns Value of label for source (from mesh generator). - */ - int getLabelValue(void) const; + const char* getSubfieldName(void) const; /** Create constraint and set kernels. * diff --git a/pylith/sources/Source.py b/pylith/sources/Source.py index 0da20cec68..8f475471e0 100644 --- a/pylith/sources/Source.py +++ b/pylith/sources/Source.py @@ -40,6 +40,9 @@ class Source(Physics, ModuleSource): import pythia.pyre.inventory + field = pythia.pyre.inventory.str("field", default="displacement") + field.meta['tip'] = "Solution subfield associated with boundary condition." + description = pythia.pyre.inventory.str("description", default="", validator=validateDescription) description.meta['tip'] = "Descriptive label for material." @@ -63,6 +66,7 @@ def preinitialize(self, problem): """Setup source. """ Physics.preinitialize(self, problem) + ModuleSource.setSubfieldName(self, self.field) ModuleSource.setDescription(self, self.description) ModuleSource.setLabelName(self, self.labelName) ModuleSource.setLabelValue(self, self.labelValue) From 323823e7e60d43634197f465fa30e441689c607a Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 10:27:35 -0600 Subject: [PATCH 12/65] Fixed variable issue --- libsrc/pylith/sources/Source.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 017b97f538..07372d8464 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -115,6 +115,7 @@ protected: std::string _description; ///< Descriptive label for source. std::string _labelName; ///< Name of label to identify source points in mesh. int _labelValue; ///< Value of label to identify source points in mesh. + std::string _subfieldName; ///< Name of solution subfield for boundary condition. // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: From 25967037654b4a3768b8f0d92e80405b4db48737 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 11:48:04 -0600 Subject: [PATCH 13/65] Parallel works now --- libsrc/pylith/feassemble/DSLabelAccess.icc | 7 ++++++- libsrc/pylith/sources/MomentTensorForce.cc | 1 + libsrc/pylith/sources/Source.cc | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libsrc/pylith/feassemble/DSLabelAccess.icc b/libsrc/pylith/feassemble/DSLabelAccess.icc index d7dd9d24d5..f41537981e 100644 --- a/libsrc/pylith/feassemble/DSLabelAccess.icc +++ b/libsrc/pylith/feassemble/DSLabelAccess.icc @@ -79,8 +79,13 @@ pylith::feassemble::DSLabelAccess::DSLabelAccess(const PetscDM dm, _numPoints = numPointsNew; } else { err = ISDestroy(&_pointsIS);PYLITH_CHECK_ERROR(err); + err = ISRestoreIndices(_cellsIS, &cellIndices);PYLITH_CHECK_ERROR(err); + // } else { + // err = ISDestroy(&_cellsIS);PYLITH_CHECK_ERROR(err); } // if/else - } // if + } else { + err = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_OWN_POINTER,&_cellsIS); + } PYLITH_METHOD_END; } diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 8652540068..4ebfbf10f8 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -165,6 +165,7 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); + _setKernelsUpdateStateVars(integrator, solution); _setKernelsDerivedField(integrator, solution); diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 1f1b852ae0..8d11b5c13d 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -189,6 +189,7 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution) { err = DMLabelSetValue(label, remotePoints[p].index, 2);PYLITH_CHECK_ERROR(err); } } // for + DMLabelView(label, NULL); err = PetscSFDestroy(&sfPoints);PYLITH_CHECK_ERROR(err); printf("In MomentTensorForce end\n"); DMView(dmSoln, NULL); From b6d84c5e9dfa1ffc10536a1e3728312ce8fd5f7e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 13:21:11 -0600 Subject: [PATCH 14/65] Removed comments --- libsrc/pylith/feassemble/DSLabelAccess.icc | 8 +-- libsrc/pylith/sources/MomentTensorForce.cc | 48 ----------------- libsrc/pylith/sources/SquarePulseSource.cc | 60 ---------------------- libsrc/pylith/sources/WellboreSource.cc | 57 -------------------- 4 files changed, 4 insertions(+), 169 deletions(-) diff --git a/libsrc/pylith/feassemble/DSLabelAccess.icc b/libsrc/pylith/feassemble/DSLabelAccess.icc index f41537981e..903f32aee3 100644 --- a/libsrc/pylith/feassemble/DSLabelAccess.icc +++ b/libsrc/pylith/feassemble/DSLabelAccess.icc @@ -80,11 +80,11 @@ pylith::feassemble::DSLabelAccess::DSLabelAccess(const PetscDM dm, } else { err = ISDestroy(&_pointsIS);PYLITH_CHECK_ERROR(err); err = ISRestoreIndices(_cellsIS, &cellIndices);PYLITH_CHECK_ERROR(err); - // } else { - // err = ISDestroy(&_cellsIS);PYLITH_CHECK_ERROR(err); + } else { + err = ISDestroy(&_cellsIS);PYLITH_CHECK_ERROR(err); } // if/else - } else { - err = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_OWN_POINTER,&_cellsIS); + // } else { + // err = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_OWN_POINTER,&_cellsIS); } PYLITH_METHOD_END; diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 4ebfbf10f8..f9651f0dd9 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -109,54 +109,6 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution="< Date: Thu, 15 Jun 2023 14:52:15 -0600 Subject: [PATCH 15/65] Field is now selectable for MT --- libsrc/pylith/sources/MomentTensorForce.cc | 115 +++++++++++---------- libsrc/pylith/sources/MomentTensorForce.hh | 14 +-- libsrc/pylith/sources/Source.cc | 1 + 3 files changed, 67 insertions(+), 63 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index f9651f0dd9..8fe68eb540 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -116,7 +116,7 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie integrator->setLabelValue(getLabelValue()); _setKernelsResidual(integrator, solution); - _setKernelsJacobian(integrator, solution); + // _setKernelsJacobian(integrator, *this, solution); _setKernelsUpdateStateVars(integrator, solution); _setKernelsDerivedField(integrator, solution); @@ -223,8 +223,8 @@ pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::Inte // Velocity const PetscPointFunc g0v = NULL; const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); - - kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::RHS, g0v, g1v); + // kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); break; } // DYNAMIC default: @@ -238,60 +238,63 @@ pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::Inte } // _setKernelsResidual +// // // --------------------------------------------------------------------------------------------------------------------- -// Set kernels for RHS Jacobian G(t,s). -void -pylith::sources::MomentTensorForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; - - switch (_formulation) { - case QUASISTATIC: { - break; - } // QUASISTATIC - case DYNAMIC_IMEX: - case DYNAMIC: { - typedef pylith::feassemble::JacobianValues::JacobianKernel ValueKernel; - std::vector valueKernelsJacobian(2); - std::vector valueKernelsPrecond; - valueKernelsJacobian[0] = ValueKernel("displacement", "displacement", pylith::feassemble::JacobianValues::blockDiag_tshift); - valueKernelsJacobian[1] = ValueKernel("velocity", "velocity", pylith::feassemble::JacobianValues::blockDiag_tshift); - integrator->setKernelsJacobian(valueKernelsJacobian, valueKernelsPrecond); - - const PetscPointJac Jf0uu = pylith::fekernels::DispVel::Jg0uv; - const PetscPointJac Jf1uu = NULL; - const PetscPointJac Jf2uu = NULL; - const PetscPointJac Jf3uu = NULL; - - const PetscPointJac Jf0vv = pylith::fekernels::DispVel::Jg0uv; - const PetscPointJac Jf1vv = NULL; - const PetscPointJac Jf2vv = NULL; - const PetscPointJac Jf3vv = NULL; - - integrator->setLHSJacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_TIME_STEP_CHANGE); - - kernels.resize(2); - const EquationPart equationPart = pylith::feassemble::Integrator::LHS_LUMPED_INV; - kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); - kernels[1] = JacobianKernels("velocity", "velocity", equationPart, Jf0vv, Jf1vv, Jf2vv, Jf3vv); - break; - } // DYNAMIC - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - integrator->setKernelsJacobian(kernels, solution); - - PYLITH_METHOD_END; - -} // _setKernelsJacobian - +// // Set kernels for RHS Jacobian G(t,s). +// void +// pylith::sources::MomentTensorForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, +// const pylith::sources::MomentTensorForce& source, +// const topology::Field& solution) const { +// PYLITH_METHOD_BEGIN; +// PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; + +// switch (_formulation) { +// case QUASISTATIC: { +// break; +// } // QUASISTATIC +// case DYNAMIC_IMEX: +// case DYNAMIC: { +// typedef pylith::feassemble::JacobianValues::JacobianKernel ValueKernel; +// std::vector valueKernelsJacobian(2); +// std::vector valueKernelsPrecond; +// valueKernelsJacobian[0] = ValueKernel("displacement", "displacement", +// pylith::feassemble::JacobianValues::blockDiag_tshift); +// valueKernelsJacobian[1] = ValueKernel("velocity", "velocity", +// pylith::feassemble::JacobianValues::blockDiag_tshift); +// integrator->setKernelsJacobian(valueKernelsJacobian, valueKernelsPrecond); + +// const PetscPointJac Jf0uu = pylith::fekernels::DispVel::Jg0uv; +// const PetscPointJac Jf1uu = NULL; +// const PetscPointJac Jf2uu = NULL; +// const PetscPointJac Jf3uu = NULL; + +// const PetscPointJac Jf0vv = pylith::fekernels::DispVel::Jg0uv; +// const PetscPointJac Jf1vv = NULL; +// const PetscPointJac Jf2vv = NULL; +// const PetscPointJac Jf3vv = NULL; + +// integrator->setLHSJacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_TIME_STEP_CHANGE); + +// kernels.resize(2); +// const EquationPart equationPart = pylith::feassemble::Integrator::LHS_LUMPED_INV; +// kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); +// kernels[1] = JacobianKernels("velocity", "velocity", equationPart, Jf0vv, Jf1vv, Jf2vv, Jf3vv); +// break; +// } // DYNAMIC +// default: +// PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); +// } // switch + +// integrator->setKernelsJacobian(kernels, solution); + +// PYLITH_METHOD_END; + +// } // _setKernelsJacobian // --------------------------------------------------------------------------------------------------------------------- // Set kernels for computing updated state variables in auxiliary field. diff --git a/libsrc/pylith/sources/MomentTensorForce.hh b/libsrc/pylith/sources/MomentTensorForce.hh index 8bc8ed40be..0f83b6fe1d 100644 --- a/libsrc/pylith/sources/MomentTensorForce.hh +++ b/libsrc/pylith/sources/MomentTensorForce.hh @@ -121,13 +121,13 @@ private: void _setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, const pylith::topology::Field& solution) const; - /** Set kernels for Jacobian. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, - const pylith::topology::Field& solution) const; + // /** Set kernels for Jacobian. + // * + // * @param[out] integrator Integrator for source. + // * @param[in] solution Solution field. + // */ + // void _setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, + // const pylith::topology::Field& solution) const; /** Set kernels for computing updated state variables in auxiliary field. * diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 8d11b5c13d..324b36892a 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -29,6 +29,7 @@ // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::Source::Source(void) : + _subfieldName(""), _description(""), _labelName(""), _labelValue(1) { From 1d5c8fb527e036f72f37375f646df3de5f7a47d2 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 14:56:07 -0600 Subject: [PATCH 16/65] Changed square pulse to user selected subfield --- libsrc/pylith/sources/SquarePulseSource.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc index c38593e6cf..36ff5e5f62 100644 --- a/libsrc/pylith/sources/SquarePulseSource.cc +++ b/libsrc/pylith/sources/SquarePulseSource.cc @@ -219,7 +219,7 @@ pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::Inte const PetscPointFunc f1p = NULL; kernels.resize(1); - kernels[0] = ResidualKernels("pressure", pylith::feassemble::Integrator::LHS, f0p, f1p); + kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::LHS, f0p, f1p); break; } // QUASISTATIC case DYNAMIC_IMEX: @@ -263,7 +263,7 @@ pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::Inte kernels.resize(1); const EquationPart equationPart = pylith::feassemble::Integrator::LHS; - kernels[0] = JacobianKernels("pressure", "pressure", equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); + kernels[0] = JacobianKernels(getSubfieldName(), getSubfieldName(), equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); break; } // QUASISTATIC case DYNAMIC: From 61da8ed3dce4b749a49f11e7ee1736677e52a020 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 15:12:57 -0600 Subject: [PATCH 17/65] Updated to new location function --- libsrc/pylith/sources/PointForce.cc | 61 +---------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc index 67fa514825..790370604b 100644 --- a/libsrc/pylith/sources/PointForce.cc +++ b/libsrc/pylith/sources/PointForce.cc @@ -127,71 +127,12 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field &sol PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - printf("In PointForce begin\n"); - DMView(solution.getDM(), NULL); - PetscErrorCode err; - PetscDM dmSoln = solution.getDM(); - assert(dmSoln); - // transform points of source to mesh coordinates in python - // DM from solution - Vec vecPoints; - DMLabel label; - PetscSF sfPoints = NULL; - const PetscInt *localPoints; - const PetscSFNode *remotePoints; - PetscInt numRoots = -1, numLeaves, dim, d; - PetscMPIInt rank; - PetscScalar *a; - - err = DMGetCoordinateDim(dmSoln, &dim); - PYLITH_CHECK_ERROR(err); - err = VecCreateSeqWithArray(PETSC_COMM_SELF, dim, _pointCoords.size(), - &_pointCoords[0], &vecPoints);PYLITH_CHECK_ERROR(err); - - PYLITH_CHECK_ERROR(err); - - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "_pointCoords\n"); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " x = %g\n", _pointCoords[0]); - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), " y = %g\n", _pointCoords[1]); - // Erzatz from ex17 - // err = VecCreateSeq(PETSC_COMM_SELF, dim, &vecPoints);PYLITH_CHECK_ERROR(err); - // err = VecSetBlockSize(vecPoints, _pointCoords.size());PYLITH_CHECK_ERROR(err); - // err = VecGetArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - // for (d = 0; d < _pointCoords.size(); ++d) { - // a[d] = _pointCoords[d]; - // } - // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); - - err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints); - PYLITH_CHECK_ERROR(err); - err = VecDestroy(&vecPoints); - PYLITH_CHECK_ERROR(err); - err = DMCreateLabel(dmSoln, getLabelName()); - PYLITH_CHECK_ERROR(err); - err = DMGetLabel(dmSoln, getLabelName(), &label); - PYLITH_CHECK_ERROR(err); - err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints); - PYLITH_CHECK_ERROR(err); - err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); - PYLITH_CHECK_ERROR(err); - // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); - for (PetscInt p = 0; p < numLeaves; ++p) { - if (remotePoints[p].rank == rank) { - err = DMLabelSetValue(label, remotePoints[p].index, 2); - PYLITH_CHECK_ERROR(err); - } - } // for - err = PetscSFDestroy(&sfPoints); - PYLITH_CHECK_ERROR(err); + pylith::sources::Source::locateSource(solution); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); integrator->setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); - printf("In PointForce end\n"); - DMView(dmSoln, NULL); _setKernelsResidual(integrator, solution); _setKernelsJacobian(integrator, solution); From d37a8e5cba6ea6bddb043cecc65ebb1c1a386e3d Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 15 Jun 2023 16:34:23 -0600 Subject: [PATCH 18/65] Array source input works for parallel --- configure.ac | 2 + libsrc/pylith/Makefile.am | 1 - .../AuxiliaryFactoryMomentTensorForce.cc | 4 +- .../sources/AuxiliaryFactorySourceTime.cc | 8 +- libsrc/pylith/sources/Makefile.am | 1 - libsrc/pylith/sources/MomentTensorForce.cc | 61 +- libsrc/pylith/sources/PointForce.cc | 2 +- libsrc/pylith/sources/Source.cc | 30 +- libsrc/pylith/sources/Source.hh | 4 +- .../SourceTimeFunctionMomentTensorForce.hh | 5 +- .../sources/SourceTimeFunctionPointForce.cc | 87 -- .../sources/SourceTimeFunctionPointForce.hh | 111 --- libsrc/pylith/sources/SquarePulseSource.cc | 2 +- libsrc/pylith/sources/WellboreSource.cc | 2 +- libsrc/pylith/sources/sourcesfwd.hh | 1 - pylith/problems/Problem.py | 7 +- pylith/sources/PointForce.py | 1 - pylith/sources/Source.py | 3 +- tests/libtests/Makefile.am | 3 +- tests/libtests/materials/TestMaterial.cc | 762 +++++++++++++++++ tests/libtests/sources/Makefile.am | 42 + .../TestAuxiliaryFactoryMomentTensorForce.cc | 221 +++++ .../TestAuxiliaryFactoryMomentTensorForce.hh | 110 +++ ...AuxiliaryFactoryMomentTensorForce_Cases.cc | 205 +++++ .../sources/TestAuxiliaryFactorySourceTime.cc | 243 ++++++ .../sources/TestAuxiliaryFactorySourceTime.hh | 110 +++ .../TestAuxiliaryFactorySourceTime_Cases.cc | 225 +++++ tests/libtests/sources/TestSource.cc | 781 ++++++++++++++++++ tests/libtests/sources/TestSource.hh | 211 +++++ tests/libtests/sources/data/Makefile.am | 29 + tests/libtests/sources/data/hex_onecell.mesh | 37 + tests/libtests/sources/data/tri_onecell.mesh | 32 + tests/pytests/sources/TestPointForce.py | 41 + tests/pytests/sources/TestSource.py | 40 + tests/pytests/sources/TestWellboreSource.py | 41 + tests/pytests/sources/__init__.py | 2 + 36 files changed, 3178 insertions(+), 289 deletions(-) delete mode 100644 libsrc/pylith/sources/SourceTimeFunctionPointForce.cc delete mode 100644 libsrc/pylith/sources/SourceTimeFunctionPointForce.hh create mode 100644 tests/libtests/sources/Makefile.am create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh create mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc create mode 100644 tests/libtests/sources/TestSource.cc create mode 100644 tests/libtests/sources/TestSource.hh create mode 100644 tests/libtests/sources/data/Makefile.am create mode 100644 tests/libtests/sources/data/hex_onecell.mesh create mode 100644 tests/libtests/sources/data/tri_onecell.mesh create mode 100644 tests/pytests/sources/TestPointForce.py create mode 100644 tests/pytests/sources/TestSource.py create mode 100644 tests/pytests/sources/TestWellboreSource.py create mode 100644 tests/pytests/sources/__init__.py diff --git a/configure.ac b/configure.ac index 247b20e3b9..62063e398a 100644 --- a/configure.ac +++ b/configure.ac @@ -236,6 +236,8 @@ AC_CONFIG_FILES([Makefile tests/libtests/meshio/Makefile tests/libtests/problems/Makefile tests/libtests/problems/data/Makefile + tests/libtests/sources/Makefile + tests/libtests/sources/data/Makefile tests/libtests/meshio/data/Makefile tests/libtests/scales/Makefile tests/libtests/topology/Makefile diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index f546abac4f..1331ee1b6f 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -148,7 +148,6 @@ libpylith_la_SOURCES = \ sources/RickerWavelet.cc \ sources/Source.cc \ sources/SourceTimeFunctionMomentTensorForce.cc \ - sources/SourceTimeFunctionPointForce.cc \ sources/SquarePulseSource.cc \ sources/WellboreSource.cc \ topology/Mesh.cc \ diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc index b88000cf96..188d896253 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -47,7 +47,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::~AuxiliaryFactoryMomentTenso void pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // momentTensor PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTensorPermeability(void)"); + PYLITH_JOURNAL_DEBUG("addMomentTensor(void)"); const char* subfieldName = "moment_tensor"; const char* componentNames[6] = { @@ -83,7 +83,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // m // --------------------------------------------------------------------------------------------------------------------- // Add time delay of source time function to auxiliary fields. void -pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { +pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { // timeDelay PYLITH_METHOD_BEGIN; PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index 8a309acab6..9bd2ce3fd5 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -36,6 +36,7 @@ pylith::sources::AuxiliaryFactorySourceTime::AuxiliaryFactorySourceTime(void) { GenericComponent::setName("auxiliaryfactorysourcetime"); } // constructor + // --------------------------------------------------------------------------------------------------------------------- // Destructor. pylith::sources::AuxiliaryFactorySourceTime::~AuxiliaryFactorySourceTime(void) {} @@ -44,7 +45,7 @@ pylith::sources::AuxiliaryFactorySourceTime::~AuxiliaryFactorySourceTime(void) { // --------------------------------------------------------------------------------------------------------------------- // Add center frequency of source time function to auxiliary fields. void -pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { +pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { // centerFrequency PYLITH_METHOD_BEGIN; PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); @@ -62,8 +63,9 @@ pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); - + PYLITH_METHOD_END; -} // addRickerCenterFrequency +} // addCenterFrequency + // End of file diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index f51f3b46ce..9af94918f1 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -35,7 +35,6 @@ subpkginclude_HEADERS = \ PointForce.hh \ AuxiliaryFactoryPointForce.hh \ SourceTimeFunctionMomentTensorForce.hh \ - SourceTimeFunctionPointForce.hh \ sourcesfwd.hh diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 8fe68eb540..4a32c8d822 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -109,14 +109,13 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution="<setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); _setKernelsResidual(integrator, solution); - // _setKernelsJacobian(integrator, *this, solution); _setKernelsUpdateStateVars(integrator, solution); _setKernelsDerivedField(integrator, solution); @@ -238,64 +237,6 @@ pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::Inte } // _setKernelsResidual -// // -// --------------------------------------------------------------------------------------------------------------------- -// // Set kernels for RHS Jacobian G(t,s). -// void -// pylith::sources::MomentTensorForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain* integrator, -// const pylith::sources::MomentTensorForce& source, -// const topology::Field& solution) const { -// PYLITH_METHOD_BEGIN; -// PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator="< kernels; - -// switch (_formulation) { -// case QUASISTATIC: { -// break; -// } // QUASISTATIC -// case DYNAMIC_IMEX: -// case DYNAMIC: { -// typedef pylith::feassemble::JacobianValues::JacobianKernel ValueKernel; -// std::vector valueKernelsJacobian(2); -// std::vector valueKernelsPrecond; -// valueKernelsJacobian[0] = ValueKernel("displacement", "displacement", -// pylith::feassemble::JacobianValues::blockDiag_tshift); -// valueKernelsJacobian[1] = ValueKernel("velocity", "velocity", -// pylith::feassemble::JacobianValues::blockDiag_tshift); -// integrator->setKernelsJacobian(valueKernelsJacobian, valueKernelsPrecond); - -// const PetscPointJac Jf0uu = pylith::fekernels::DispVel::Jg0uv; -// const PetscPointJac Jf1uu = NULL; -// const PetscPointJac Jf2uu = NULL; -// const PetscPointJac Jf3uu = NULL; - -// const PetscPointJac Jf0vv = pylith::fekernels::DispVel::Jg0uv; -// const PetscPointJac Jf1vv = NULL; -// const PetscPointJac Jf2vv = NULL; -// const PetscPointJac Jf3vv = NULL; - -// integrator->setLHSJacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_TIME_STEP_CHANGE); - -// kernels.resize(2); -// const EquationPart equationPart = pylith::feassemble::Integrator::LHS_LUMPED_INV; -// kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); -// kernels[1] = JacobianKernels("velocity", "velocity", equationPart, Jf0vv, Jf1vv, Jf2vv, Jf3vv); -// break; -// } // DYNAMIC -// default: -// PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); -// } // switch - -// integrator->setKernelsJacobian(kernels, solution); - -// PYLITH_METHOD_END; - -// } // _setKernelsJacobian - // --------------------------------------------------------------------------------------------------------------------- // Set kernels for computing updated state variables in auxiliary field. void diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc index 790370604b..a445c7df8e 100644 --- a/libsrc/pylith/sources/PointForce.cc +++ b/libsrc/pylith/sources/PointForce.cc @@ -127,7 +127,7 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field &sol PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - pylith::sources::Source::locateSource(solution); + pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 324b36892a..db946143b8 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -143,9 +143,11 @@ pylith::sources::Source::setPoints(const PylithReal* pointCoords, // ------------------------------------------------------------------------------------------------ // Convert cartesian positions to a labeled source void -pylith::sources::Source::locateSource(const pylith::topology::Field& solution) { - printf("In MomentTensorForce begin\n"); - DMView(solution.getDM(), NULL); +pylith::sources::Source::locateSource(const pylith::topology::Field& solution, + const char labelName[], + const int labelValue) { + // printf("In MomentTensorForce begin\n"); + // DMView(solution.getDM(), NULL); PetscErrorCode err; PetscDM dmSoln = solution.getDM();assert(dmSoln); // transform points of source to mesh coordinates in python @@ -177,23 +179,27 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution) { // err = VecRestoreArray(vecPoints, &a);PYLITH_CHECK_ERROR(err); err = DMLocatePoints(dmSoln, vecPoints, DM_POINTLOCATION_NONE, &sfPoints);PYLITH_CHECK_ERROR(err); - err = PetscSFView(sfPoints, NULL);PYLITH_CHECK_ERROR(err); + // err = PetscSFView(sfPoints, NULL);PYLITH_CHECK_ERROR(err); err = VecDestroy(&vecPoints);PYLITH_CHECK_ERROR(err); - err = DMCreateLabel(dmSoln,getLabelName());PYLITH_CHECK_ERROR(err); - err = DMGetLabel(dmSoln,getLabelName(), &label);PYLITH_CHECK_ERROR(err); + err = DMCreateLabel(dmSoln,labelName);PYLITH_CHECK_ERROR(err); + err = DMGetLabel(dmSoln,labelName, &label);PYLITH_CHECK_ERROR(err); err = PetscSFGetGraph(sfPoints, &numRoots, &numLeaves, &localPoints, &remotePoints);PYLITH_CHECK_ERROR(err); err = MPI_Comm_rank(PetscObjectComm((PetscObject) dmSoln), &rank);PYLITH_CHECK_ERROR(err); // Debug - // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n", numLeaves); - for (PetscInt p = 0; p < numLeaves; ++p) { - if (remotePoints[p].rank == rank) { - err = DMLabelSetValue(label, remotePoints[p].index, 2);PYLITH_CHECK_ERROR(err); + // PetscPrintf(PetscObjectComm((PetscObject) dmSoln), "localPoints: %D\n",Thread 1 "mpinemesis" hit Breakpoint 1, + // pylith::sources::Source numLeaves); + // PetscMPIInt rank; + err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); + for (PetscInt p = 0; p < _pointCoords.size() / dim; ++p) { + PetscPrintf(PETSC_COMM_SELF, "[%i] OUTPUT rank: %i, index: %i, label: %s, labelValue: %i \n", (int)rank, (PetscInt)remotePoints[p].rank, (PetscInt)remotePoints[p].index, labelName, (int) labelValue); + if ((remotePoints[p].index >= 0)) { + err = DMLabelSetValue(label, remotePoints[p].index, labelValue);PYLITH_CHECK_ERROR(err); } } // for DMLabelView(label, NULL); err = PetscSFDestroy(&sfPoints);PYLITH_CHECK_ERROR(err); - printf("In MomentTensorForce end\n"); - DMView(dmSoln, NULL); + // printf("In MomentTensorForce end\n"); + // // DMView(dmSoln, NULL); } diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 07372d8464..7bae44c5a9 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -105,7 +105,9 @@ public: /** Assign source label from coordinates. */ - void locateSource(const pylith::topology::Field& solution); + void locateSource(const pylith::topology::Field& solution, + const char labelName[], + const int labelValue); // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// protected: diff --git a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.hh b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.hh index b1b6a2951c..0e23b8c4cb 100644 --- a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.hh +++ b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.hh @@ -36,7 +36,7 @@ #include "petscds.h" // USES PetscPointFunc, PetscPointJac class pylith::sources::SourceTimeFunctionMomentTensorForce : public pylith::utils::PyreComponent { - friend class TestRickerFunction; // unit testing + friend class TestSourceTimeFunctionMomentTensorForce; // unit testing // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// public: @@ -103,7 +103,8 @@ private: SourceTimeFunctionMomentTensorForce(const SourceTimeFunctionMomentTensorForce&); ///< Not implemented. const SourceTimeFunctionMomentTensorForce& operator=(const SourceTimeFunctionMomentTensorForce&); /// Not - /// implemented. + + /// implemented. }; // class SourceTimeFunctionMomentTensorForce diff --git a/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc b/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc deleted file mode 100644 index 3a23fa7b63..0000000000 --- a/libsrc/pylith/sources/SourceTimeFunctionPointForce.cc +++ /dev/null @@ -1,87 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2021 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "pylith/sources/SourceTimeFunctionPointForce.hh" // implementation of object methods - -#include "pylith/feassemble/Integrator.hh" // USES NEW_JACOBIAN_NEVER - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_DEBUG - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::SourceTimeFunctionPointForce::SourceTimeFunctionPointForce(void) : - _JacobianTriggers(pylith::feassemble::Integrator::NEW_JACOBIAN_NEVER) {} - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::SourceTimeFunctionPointForce::~SourceTimeFunctionPointForce(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::SourceTimeFunctionPointForce::deallocate(void) {} - - -// --------------------------------------------------------------------------------------------------------------------- -// Get triggers for needing to compute the elastic constants for the RHS Jacobian. -int -pylith::sources::SourceTimeFunctionPointForce::getJacobianTriggers(void) const { - return _JacobianTriggers; -} // getJacobianTriggers - - -// --------------------------------------------------------------------------------------------------------------------- -// Update kernel constants. -void -pylith::sources::SourceTimeFunctionPointForce::updateKernelConstants(pylith::real_array* kernelConstants, - const PylithReal dt) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("updateKernelConstants(kernelConstants"<* kernels, - const spatialdata::geocoords::CoordSys* coordsys) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("addKernelsUpdateStateVars(kernels="<* kernels, - const spatialdata::geocoords::CoordSys* coordsys) const; - - /** Update kernel constants. - * - * @param[inout] kernelConstants Array of constants used in integration kernels. - * @param[in] dt Current time step. - */ - virtual - void updateKernelConstants(pylith::real_array* kernelConstants, - const PylithReal dt) const; - - // PROTECTED MEMBERS /////////////////////////////////////////////////////////////////////////////////////////////// - - int _JacobianTriggers; ///< Triggers for needing to recompute the RHS Jacobian. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - SourceTimeFunctionPointForce(const SourceTimeFunctionPointForce&); ///< Not implemented. - const SourceTimeFunctionPointForce& operator=(const SourceTimeFunctionPointForce&); /// Not implemented. - -}; // class SourceTimeFunctionPointForce - -#endif // pylith_sources_sourcetimefunctionpointforce_hh - -// End of file diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc index 36ff5e5f62..6461dc64d6 100644 --- a/libsrc/pylith/sources/SquarePulseSource.cc +++ b/libsrc/pylith/sources/SquarePulseSource.cc @@ -127,7 +127,7 @@ pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Fie PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - pylith::sources::Source::locateSource(solution); + pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc index abb2b1627a..3518300383 100644 --- a/libsrc/pylith/sources/WellboreSource.cc +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -127,7 +127,7 @@ pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - pylith::sources::Source::locateSource(solution); + pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); assert(integrator); diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh index f792bec2cc..2a625d28da 100644 --- a/libsrc/pylith/sources/sourcesfwd.hh +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -43,7 +43,6 @@ namespace pylith { class GaussianWavelet; class PointForce; - class SourceTimeFunctionPointForce; class AuxiliaryFactoryPointForce; class SquarePulseSource; diff --git a/pylith/problems/Problem.py b/pylith/problems/Problem.py index dcda28f447..cc875cb813 100644 --- a/pylith/problems/Problem.py +++ b/pylith/problems/Problem.py @@ -42,9 +42,12 @@ def faultFactory(name): def sourceFactory(name): """Factory for source items. """ + # from pythia.pyre.inventory import facility + # from pylith.sources.WellboreSource import WellboreSource + # return facility(name, family="source", factory=WellboreSource) from pythia.pyre.inventory import facility - from pylith.sources.WellboreSource import WellboreSource - return facility(name, family="source", factory=WellboreSource) + from pylith.sources.MomentTensorForce import MomentTensorForce + return facility(name, family="source", factory=MomentTensorForce) def observerFactory(name): """Factory for output items.""" diff --git a/pylith/sources/PointForce.py b/pylith/sources/PointForce.py index dff7509335..53f71d8b26 100644 --- a/pylith/sources/PointForce.py +++ b/pylith/sources/PointForce.py @@ -57,7 +57,6 @@ def _createModuleObj(self): """Create handle to C++ PointForce. """ ModulePointForce.__init__(self) - ModuleMomentTensorForce.setSourceTimeFunction(self, self.source_time_function) # Material sets auxiliary db in source_time_function. return diff --git a/pylith/sources/Source.py b/pylith/sources/Source.py index 8f475471e0..b144c61396 100644 --- a/pylith/sources/Source.py +++ b/pylith/sources/Source.py @@ -46,7 +46,8 @@ class Source(Physics, ModuleSource): description = pythia.pyre.inventory.str("description", default="", validator=validateDescription) description.meta['tip'] = "Descriptive label for material." - labelName = pythia.pyre.inventory.str("label", default="source-id", validator=pythia.pyre.inventory.choice(["source-id"])) + # labelName = pythia.pyre.inventory.str("label", default="source-id", validator=pythia.pyre.inventory.choice(["source-id"])) + labelName = pythia.pyre.inventory.str("label", default="source-id") labelName.meta['tip'] = "Name of label for source. Currently only 'source-id' is allowed." labelValue = pythia.pyre.inventory.int("label_value", default=1) diff --git a/tests/libtests/Makefile.am b/tests/libtests/Makefile.am index 08cc441497..3caad8b52e 100644 --- a/tests/libtests/Makefile.am +++ b/tests/libtests/Makefile.am @@ -16,7 +16,8 @@ SUBDIRS = \ materials \ meshio \ problems \ - scales \ + scales \ + sources \ topology \ testing \ utils diff --git a/tests/libtests/materials/TestMaterial.cc b/tests/libtests/materials/TestMaterial.cc index 087d0595b7..012a701f31 100644 --- a/tests/libtests/materials/TestMaterial.cc +++ b/tests/libtests/materials/TestMaterial.cc @@ -770,4 +770,766 @@ pylith::materials::TestMaterial_Data::~TestMaterial_Data(void) { } // destructor +// End of file + +#include "TestMaterial.hh" // Implementation of class methods + +#include "pylith/materials/Material.hh" // USES Material +#include "pylith/materials/Query.hh" // USES Query + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps::nondimensionalize() +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/Fields.hh" // USES Fields +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/topology/FieldQuery.hh" // USES FieldQuery +#include "pylith/feassemble/AuxiliaryFactory.hh" // USES AuxiliaryFactory +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "pylith/utils/journals.hh" // pythia::journal + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +// ---------------------------------------------------------------------- +// Setup testing data. +void +pylith::materials::TestMaterial::setUp(void) { + _mesh = new pylith::topology::Mesh();CPPUNIT_ASSERT(_mesh); + _solutionFields = NULL; +} // setUp + + +// ---------------------------------------------------------------------- +// Deallocate testing data. +void +pylith::materials::TestMaterial::tearDown(void) { + delete _solutionFields;_solutionFields = NULL; + delete _mesh;_mesh = NULL; +} // tearDown + + +// ---------------------------------------------------------------------- +// Test auxField(). +void +pylith::materials::TestMaterial::testAuxField(void) { + PYLITH_METHOD_BEGIN; + + _initializeFull(); + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + + const pylith::topology::Field* auxField = material->auxField();CPPUNIT_ASSERT(auxField); + for (int i = 0; i < data->numAuxSubfields; ++i) { + CPPUNIT_ASSERT(auxField->hasSubfield(data->auxSubfields[i])); + } // for + + CPPUNIT_ASSERT(!auxField->hasSubfield("abc4598245")); + + PYLITH_METHOD_END; +} // testAuxField + + +// ---------------------------------------------------------------------- +// Test auxSubfieldDiscretization(). +void +pylith::materials::TestMaterial::testAuxSubfieldDiscretization(void) { + PYLITH_METHOD_BEGIN; + + const topology::FieldBase::Discretization infoDefault = pylith::topology::Field::Discretization(1, 1, true, pylith::topology::FieldBase::POLYNOMIAL_SPACE); + const topology::FieldBase::Discretization infoA = pylith::topology::Field::Discretization(1, 2, false, pylith::topology::FieldBase::POLYNOMIAL_SPACE); + const topology::FieldBase::Discretization infoB = pylith::topology::Field::Discretization(2, 2, true, pylith::topology::FieldBase::POINT_SPACE); + + Material* material = _material();CPPUNIT_ASSERT(material); + material->auxSubfieldDiscretization("A", infoA.basisOrder, infoA.quadOrder, infoA.isBasisContinuous, infoA.feSpace); + material->auxSubfieldDiscretization("B", infoB.basisOrder, infoB.quadOrder, infoB.isBasisContinuous, infoB.feSpace); + + CPPUNIT_ASSERT(material->_auxiliaryFactory()); + { // A + const topology::FieldBase::Discretization& test = material->_auxiliaryFactory()->getSubfieldDiscretization("A"); + CPPUNIT_ASSERT_EQUAL(infoA.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoA.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoA.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoA.feSpace, test.feSpace); + } // A + + { // B + const topology::FieldBase::Discretization& test = material->_auxiliaryFactory()->getSubfieldDiscretization("B"); + CPPUNIT_ASSERT_EQUAL(infoB.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoB.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoB.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoB.feSpace, test.feSpace); + } // B + + { // C (default) + const topology::FieldBase::Discretization& test = material->_auxiliaryFactory()->getSubfieldDiscretization("C"); + CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); + } // C (default) + + { // default + const topology::FieldBase::Discretization& test = material->_auxiliaryFactory()->getSubfieldDiscretization("default"); + CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); + } // default + + PYLITH_METHOD_END; +} // testAuxSubfieldDiscretization + + +// ---------------------------------------------------------------------- +// Test auxFieldDB(). +void +pylith::materials::TestMaterial::testAuxFieldDB(void) { + PYLITH_METHOD_BEGIN; + + const std::string label = "test db"; + spatialdata::spatialdb::UserFunctionDB db; + db.setLabel(label.c_str()); + + Material* material = _material();CPPUNIT_ASSERT(material); + material->auxFieldDB(&db); + + CPPUNIT_ASSERT(material->_auxiliaryFactory()); + CPPUNIT_ASSERT(material->_auxiliaryFactory()->queryDB()); + CPPUNIT_ASSERT_EQUAL(label, std::string(material->_auxiliaryFactory()->queryDB()->getLabel())); + + PYLITH_METHOD_END; +} // testAuxFieldDB + + +// ---------------------------------------------------------------------- +// Test normalizer(). +void +pylith::materials::TestMaterial::testNormalizer(void) { + PYLITH_METHOD_BEGIN; + + spatialdata::units::Nondimensional normalizer; + const double scale = 5.0; + normalizer.setLengthScale(scale); + + Material* material = _material();CPPUNIT_ASSERT(material); + material->normalizer(normalizer); + CPPUNIT_ASSERT_EQUAL(scale, material->_normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testNormalizer + + +// ---------------------------------------------------------------------- +// Test verifyConfiguration(). +void +pylith::materials::TestMaterial::testVerifyConfiguration(void) { + PYLITH_METHOD_BEGIN; + + // Call verifyConfiguration() + Material* material = _material();CPPUNIT_ASSERT(material); + CPPUNIT_ASSERT(_solutionFields); + material->verifyConfiguration(_solutionFields->get("solution")); + + // Nothing to test. + + PYLITH_METHOD_END; +} // testVerifyConfiguration + + +// ---------------------------------------------------------------------- +// Test dimension(), id(), and getLabel(). +void +pylith::materials::TestMaterial::testAccessors(void) { + PYLITH_METHOD_BEGIN; + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Material::dimension() failed.", data->dimension, material->dimension()); + + const int matId = 1234; + material->id(matId); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Material::id() failed.", matId, material->id()); + + const std::string& matLabel = "xyz"; + material->setLabel(matLabel.c_str()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Material::getLabel() failed.", matLabel, std::string(material->getLabel())); + + PYLITH_METHOD_END; +} // testAccessors + + +// ---------------------------------------------------------------------- +// Test initialize(). +void +pylith::materials::TestMaterial::testInitialize(void) { + PYLITH_METHOD_BEGIN; + + // Call initialize() + _initializeFull(); // includes setting up auxField + + Material* material = _material();CPPUNIT_ASSERT(material); + const pylith::topology::Field* auxField = material->auxField();CPPUNIT_ASSERT(auxField); + + // material->_auxiliaryField->view("AUX FIELDS"); // :DEBUGGING: + + // Check result + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT_EQUAL(std::string("auxiliary subfields"), std::string(auxField->getLabel())); + CPPUNIT_ASSERT_EQUAL(data->dimension, auxField->getSpaceDim()); + + PylithReal norm = 0.0; + PylithReal t = 0.0; + const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); + pylith::topology::FieldQuery query(*auxField); + query.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + query.openDB(data->auxDB, data->normalizer->getLengthScale()); + PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); + query.closeDB(data->auxDB); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of auxiliary field values failed.", 0.0, norm, tolerance); + +#if 1 + // Verify solution and perturbation fields can be exactly represented by discretization. + norm = 0.0; + t = 0.0; + + pylith::topology::Field& solution = _solutionFields->get("solution"); + // solution.view("SOLUTION"); // :DEBUG: + const PetscDM dmSoln = solution.dmMesh();CPPUNIT_ASSERT(dmSoln); + pylith::topology::FieldQuery solnQuery(solution); + solnQuery.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + solnQuery.openDB(data->solnDB, data->normalizer->getLengthScale()); + err = DMPlexComputeL2DiffLocal(dmSoln, t, solnQuery.functions(), (void**)solnQuery.contextPtrs(), solution.localVector(), &norm);CPPUNIT_ASSERT(!err); + solnQuery.closeDB(data->solnDB); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized solution field failed representation test.", 0.0, norm, tolerance); + + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + // perturbation.view("PERTURBATION"); // :DEBUG: + const PetscDM dmPerturb = perturbation.dmMesh();CPPUNIT_ASSERT(dmPerturb); + pylith::topology::FieldQuery perturbQuery(perturbation); + perturbQuery.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + perturbQuery.openDB(data->perturbDB, data->normalizer->getLengthScale()); + err = DMPlexComputeL2DiffLocal(dmPerturb, t, perturbQuery.functions(), (void**)perturbQuery.contextPtrs(), perturbation.localVector(), &norm);CPPUNIT_ASSERT(!err); + perturbQuery.closeDB(data->perturbDB); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized perturbation field failed representation test.", 0.0, norm, tolerance); +#endif + + PYLITH_METHOD_END; +} // testInitialize + + +// ---------------------------------------------------------------------- +// Test computeResidual(). +void +pylith::materials::TestMaterial::testComputeResidual(void) { + PYLITH_METHOD_BEGIN; + + // Call initialize() + _initializeFull(); // includes setting up auxField + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); + + pylith::topology::Field residualRHS(*_mesh); + residualRHS.cloneSection(solution); + residualRHS.setLabel("residual RHS"); + residualRHS.createDiscretization(); + residualRHS.allocate(); + + pylith::topology::Field residualLHS(*_mesh); + residualLHS.cloneSection(solution); + residualLHS.setLabel("residual LHS"); + residualLHS.createDiscretization(); + residualLHS.allocate(); + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: + DMSetFromOptions(residualRHS.dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + material->computeRHSResidual(&residualRHS, t, dt, solution); + material->computeLHSResidual(&residualLHS, t, dt, solution, solutionDot); + + // We don't use Dirichlet BC, so we must manually zero out the residual values for constrained DOF. + _zeroBoundary(&residualRHS); + _zeroBoundary(&residualLHS); + +#if 0 // :DEBUG: + solution.view("SOLUTION"); // :DEBUG: + solutionDot.view("SOLUTION_DOT"); // :DEBUG: + residualRHS.view("RESIDUAL RHS"); // :DEBUG: + residualLHS.view("RESIDUAL LHS"); // :DEBUG: +#endif // :DEBUG: + + PetscErrorCode err; + PetscVec residualVec = NULL; + err = VecDuplicate(residualRHS.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residualRHS.localVector(), residualLHS.localVector());CPPUNIT_ASSERT(!err); + + PylithReal norm = 0.0; + PylithReal normRHS = 0.0; + PylithReal normLHS = 0.0; + err = VecNorm(residualRHS.localVector(), NORM_2, &normRHS);CPPUNIT_ASSERT(!err); + err = VecNorm(residualLHS.localVector(), NORM_2, &normLHS);CPPUNIT_ASSERT(!err); + err = VecNorm(residualVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of F(s) - G(s) == 0 failed.", 0.0, norm, tolerance); + // Avoid trivial satisfaction of norm with zero values. + CPPUNIT_ASSERT_MESSAGE("RHS and LHS residuals are both exactly zero, which is suspicious.", normRHS > 0.0 || normLHS > 0.0); + + PYLITH_METHOD_END; +} // testComputeResidual + + +// ---------------------------------------------------------------------- +// Test computeJacobian(). +void +pylith::materials::TestMaterial::testComputeJacobian(void) { + PYLITH_METHOD_BEGIN; + + // Create linear problem (MMS) with two trial solutions, s and p. + // + // Check that Jg(s)*(p - s) = G(p) - G(s). + + // Call initialize() + _initializeFull(); + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + + pylith::topology::Field residual1(*_mesh); + residual1.cloneSection(solution); + residual1.setLabel("residual1"); + residual1.createDiscretization(); + residual1.allocate(); + + pylith::topology::Field residual2(*_mesh); + residual2.cloneSection(perturbation); + residual2.setLabel("residual2"); + residual2.createDiscretization(); + residual2.allocate(); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "3"); // :DEBUG: + DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + material->computeLHSResidual(&residual1, t, dt, solution); + material->computeLHSResidual(&residual2, t, dt, perturbation); + + // residual1.view("RESIDUAL 1 RHS"); // :DEBUG: + // residual2.view("RESIDUAL 2 RHS"); // :DEBUG: + + // Compute Jacobian + PetscErrorCode err; + PetscMat jacobianMat = NULL; + err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); + err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); + PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner + + material->computeLHSJacobian(jacobianMat, precondMat, t, dt, solution); + CPPUNIT_ASSERT_EQUAL(false, material->needNewLHSJacobian()); + // _zeroBoundary(&residual1); + // _zeroBoundary(&residual2, jacobianMat); + err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + + // Check that J(s)*(p - s) = G(p) - G(s). + + PetscVec residualVec = NULL; + err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); + + PetscVec solnIncrVec = NULL; + err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); + + // result = Jg*(-solnIncr) + residual + PetscVec resultVec = NULL; + err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); + err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); + err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); + err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); + +#if 0 // :DEBUG: + std::cout << "SOLN INCR" << std::endl; + VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "G2-G1" << std::endl; + VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "RESULT" << std::endl; + VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); +#endif // :DEBUG: + + PylithReal norm = 0.0; + err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); + + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jg(s)*(p-s) - (G(p) - G(s)) == 0 failed.", 0.0, norm, tolerance); + CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", norm > 0.0); + + PYLITH_METHOD_END; +} // testComputeJacobian + + +// ---------------------------------------------------------------------- +// Test computeLHSJacobianImplicit(). +void +pylith::materials::TestMaterial::testComputeLHSJacobianImplicit(void) { + PYLITH_METHOD_BEGIN; + + Material* material = _material();CPPUNIT_ASSERT(material); + const TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + if (data->isExplicit) { + PYLITH_METHOD_END; + } // if + + // Create linear problem (MMS) with two trial solutions, s,s_dor and p,p_dot. + // + // Check that Jf(s,s_dot)*(p - s) = F(p,p_dot) - F(s,s_dot). + + // Call initialize() + _initializeFull(); // includes setting up auxField + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + pylith::topology::Field& perturbationDot = _solutionFields->get("perturbation_dot"); + + pylith::topology::Field residual1(*_mesh); + residual1.cloneSection(solution); + residual1.setLabel("residual1"); + residual1.createDiscretization(); + residual1.allocate(); + + pylith::topology::Field residual2(*_mesh); + residual2.cloneSection(perturbation); + residual2.setLabel("residual2"); + residual2.createDiscretization(); + residual2.allocate(); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: + DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + const PylithReal s_tshift = data->s_tshift; + material->computeLHSResidual(&residual1, t, dt, solution, solutionDot); + material->computeLHSResidual(&residual2, t, dt, perturbation, perturbationDot); + + // residual1.view("RESIDUAL 1 LHS"); // :DEBUG: + // residual2.view("RESIDUAL 2 LHS"); // :DEBUG: + + PetscErrorCode err; + + PetscVec residualVec = NULL; + err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); + + PetscVec solnIncrVec = NULL; + err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); + + // Compute Jacobian + PetscMat jacobianMat = NULL; + err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); + err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); + PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner + + material->computeLHSJacobianImplicit(jacobianMat, precondMat, t, dt, s_tshift, solution, solutionDot); + CPPUNIT_ASSERT_EQUAL(false, material->needNewLHSJacobian()); + err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + + // result = J*(-solnIncr) + residual + PetscVec resultVec = NULL; + err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); + err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); + err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); + err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); + +#if 0 // :DEBUG: + std::cout << "SOLN INCR" << std::endl; + VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "F2-F1" << std::endl; + VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "RESULT" << std::endl; + VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); +#endif // :DEBUG: + + PylithReal norm = 0.0, normSolnIncr = 0.0, normResidual = 0.0; + err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecNorm(solnIncrVec, NORM_2, &normSolnIncr);CPPUNIT_ASSERT(!err); + err = VecNorm(residualVec, NORM_2, &normResidual);CPPUNIT_ASSERT(!err); + err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); + + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jf(s)*(p-s) - (F(p) - F(s)) == 0 failed.", 0.0, norm, tolerance); + CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", (0 < normResidual && 0 < norm) || (0 == normResidual && 0 == norm)); + + PYLITH_METHOD_END; +} // testComputeLHSJacobianImplicit + + +// ---------------------------------------------------------------------- +// Test computeLHSJacobianExplicit(). +void +pylith::materials::TestMaterial::testComputeLHSJacobianInverseExplicit(void) { + PYLITH_METHOD_BEGIN; + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + if (!data->isExplicit) { + PYLITH_METHOD_END; + } // if + + CPPUNIT_ASSERT_MESSAGE("Test not implemented.", false); // :TODO: ADD MORE HERE + + PYLITH_METHOD_END; +} // testComputeLHSJacobianInverseExplicit + + +// ---------------------------------------------------------------------- +// Test updateStateVars(). +void +pylith::materials::TestMaterial::testUpdateStateVars(void) { + PYLITH_METHOD_BEGIN; + + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + if (!data->auxUpdateDB) { + PYLITH_METHOD_END; + } // if + + // Call initialize() + _initializeFull(); // includes setting up auxField + + // We test updating the state variables in the auxiliary field by + // passing the perturbation as the "new" solution and the existing + // auxiliary field. We test whether the "updated" auxiliary field + // matches the database with the updated auxiliary field. + + Material* material = _material();CPPUNIT_ASSERT(material); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); +#if 0 + material->_auxiliaryField->view("INITIAL_AUX FIELDS"); // :DEBUGGING: +#endif + material->_updateStateVars(data->t, data->dt, perturbation); + + const pylith::topology::Field* auxField = material->auxField();CPPUNIT_ASSERT(auxField); + material->_auxiliaryField->view("UPDATED_AUX FIELDS"); // :DEBUGGING: + + // Check updated auxiliary field. + PylithReal norm = 0.0; + PylithReal t = 0.0; + const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); + pylith::topology::FieldQuery query(*auxField); + query.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + query.openDB(data->auxUpdateDB, data->normalizer->getLengthScale()); +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_l2", "1"); // :DEBUG: + DMSetFromOptions(dm); // :DEBUG: +#endif + PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); + query.closeDB(data->auxUpdateDB); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of updated auxiliary field values failed.", 0.0, norm, tolerance); + + PYLITH_METHOD_END; +} // testUpdateStateVars + + +// ---------------------------------------------------------------------- +// Do minimal initilaization of test data. +void +pylith::materials::TestMaterial::_initializeMin(void) { + PYLITH_METHOD_BEGIN; + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + + pylith::meshio::MeshIOAscii iohandler; + CPPUNIT_ASSERT(data->meshFilename); + iohandler.filename(data->meshFilename); + iohandler.read(_mesh);CPPUNIT_ASSERT(_mesh); + + CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any cells.", _mesh->numCells() > 0); + CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any vertices.", _mesh->numVertices() > 0); + + // Setup coordinates. + _mesh->setCoordSys(data->cs); + CPPUNIT_ASSERT(data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *data->normalizer); + + // id and label initialized in derived class + material->normalizer(*data->normalizer); + material->gravityField(data->gravityField); + + // Setup solution fields. + delete _solutionFields;_solutionFields = new pylith::topology::Fields(*_mesh);CPPUNIT_ASSERT(_solutionFields); + _solutionFields->add("solution","solution"); + _solutionFields->add("solution_dot","solution_dot"); + _solutionFields->add("perturbation","perturbation"); + _solutionFields->add("perturbation_dot","perturbation_dot"); + this->_setupSolutionFields(); + + PYLITH_METHOD_END; +} // _initializeMin + + +// ---------------------------------------------------------------------- +// Complete initilaization of test data. +void +pylith::materials::TestMaterial::_initializeFull(void) { + PYLITH_METHOD_BEGIN; + + Material* material = _material();CPPUNIT_ASSERT(material); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT(_mesh); + + // Set auxiliary fields spatial database. + material->auxFieldDB(data->auxDB); + + for (int i = 0; i < data->numAuxSubfields; ++i) { + const pylith::topology::FieldBase::Discretization& info = data->auxDiscretizations[i]; + material->auxSubfieldDiscretization(data->auxSubfields[i], info.basisOrder, info.quadOrder, info.isBasisContinuous, info.feSpace); + } // for + + CPPUNIT_ASSERT(_solutionFields); + material->initialize(_solutionFields->get("solution")); + + PYLITH_METHOD_END; +} // _initializeFull + + +// ---------------------------------------------------------------------- +// Set field to zero on the boundary. +void +pylith::materials::TestMaterial::_zeroBoundary(pylith::topology::Field* field) { + PYLITH_METHOD_BEGIN; + + CPPUNIT_ASSERT(field); + TestMaterial_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT(data->boundaryLabel); + + PetscDM dmMesh = field->mesh().dmMesh();CPPUNIT_ASSERT(dmMesh); + PetscDMLabel label = NULL; + PetscIS pointIS = NULL; + const PetscInt *points; + PetscInt numPoints = 0; + PetscBool hasLabel = PETSC_FALSE; + PetscErrorCode err; + err = DMHasLabel(dmMesh, data->boundaryLabel, &hasLabel);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(hasLabel); + err = DMGetLabel(dmMesh, data->boundaryLabel, &label);CPPUNIT_ASSERT(!err); + err = DMLabelGetStratumIS(label, 1, &pointIS);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(pointIS); + err = ISGetLocalSize(pointIS, &numPoints);CPPUNIT_ASSERT(!err); + err = ISGetIndices(pointIS, &points);CPPUNIT_ASSERT(!err); + + pylith::topology::VecVisitorMesh fieldVisitor(*field); + PylithScalar* fieldArray = fieldVisitor.localArray();CPPUNIT_ASSERT(fieldArray); + + for (PylithInt p = 0; p < numPoints; ++p) { + const PylithInt p_bc = points[p]; + + const PylithInt off = fieldVisitor.sectionOffset(p_bc); + const PylithInt dof = fieldVisitor.sectionDof(p_bc); + for (PylithInt i = 0; i < dof; ++i) { + fieldArray[off+i] = 0.0; + } // for + } // for + + err = ISRestoreIndices(pointIS, &points);PYLITH_CHECK_ERROR(err); + err = ISDestroy(&pointIS);PYLITH_CHECK_ERROR(err); + + PYLITH_METHOD_END; +} // _zeroBoundary + + +// ---------------------------------------------------------------------- +// Constructor +pylith::materials::TestMaterial_Data::TestMaterial_Data(void) : + dimension(0), + meshFilename(0), + boundaryLabel(NULL), + cs(NULL), + gravityField(NULL), + + normalizer(new spatialdata::units::Nondimensional), + + t(0.0), + dt(0.0), + s_tshift(0.0), + perturbation(1.0e-4), + + numSolnSubfields(0), + solnDiscretizations(NULL), + solnDB(new spatialdata::spatialdb::UserFunctionDB), + perturbDB(new spatialdata::spatialdb::UserFunctionDB), + + numAuxSubfields(0), + auxSubfields(NULL), + auxDiscretizations(NULL), + auxDB(new spatialdata::spatialdb::UserFunctionDB), + auxUpdateDB(NULL), + + isExplicit(false) { // constructor + CPPUNIT_ASSERT(normalizer); + + CPPUNIT_ASSERT(solnDB); + solnDB->setLabel("solution"); + + CPPUNIT_ASSERT(perturbDB); + perturbDB->setLabel("solution+perturbation"); + + CPPUNIT_ASSERT(auxDB); + auxDB->setLabel("auxiliary field"); +} // constructor + + +// ---------------------------------------------------------------------- +// Destructor +pylith::materials::TestMaterial_Data::~TestMaterial_Data(void) { + delete cs;cs = NULL; + delete gravityField;gravityField = NULL; + delete normalizer;normalizer = NULL; + delete solnDB;solnDB = NULL; + delete auxDB;auxDB = NULL; + delete auxUpdateDB;auxUpdateDB = NULL; +} // destructor + + // End of file diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am new file mode 100644 index 0000000000..8aac9a7db3 --- /dev/null +++ b/tests/libtests/sources/Makefile.am @@ -0,0 +1,42 @@ +# -*- Makefile -*- +# +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# + +include $(top_srcdir)/tests/check_catch2.am + +SUBDIRS = data + +TESTS = libtest_sources + +check_PROGRAMS = $(TESTS) + + +libtest_sources_SOURCES = \ + TestAuxiliaryFactoryMomentTensorForce.cc \ + TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ + TestAuxiliaryFactorySourceTime.cc \ + TestAuxiliaryFactorySourceTime_Cases.cc \ + $(top_srcdir)/tests/src/FieldTester.cc \ + $(top_srcdir)/tests/src/driver_catch2.cc + + +dist_noinst_HEADERS = \ + TestAuxiliaryFactoryMomentTensorForce.hh \ + TestAuxiliaryFactorySourceTime.hh + + +# End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc new file mode 100644 index 0000000000..7267e22ddc --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc @@ -0,0 +1,221 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// Robert L. Walker, Kegman, Inc. +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactoryMomentTensorForce.hh" // Implementation of class methods + +#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // Test subject +#include "tests/src/FieldTester.hh" // USES FieldTester + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +// ------------------------------------------------------------------------------------------------ +// Constructor. +pylith::sources::TestAuxiliaryFactoryMomentTensorForce::TestAuxiliaryFactoryMomentTensorForce(TestAuxiliaryFactoryMomentTensorForce_Data* data) : + _data(data) { + PYLITH_METHOD_BEGIN; + + assert(_data->normalizer); + _data->normalizer->setLengthScale(1.0e+03); + _data->normalizer->setTimeScale(2.0); + _data->normalizer->setDensityScale(3.0e+3); + _data->normalizer->setPressureScale(2.25e+10); + + pylith::topology::Field::SubfieldInfo info; + pylith::string_vector componentNames; + + // momentTensor + componentNames.resize(6); + componentNames[0] = "moment_tensor_xx"; + componentNames[1] = "moment_tensor_yy"; + componentNames[2] = "moment_tensor_zz"; + componentNames[3] = "moment_tensor_xy"; + componentNames[4] = "moment_tensor_yz"; + componentNames[5] = "moment_tensor_xz"; + + info.description = pylith::topology::Field::Description( + "moment_tensor", + "moment_tensor", + componentNames, + componentNames.size(), + pylith::topology::Field::TENSOR, + _data->normalizer->getPressureScale() + ); + info.fe = pylith::topology::Field::Discretization( + 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false + ); + info.index = 3; + _data->subfields["moment_tensor"] = info; + if (2 == _data->auxDim) { + _data->subfields["moment_tensor"].description.numComponents = 4; + _data->subfields["moment_tensor"].description.vectorFieldType = pylith::topology::Field::OTHER; + } // if + + // timeDelay + componentNames.resize(1); + componentNames[0] = "time_delay"; + info.description = pylith::topology::Field::Description( + "time_delay", + "time_delay", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getTimeScale(), + pylith::topology::FieldQuery::validatorNonnegative + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["time_delay"] = info; + + _initialize(); + + PYLITH_METHOD_END; +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor. +pylith::sources::TestAuxiliaryFactoryMomentTensorForce::~TestAuxiliaryFactoryMomentTensorForce(void) { + PYLITH_METHOD_BEGIN; + + delete _factory;_factory = NULL; + delete _data;_data = NULL; + delete _mesh;_mesh = NULL; + delete _auxiliaryField;_auxiliaryField = NULL; + + PYLITH_METHOD_END; +} // tearDown + + +// ------------------------------------------------------------------------------------------------ +// Test adding moment tensor and time delay subfields. +void +pylith::sources::TestAuxiliaryFactoryMomentTensorForce::testAdd(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + assert(_data); + + CHECK(!_auxiliaryField->hasSubfield("moment_tensor")); + CHECK(!_auxiliaryField->hasSubfield("time_delay")); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + + assert(_data->normalizer); + + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["moment_tensor"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); + + PYLITH_METHOD_END; +} // testAdd + + +// ------------------------------------------------------------------------------------------------ +// Test setValues(). +void +pylith::sources::TestAuxiliaryFactoryMomentTensorForce::testSetValuesFromDB(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + _auxiliaryField->subfieldsSetup(); + _auxiliaryField->createDiscretization(); + _auxiliaryField->allocate(); + + assert(_data); + assert(_data->normalizer); + _factory->setValuesFromDB(); + pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testSetValues + + +// ------------------------------------------------------------------------------------------------ +// Initialze mesh, coordinate system, auxiliary field, and factory. +void +pylith::sources::TestAuxiliaryFactoryMomentTensorForce::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_data); + + pylith::meshio::MeshIOAscii iohandler; + assert(_data->meshFilename); + iohandler.setFilename(_data->meshFilename); + _mesh = new pylith::topology::Mesh();assert(_mesh); + iohandler.read(_mesh); + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Setup coordinates. + _mesh->setCoordSys(_data->cs); + assert(_data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); + + _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); + _auxiliaryField->setLabel("auxiliary"); + + _factory = new AuxiliaryFactoryMomentTensorForce(); + assert(_data->auxiliaryDB); + _factory->setQueryDB(_data->auxiliaryDB); + typedef std::map::const_iterator subfield_iter; + for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { + const char* subfieldName = iter->first.c_str(); + const pylith::topology::Field::Discretization& fe = iter->second.fe; + _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, + fe.feSpace, fe.isBasisContinuous); + } // for + assert(_data->normalizer); + _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data::TestAuxiliaryFactoryMomentTensorForce_Data(void) : + meshFilename(NULL), + cs(NULL), + normalizer(new spatialdata::units::Nondimensional), + auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data::~TestAuxiliaryFactoryMomentTensorForce_Data(void) { + delete cs;cs = NULL; + delete normalizer;normalizer = NULL; + delete auxiliaryDB;auxiliaryDB = NULL; +} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh new file mode 100644 index 0000000000..0d9080b53d --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// Robert L. Walker, Kegman, Inc. +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** + * @file tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh + * + * @brief C++ TestAuxiliaryFactoryMomentTensorForce object. + * + * C++ unit testing for AuxiliaryFactoryMomentTensorForce. + */ + +#if !defined(pylith_sources_testauxiliaryfactorymomenttensorforce_hh) +#define pylith_sources_testauxiliaryfactorymomenttensorforce_hh + +#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent + +#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryMomentTensorForce +#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo +#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB +#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys +#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional + +#include // USES std::map + +namespace pylith { + namespace sources { + class TestAuxiliaryFactoryMomentTensorForce; + class TestAuxiliaryFactoryMomentTensorForce_Data; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryMomentTensorForce : public pylith::utils::GenericComponent { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor. + TestAuxiliaryFactoryMomentTensorForce(TestAuxiliaryFactoryMomentTensorForce_Data* data); + + /// Destructor. + ~TestAuxiliaryFactoryMomentTensorForce(void); + + /// Test adding density, body force, and gravity subfields. + void testAdd(void); + + /// Test setValuesFromDB(). + void testSetValuesFromDB(void); + + // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// +protected: + + /// Initialze mesh, coordinate system, auxiliary field, and factory. + void _initialize(void); + + // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// +protected: + + AuxiliaryFactoryMomentTensorForce* _factory; ///< Test subject. + TestAuxiliaryFactoryMomentTensorForce_Data* _data; ///< Test data. + + pylith::topology::Mesh* _mesh; ///< Finite-element mesh. + pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. + +}; // class TestAuxiliaryFactoryMomentTensorForce + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + TestAuxiliaryFactoryMomentTensorForce_Data(void); + + /// Destructor + ~TestAuxiliaryFactoryMomentTensorForce_Data(void); + + // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// +public: + + size_t dimension; ///< Spatial dimension. + size_t auxDim; ///< Topological dimension of auxiliary field. + const char* meshFilename; ///< Name of file with ASCII mesh. + spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. + spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. + + std::map subfields; + spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. + spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. + +}; // class TestAuxiliaryFactoryMomentTensorForce_Data + +#endif // pylith_sources_testAuxiliaryFactoryMomentTensorForce_hh + +// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc new file mode 100644 index 0000000000..6b59c2f6e2 --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc @@ -0,0 +1,205 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactoryMomentTensorForce.hh" // Implementation of cases + +#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce +#include "spatialdata/geocoords/CSCart.hh" // USES CSCart +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +#include // USES fabs() + +// forward declarations +namespace pylith { + namespace sources { + class TestAuxiliaryFactoryMomentTensorForce_Cases; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases { +public: + + // Data factory methods + static TestAuxiliaryFactoryMomentTensorForce_Data* Tri(void); + + static TestAuxiliaryFactoryMomentTensorForce_Data* Hex(void); + +private: + + static + double moment_tensor_2d_xx(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // moment_tensor_2d_xx + + static + double moment_tensor_2d_yy(const double x, + const double y) { + return -0.8*x*y + 0.2*y*y; + } // moment_tensor_2d_yy + + static + double moment_tensor_2d_zz(const double x, + const double y) { + return -0.3*x*x + 0.5*y*y; + } // moment_tensor_2d_zz + + static + double moment_tensor_2d_xy(const double x, + const double y) { + return -0.3*x*x + 0.3*x*y; + } + + static + const char* pressure_units(void) { + return "Pa"; + } // pressure_units + + static + double time_delay_2d(const double x, + const double y) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); + } // time_delay + + static + const char* time_units(void) { + return "s"; + } // time_units + + static + double moment_tensor_3d_xx(const double x, + const double y, + const double z) { + return -0.3*x*z + 0.1*x*z; + } // moment_tensor_3d_xx + + static + double moment_tensor_3d_yy(const double x, + const double y, + const double z) { + return -0.8*x*z + 0.2*y*y; + } // moment_tensor_3d_yy + + static + double moment_tensor_3d_zz(const double x, + const double y, + const double z) { + return -0.3*x*x + 0.5*y*z; + } // moment_tensor_3d_zz + + static + double moment_tensor_3d_xy(const double x, + const double y, + const double z) { + return -0.3*x + 0.2*x*y; + } // moment_tensor_3d_xy + + static + double moment_tensor_3d_yz(const double x, + const double y, + const double z) { + return -0.3*x*z + 0.2*x*y; + } // moment_tensor_3d_yz + + static + double moment_tensor_3d_xz(const double x, + const double y, + const double z) { + return -0.3*x + 0.2*y; + } // moment_tensor_3d_xz + + static + double time_delay_3d(const double x, + const double y, + const double z) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); + } // time_delay + +}; + +// ------------------------------------------------------------------------------------------------ +TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Tri::testAdd", "[TestAuxiliaryFactoryMomentTensorForce][add]") { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryMomentTensorForce][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri()).testSetValuesFromDB(); +} + +TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Hex::testAdd", "[TestAuxiliaryFactoryMomentTensorForce][add]") { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryMomentTensorForce][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex()).testSetValuesFromDB(); +} + +// -------------------------------------------------------------------------------------------------------------------- +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri(void) { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* data = new pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data(); + assert(data); + + data->auxDim = 2; + data->dimension = 2; + data->meshFilename = "data/tri_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Tri + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* +pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex(void) { + pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* data = new pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data(); + assert(data); + + data->auxDim = 3; + data->dimension = 3; + data->meshFilename = "data/hex_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Hex diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc new file mode 100644 index 0000000000..03f57ea246 --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc @@ -0,0 +1,243 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of class methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // Test subject +#include "tests/src/FieldTester.hh" // USES FieldTester + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +// ------------------------------------------------------------------------------------------------ +// Constructor. +pylith::sources::TestAuxiliaryFactorySourceTime::TestAuxiliaryFactorySourceTime(TestAuxiliaryFactorySourceTime_Data* data) : + _data(data) { + PYLITH_METHOD_BEGIN; + + assert(_data->normalizer); + _data->normalizer->setLengthScale(1.0e+03); + _data->normalizer->setTimeScale(2.0); + _data->normalizer->setDensityScale(3.0e+3); + _data->normalizer->setPressureScale(2.25e+10); + + pylith::topology::Field::SubfieldInfo info; + pylith::string_vector componentNames; + + // momentTensor + componentNames.resize(6); + componentNames[0] = "moment_tensor_xx"; + componentNames[1] = "moment_tensor_yy"; + componentNames[2] = "moment_tensor_zz"; + componentNames[3] = "moment_tensor_xy"; + componentNames[4] = "moment_tensor_yz"; + componentNames[5] = "moment_tensor_xz"; + + info.description = pylith::topology::Field::Description( + "moment_tensor", + "moment_tensor", + componentNames, + componentNames.size(), + pylith::topology::Field::TENSOR, + _data->normalizer->getPressureScale() + ); + info.fe = pylith::topology::Field::Discretization( + 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false + ); + info.index = 3; + _data->subfields["moment_tensor"] = info; + if (2 == _data->auxDim) { + _data->subfields["moment_tensor"].description.numComponents = 4; + _data->subfields["moment_tensor"].description.vectorFieldType = pylith::topology::Field::OTHER; + } // if + + // timeDelay + componentNames.resize(1); + componentNames[0] = "time_delay"; + info.description = pylith::topology::Field::Description( + "time_delay", + "time_delay", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getTimeScale(), + pylith::topology::FieldQuery::validatorNonnegative + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["time_delay"] = info; + + // centerFrequency + componentNames.resize(1); + componentNames[0] = "center_frequency"; + info.description = pylith::topology::Field::Description( + "center_frequency", + "center_frequency", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + 1.0 / _data->normalizer->getTimeScale(), + pylith::topology::FieldQuery::validatorNonnegative + ); + info.fe = pylith::topology::Field::Discretization( + 2, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["center_frequency"] = info; + + _initialize(); + + PYLITH_METHOD_END; +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor. +pylith::sources::TestAuxiliaryFactorySourceTime::~TestAuxiliaryFactorySourceTime(void) { + PYLITH_METHOD_BEGIN; + + delete _factory;_factory = NULL; + delete _data;_data = NULL; + delete _mesh;_mesh = NULL; + delete _auxiliaryField;_auxiliaryField = NULL; + + PYLITH_METHOD_END; +} // tearDown + + +// ------------------------------------------------------------------------------------------------ +// Test adding moment tensor and time delay subfields. +void +pylith::sources::TestAuxiliaryFactorySourceTime::testAdd(void) { + PYLITH_METHOD_BEGIN; + assert(_factory); + assert(_data); + + CHECK(!_auxiliaryField->hasSubfield("moment_tensor")); + CHECK(!_auxiliaryField->hasSubfield("time_delay")); + CHECK(!_auxiliaryField->hasSubfield("center_frequency")); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + _factory->addCenterFrequency(); + + assert(_data->normalizer); + + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["moment_tensor"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["center_frequency"]); + + PYLITH_METHOD_END; +} // testAdd + + +// ------------------------------------------------------------------------------------------------ +// Test setValues(). +void +pylith::sources::TestAuxiliaryFactorySourceTime::testSetValuesFromDB(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + _factory->addCenterFrequency(); + _auxiliaryField->subfieldsSetup(); + _auxiliaryField->createDiscretization(); + _auxiliaryField->allocate(); + + assert(_data); + assert(_data->normalizer); + _factory->setValuesFromDB(); + pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testSetValues + + +// ------------------------------------------------------------------------------------------------ +// Initialze mesh, coordinate system, auxiliary field, and factory. +void +pylith::sources::TestAuxiliaryFactorySourceTime::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_data); + + pylith::meshio::MeshIOAscii iohandler; + assert(_data->meshFilename); + iohandler.setFilename(_data->meshFilename); + _mesh = new pylith::topology::Mesh();assert(_mesh); + iohandler.read(_mesh); + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Setup coordinates. + _mesh->setCoordSys(_data->cs); + assert(_data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); + + _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); + _auxiliaryField->setLabel("auxiliary"); + + _factory = new AuxiliaryFactorySourceTime(); + assert(_data->auxiliaryDB); + _factory->setQueryDB(_data->auxiliaryDB); + typedef std::map::const_iterator subfield_iter; + for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { + const char* subfieldName = iter->first.c_str(); + const pylith::topology::Field::Discretization& fe = iter->second.fe; + _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, + fe.feSpace, fe.isBasisContinuous); + } // for + assert(_data->normalizer); + _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactorySourceTime_Data::TestAuxiliaryFactorySourceTime_Data(void) : + meshFilename(NULL), + cs(NULL), + normalizer(new spatialdata::units::Nondimensional), + auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactorySourceTime_Data::~TestAuxiliaryFactorySourceTime_Data(void) { + delete cs;cs = NULL; + delete normalizer;normalizer = NULL; + delete auxiliaryDB;auxiliaryDB = NULL; +} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh new file mode 100644 index 0000000000..f442189c9d --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// Robert L. Walker, Kegman, Inc. +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** + * @file tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh + * + * @brief C++ TestAuxiliaryFactorySourceTime object. + * + * C++ unit testing for AuxiliaryFactorySourceTime. + */ + +#if !defined(pylith_sources_testauxiliaryfactorysourcetime_hh) +#define pylith_sources_testauxiliaryfactorysourcetime_hh + +#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent + +#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactorySourceTime +#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo +#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB +#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys +#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional + +#include // USES std::map + +namespace pylith { + namespace sources { + class TestAuxiliaryFactorySourceTime; + class TestAuxiliaryFactorySourceTime_Data; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactorySourceTime : public pylith::utils::GenericComponent { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor. + TestAuxiliaryFactorySourceTime(TestAuxiliaryFactorySourceTime_Data* data); + + /// Destructor. + ~TestAuxiliaryFactorySourceTime(void); + + /// Test adding density, body force, and gravity subfields. + void testAdd(void); + + /// Test setValuesFromDB(). + void testSetValuesFromDB(void); + + // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// +protected: + + /// Initialze mesh, coordinate system, auxiliary field, and factory. + void _initialize(void); + + // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// +protected: + + AuxiliaryFactorySourceTime* _factory; ///< Test subject. + TestAuxiliaryFactorySourceTime_Data* _data; ///< Test data. + + pylith::topology::Mesh* _mesh; ///< Finite-element mesh. + pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. + +}; // class TestAuxiliaryFactorySourceTime + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactorySourceTime_Data { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + TestAuxiliaryFactorySourceTime_Data(void); + + /// Destructor + ~TestAuxiliaryFactorySourceTime_Data(void); + + // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// +public: + + size_t dimension; ///< Spatial dimension. + size_t auxDim; ///< Topological dimension of auxiliary field. + const char* meshFilename; ///< Name of file with ASCII mesh. + spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. + spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. + + std::map subfields; + spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. + spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. + +}; // class TestAuxiliaryFactorySourceTime_Data + +#endif // pylith_sources_testAuxiliaryFactorySourceTime_hh + +// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc new file mode 100644 index 0000000000..fb268f0a43 --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc @@ -0,0 +1,225 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of cases + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "spatialdata/geocoords/CSCart.hh" // USES CSCart +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +#include // USES fabs() + +// forward declarations +namespace pylith { + namespace sources { + class TestAuxiliaryFactorySourceTime_Cases; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactorySourceTime_Cases { +public: + + // Data factory methods + static TestAuxiliaryFactorySourceTime_Data* Tri(void); + + static TestAuxiliaryFactorySourceTime_Data* Hex(void); + +private: + + static + double moment_tensor_2d_xx(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // moment_tensor_2d_xx + + static + double moment_tensor_2d_yy(const double x, + const double y) { + return -0.8*x*y + 0.2*y*y; + } // moment_tensor_2d_yy + + static + double moment_tensor_2d_zz(const double x, + const double y) { + return -0.3*x*x + 0.5*y*y; + } // moment_tensor_2d_zz + + static + double moment_tensor_2d_xy(const double x, + const double y) { + return -0.3*x*x + 0.3*x*y; + } + + static + const char* pressure_units(void) { + return "Pa"; + } // pressure_units + + static + double time_delay_2d(const double x, + const double y) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); + } // time_delay + + static + const char* time_units(void) { + return "s"; + } // time_units + + static + double center_frequency_2d(const double x, + const double y) { + return 6.4 + 5.0*fabs(x) + 4.3*fabs(y); + } // center_frequency + + static + const char* frequency_units(void) { + return "1/s"; + } // frequency_units + + static + double moment_tensor_3d_xx(const double x, + const double y, + const double z) { + return -0.3*x*z + 0.1*x*z; + } // moment_tensor_3d_xx + + static + double moment_tensor_3d_yy(const double x, + const double y, + const double z) { + return -0.8*x*z + 0.2*y*y; + } // moment_tensor_3d_yy + + static + double moment_tensor_3d_zz(const double x, + const double y, + const double z) { + return -0.3*x*x + 0.5*y*z; + } // moment_tensor_3d_zz + + static + double moment_tensor_3d_xy(const double x, + const double y, + const double z) { + return -0.3*x + 0.2*x*y; + } // moment_tensor_3d_xy + + static + double moment_tensor_3d_yz(const double x, + const double y, + const double z) { + return -0.3*x*z + 0.2*x*y; + } // moment_tensor_3d_yz + + static + double moment_tensor_3d_xz(const double x, + const double y, + const double z) { + return -0.3*x + 0.2*y; + } // moment_tensor_3d_xz + + static + double time_delay_3d(const double x, + const double y, + const double z) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); + } // time_delay + + static + double center_frequency_3d(const double x, + const double y, + const double z) { + return 6.4 + 4.0*fabs(x) + 5.3*fabs(z); + } // center_frequency + +}; + +// ------------------------------------------------------------------------------------------------ +TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testSetValuesFromDB(); +} + +TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testSetValuesFromDB(); +} + +// -------------------------------------------------------------------------------------------------------------------- +pylith::sources::TestAuxiliaryFactorySourceTime_Data* +pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri(void) { + pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); + assert(data); + + data->auxDim = 2; + data->dimension = 2; + data->meshFilename = "data/tri_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); + data->auxiliaryDB->addValue("center_frequency", center_frequency_2d, frequency_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Tri + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactorySourceTime_Data* +pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex(void) { + pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); + assert(data); + + data->auxDim = 3; + data->dimension = 3; + data->meshFilename = "data/hex_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); + data->auxiliaryDB->addValue("center_frequency", center_frequency_3d, frequency_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Hex diff --git a/tests/libtests/sources/TestSource.cc b/tests/libtests/sources/TestSource.cc new file mode 100644 index 0000000000..559cf60408 --- /dev/null +++ b/tests/libtests/sources/TestSource.cc @@ -0,0 +1,781 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestSource.hh" // Implementation of class methods + +#include "pylith/sources/Source.hh" // USES Source +#include "pylith/sources/Query.hh" // USES Query + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps::nondimensionalize() +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/Fields.hh" // USES Fields +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/topology/FieldQuery.hh" // USES FieldQuery +#include "pylith/feassemble/AuxiliaryFactory.hh" // USES AuxiliaryFactory +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "pylith/utils/journals.hh" // pythia::journal + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +// ---------------------------------------------------------------------- +// Setup testing data. +void +pylith::sources::TestSource::setUp(void) { + _mesh = new pylith::topology::Mesh();CPPUNIT_ASSERT(_mesh); + _solutionFields = NULL; +} // setUp + + +// ---------------------------------------------------------------------- +// Deallocate testing data. +void +pylith::sources::TestSource::tearDown(void) { + delete _solutionFields;_solutionFields = NULL; + delete _mesh;_mesh = NULL; +} // tearDown + + +// ---------------------------------------------------------------------- +// Test auxField(). +void +pylith::sources::TestSource::testAuxField(void) { + PYLITH_METHOD_BEGIN; + + _initializeFull(); + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + + const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); + for (int i = 0; i < data->numAuxSubfields; ++i) { + CPPUNIT_ASSERT(auxField->hasSubfield(data->auxSubfields[i])); + } // for + + CPPUNIT_ASSERT(!auxField->hasSubfield("abc4598245")); + + PYLITH_METHOD_END; +} // testAuxField + + +// ---------------------------------------------------------------------- +// Test auxSubfieldDiscretization(). +void +pylith::sources::TestSource::testAuxSubfieldDiscretization(void) { + PYLITH_METHOD_BEGIN; + + const topology::FieldBase::Discretization infoDefault = pylith::topology::Field::Discretization(1, 1, true, pylith::topology::FieldBase::POLYNOMIAL_SPACE); + const topology::FieldBase::Discretization infoA = pylith::topology::Field::Discretization(1, 2, false, pylith::topology::FieldBase::POLYNOMIAL_SPACE); + const topology::FieldBase::Discretization infoB = pylith::topology::Field::Discretization(2, 2, true, pylith::topology::FieldBase::POINT_SPACE); + + Source* source = _source();CPPUNIT_ASSERT(source); + source->auxSubfieldDiscretization("A", infoA.basisOrder, infoA.quadOrder, infoA.isBasisContinuous, infoA.feSpace); + source->auxSubfieldDiscretization("B", infoB.basisOrder, infoB.quadOrder, infoB.isBasisContinuous, infoB.feSpace); + + CPPUNIT_ASSERT(source->_auxiliaryFactory()); + { // A + const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("A"); + CPPUNIT_ASSERT_EQUAL(infoA.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoA.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoA.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoA.feSpace, test.feSpace); + } // A + + { // B + const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("B"); + CPPUNIT_ASSERT_EQUAL(infoB.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoB.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoB.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoB.feSpace, test.feSpace); + } // B + + { // C (default) + const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("C"); + CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); + } // C (default) + + { // default + const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("default"); + CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); + CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); + CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); + } // default + + PYLITH_METHOD_END; +} // testAuxSubfieldDiscretization + + +// ---------------------------------------------------------------------- +// Test auxFieldDB(). +void +pylith::sources::TestSource::testAuxFieldDB(void) { + PYLITH_METHOD_BEGIN; + + const std::string label = "test db"; + spatialdata::spatialdb::UserFunctionDB db; + db.setLabel(label.c_str()); + + Source* source = _source();CPPUNIT_ASSERT(source); + source->auxFieldDB(&db); + + CPPUNIT_ASSERT(source->_auxiliaryFactory()); + CPPUNIT_ASSERT(source->_auxiliaryFactory()->queryDB()); + CPPUNIT_ASSERT_EQUAL(label, std::string(source->_auxiliaryFactory()->queryDB()->getLabel())); + + PYLITH_METHOD_END; +} // testAuxFieldDB + + +// ---------------------------------------------------------------------- +// Test normalizer(). +void +pylith::sources::TestSource::testNormalizer(void) { + PYLITH_METHOD_BEGIN; + + spatialdata::units::Nondimensional normalizer; + const double scale = 5.0; + normalizer.setLengthScale(scale); + + Source* source = _source();CPPUNIT_ASSERT(source); + source->normalizer(normalizer); + CPPUNIT_ASSERT_EQUAL(scale, source->_normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testNormalizer + + +// ---------------------------------------------------------------------- +// Test verifyConfiguration(). +void +pylith::sources::TestSource::testVerifyConfiguration(void) { + PYLITH_METHOD_BEGIN; + + // Call verifyConfiguration() + Source* source = _source();CPPUNIT_ASSERT(source); + CPPUNIT_ASSERT(_solutionFields); + source->verifyConfiguration(_solutionFields->get("solution")); + + // Nothing to test. + + PYLITH_METHOD_END; +} // testVerifyConfiguration + + +// ---------------------------------------------------------------------- +// Test dimension(), id(), and getLabel(). +void +pylith::sources::TestSource::testAccessors(void) { + PYLITH_METHOD_BEGIN; + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::dimension() failed.", data->dimension, source->dimension()); + + const int matId = 1234; + source->id(matId); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::id() failed.", matId, source->id()); + + const std::string& matLabel = "xyz"; + source->setLabel(matLabel.c_str()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::getLabel() failed.", matLabel, std::string(source->getLabel())); + + PYLITH_METHOD_END; +} // testAccessors + + +// ---------------------------------------------------------------------- +// Test initialize(). +void +pylith::sources::TestSource::testInitialize(void) { + PYLITH_METHOD_BEGIN; + + // Call initialize() + _initializeFull(); // includes setting up auxField + + Source* source = _source();CPPUNIT_ASSERT(source); + const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); + + // source->_auxiliaryField->view("AUX FIELDS"); // :DEBUGGING: + + // Check result + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT_EQUAL(std::string("auxiliary subfields"), std::string(auxField->getLabel())); + CPPUNIT_ASSERT_EQUAL(data->dimension, auxField->getSpaceDim()); + + PylithReal norm = 0.0; + PylithReal t = 0.0; + const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); + pylith::topology::FieldQuery query(*auxField); + query.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + query.openDB(data->auxDB, data->normalizer->getLengthScale()); + PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); + query.closeDB(data->auxDB); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of auxiliary field values failed.", 0.0, norm, tolerance); + +#if 1 + // Verify solution and perturbation fields can be exactly represented by discretization. + norm = 0.0; + t = 0.0; + + pylith::topology::Field& solution = _solutionFields->get("solution"); + // solution.view("SOLUTION"); // :DEBUG: + const PetscDM dmSoln = solution.dmMesh();CPPUNIT_ASSERT(dmSoln); + pylith::topology::FieldQuery solnQuery(solution); + solnQuery.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + solnQuery.openDB(data->solnDB, data->normalizer->getLengthScale()); + err = DMPlexComputeL2DiffLocal(dmSoln, t, solnQuery.functions(), (void**)solnQuery.contextPtrs(), solution.localVector(), &norm);CPPUNIT_ASSERT(!err); + solnQuery.closeDB(data->solnDB); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized solution field failed representation test.", 0.0, norm, tolerance); + + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + // perturbation.view("PERTURBATION"); // :DEBUG: + const PetscDM dmPerturb = perturbation.dmMesh();CPPUNIT_ASSERT(dmPerturb); + pylith::topology::FieldQuery perturbQuery(perturbation); + perturbQuery.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + perturbQuery.openDB(data->perturbDB, data->normalizer->getLengthScale()); + err = DMPlexComputeL2DiffLocal(dmPerturb, t, perturbQuery.functions(), (void**)perturbQuery.contextPtrs(), perturbation.localVector(), &norm);CPPUNIT_ASSERT(!err); + perturbQuery.closeDB(data->perturbDB); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized perturbation field failed representation test.", 0.0, norm, tolerance); +#endif + + PYLITH_METHOD_END; +} // testInitialize + + +// ---------------------------------------------------------------------- +// Test computeResidual(). +void +pylith::sources::TestSource::testComputeResidual(void) { + PYLITH_METHOD_BEGIN; + + // Call initialize() + _initializeFull(); // includes setting up auxField + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); + + pylith::topology::Field residualRHS(*_mesh); + residualRHS.cloneSection(solution); + residualRHS.setLabel("residual RHS"); + residualRHS.createDiscretization(); + residualRHS.allocate(); + + pylith::topology::Field residualLHS(*_mesh); + residualLHS.cloneSection(solution); + residualLHS.setLabel("residual LHS"); + residualLHS.createDiscretization(); + residualLHS.allocate(); + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: + DMSetFromOptions(residualRHS.dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + source->computeRHSResidual(&residualRHS, t, dt, solution); + source->computeLHSResidual(&residualLHS, t, dt, solution, solutionDot); + + // We don't use Dirichlet BC, so we must manually zero out the residual values for constrained DOF. + _zeroBoundary(&residualRHS); + _zeroBoundary(&residualLHS); + +#if 0 // :DEBUG: + solution.view("SOLUTION"); // :DEBUG: + solutionDot.view("SOLUTION_DOT"); // :DEBUG: + residualRHS.view("RESIDUAL RHS"); // :DEBUG: + residualLHS.view("RESIDUAL LHS"); // :DEBUG: +#endif // :DEBUG: + + PetscErrorCode err; + PetscVec residualVec = NULL; + err = VecDuplicate(residualRHS.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residualRHS.localVector(), residualLHS.localVector());CPPUNIT_ASSERT(!err); + + PylithReal norm = 0.0; + PylithReal normRHS = 0.0; + PylithReal normLHS = 0.0; + err = VecNorm(residualRHS.localVector(), NORM_2, &normRHS);CPPUNIT_ASSERT(!err); + err = VecNorm(residualLHS.localVector(), NORM_2, &normLHS);CPPUNIT_ASSERT(!err); + err = VecNorm(residualVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of F(s) - G(s) == 0 failed.", 0.0, norm, tolerance); + // Avoid trivial satisfaction of norm with zero values. + CPPUNIT_ASSERT_MESSAGE("RHS and LHS residuals are both exactly zero, which is suspicious.", normRHS > 0.0 || normLHS > 0.0); + + PYLITH_METHOD_END; +} // testComputeResidual + + +// ---------------------------------------------------------------------- +// Test computeJacobian(). +void +pylith::sources::TestSource::testComputeJacobian(void) { + PYLITH_METHOD_BEGIN; + + // Create linear problem (MMS) with two trial solutions, s and p. + // + // Check that Jg(s)*(p - s) = G(p) - G(s). + + // Call initialize() + _initializeFull(); + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + + pylith::topology::Field residual1(*_mesh); + residual1.cloneSection(solution); + residual1.setLabel("residual1"); + residual1.createDiscretization(); + residual1.allocate(); + + pylith::topology::Field residual2(*_mesh); + residual2.cloneSection(perturbation); + residual2.setLabel("residual2"); + residual2.createDiscretization(); + residual2.allocate(); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "3"); // :DEBUG: + DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + source->computeLHSResidual(&residual1, t, dt, solution); + source->computeLHSResidual(&residual2, t, dt, perturbation); + + // residual1.view("RESIDUAL 1 RHS"); // :DEBUG: + // residual2.view("RESIDUAL 2 RHS"); // :DEBUG: + + // Compute Jacobian + PetscErrorCode err; + PetscMat jacobianMat = NULL; + err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); + err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); + PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner + + source->computeLHSJacobian(jacobianMat, precondMat, t, dt, solution); + CPPUNIT_ASSERT_EQUAL(false, source->needNewLHSJacobian()); + // _zeroBoundary(&residual1); + // _zeroBoundary(&residual2, jacobianMat); + err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + + // Check that J(s)*(p - s) = G(p) - G(s). + + PetscVec residualVec = NULL; + err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); + + PetscVec solnIncrVec = NULL; + err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); + + // result = Jg*(-solnIncr) + residual + PetscVec resultVec = NULL; + err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); + err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); + err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); + err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); + +#if 0 // :DEBUG: + std::cout << "SOLN INCR" << std::endl; + VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "G2-G1" << std::endl; + VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "RESULT" << std::endl; + VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); +#endif // :DEBUG: + + PylithReal norm = 0.0; + err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); + + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jg(s)*(p-s) - (G(p) - G(s)) == 0 failed.", 0.0, norm, tolerance); + CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", norm > 0.0); + + PYLITH_METHOD_END; +} // testComputeJacobian + + +// ---------------------------------------------------------------------- +// Test computeLHSJacobianImplicit(). +void +pylith::sources::TestSource::testComputeLHSJacobianImplicit(void) { + PYLITH_METHOD_BEGIN; + + Source* source = _source();CPPUNIT_ASSERT(source); + const TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + if (data->isExplicit) { + PYLITH_METHOD_END; + } // if + + // Create linear problem (MMS) with two trial solutions, s,s_dor and p,p_dot. + // + // Check that Jf(s,s_dot)*(p - s) = F(p,p_dot) - F(s,s_dot). + + // Call initialize() + _initializeFull(); // includes setting up auxField + + CPPUNIT_ASSERT(_mesh); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& solution = _solutionFields->get("solution"); + pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); + pylith::topology::Field& perturbationDot = _solutionFields->get("perturbation_dot"); + + pylith::topology::Field residual1(*_mesh); + residual1.cloneSection(solution); + residual1.setLabel("residual1"); + residual1.createDiscretization(); + residual1.allocate(); + + pylith::topology::Field residual2(*_mesh); + residual2.cloneSection(perturbation); + residual2.setLabel("residual2"); + residual2.createDiscretization(); + residual2.allocate(); + +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: + DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: +#endif // :DEBUG: + + const PylithReal t = data->t; + const PylithReal dt = data->dt; + const PylithReal s_tshift = data->s_tshift; + source->computeLHSResidual(&residual1, t, dt, solution, solutionDot); + source->computeLHSResidual(&residual2, t, dt, perturbation, perturbationDot); + + // residual1.view("RESIDUAL 1 LHS"); // :DEBUG: + // residual2.view("RESIDUAL 2 LHS"); // :DEBUG: + + PetscErrorCode err; + + PetscVec residualVec = NULL; + err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); + + PetscVec solnIncrVec = NULL; + err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); + + // Compute Jacobian + PetscMat jacobianMat = NULL; + err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); + err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); + PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner + + source->computeLHSJacobianImplicit(jacobianMat, precondMat, t, dt, s_tshift, solution, solutionDot); + CPPUNIT_ASSERT_EQUAL(false, source->needNewLHSJacobian()); + err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); + + // result = J*(-solnIncr) + residual + PetscVec resultVec = NULL; + err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); + err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); + err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); + err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); + +#if 0 // :DEBUG: + std::cout << "SOLN INCR" << std::endl; + VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "F2-F1" << std::endl; + VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); + std::cout << "RESULT" << std::endl; + VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); +#endif // :DEBUG: + + PylithReal norm = 0.0, normSolnIncr = 0.0, normResidual = 0.0; + err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); + err = VecNorm(solnIncrVec, NORM_2, &normSolnIncr);CPPUNIT_ASSERT(!err); + err = VecNorm(residualVec, NORM_2, &normResidual);CPPUNIT_ASSERT(!err); + err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); + err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); + err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); + + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jf(s)*(p-s) - (F(p) - F(s)) == 0 failed.", 0.0, norm, tolerance); + CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", (0 < normResidual && 0 < norm) || (0 == normResidual && 0 == norm)); + + PYLITH_METHOD_END; +} // testComputeLHSJacobianImplicit + + +// ---------------------------------------------------------------------- +// Test computeLHSJacobianExplicit(). +void +pylith::sources::TestSource::testComputeLHSJacobianInverseExplicit(void) { + PYLITH_METHOD_BEGIN; + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + if (!data->isExplicit) { + PYLITH_METHOD_END; + } // if + + CPPUNIT_ASSERT_MESSAGE("Test not implemented.", false); // :TODO: ADD MORE HERE + + PYLITH_METHOD_END; +} // testComputeLHSJacobianInverseExplicit + + +// ---------------------------------------------------------------------- +// Test updateStateVars(). +void +pylith::sources::TestSource::testUpdateStateVars(void) { + PYLITH_METHOD_BEGIN; + + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + if (!data->auxUpdateDB) { + PYLITH_METHOD_END; + } // if + + // Call initialize() + _initializeFull(); // includes setting up auxField + + // We test updating the state variables in the auxiliary field by + // passing the perturbation as the "new" solution and the existing + // auxiliary field. We test whether the "updated" auxiliary field + // matches the database with the updated auxiliary field. + + Source* source = _source();CPPUNIT_ASSERT(source); + CPPUNIT_ASSERT(_solutionFields); + pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); +#if 0 + source->_auxiliaryField->view("INITIAL_AUX FIELDS"); // :DEBUGGING: +#endif + source->_updateStateVars(data->t, data->dt, perturbation); + + const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); + source->_auxiliaryField->view("UPDATED_AUX FIELDS"); // :DEBUGGING: + + // Check updated auxiliary field. + PylithReal norm = 0.0; + PylithReal t = 0.0; + const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); + pylith::topology::FieldQuery query(*auxField); + query.initializeWithDefaultQueryFns(); + CPPUNIT_ASSERT(data->normalizer); + query.openDB(data->auxUpdateDB, data->normalizer->getLengthScale()); +#if 0 // :DEBUG: + PetscOptionsSetValue(NULL, "-dm_plex_print_l2", "1"); // :DEBUG: + DMSetFromOptions(dm); // :DEBUG: +#endif + PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); + query.closeDB(data->auxUpdateDB); + const PylithReal tolerance = 1.0e-6; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of updated auxiliary field values failed.", 0.0, norm, tolerance); + + PYLITH_METHOD_END; +} // testUpdateStateVars + + +// ---------------------------------------------------------------------- +// Do minimal initilaization of test data. +void +pylith::sources::TestSource::_initializeMin(void) { + PYLITH_METHOD_BEGIN; + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + + pylith::meshio::MeshIOAscii iohandler; + CPPUNIT_ASSERT(data->meshFilename); + iohandler.filename(data->meshFilename); + iohandler.read(_mesh);CPPUNIT_ASSERT(_mesh); + + CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any cells.", _mesh->numCells() > 0); + CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any vertices.", _mesh->numVertices() > 0); + + // Setup coordinates. + _mesh->setCoordSys(data->cs); + CPPUNIT_ASSERT(data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *data->normalizer); + + // id and label initialized in derived class + source->normalizer(*data->normalizer); + source->gravityField(data->gravityField); + + // Setup solution fields. + delete _solutionFields;_solutionFields = new pylith::topology::Fields(*_mesh);CPPUNIT_ASSERT(_solutionFields); + _solutionFields->add("solution","solution"); + _solutionFields->add("solution_dot","solution_dot"); + _solutionFields->add("perturbation","perturbation"); + _solutionFields->add("perturbation_dot","perturbation_dot"); + this->_setupSolutionFields(); + + PYLITH_METHOD_END; +} // _initializeMin + + +// ---------------------------------------------------------------------- +// Complete initilaization of test data. +void +pylith::sources::TestSource::_initializeFull(void) { + PYLITH_METHOD_BEGIN; + + Source* source = _source();CPPUNIT_ASSERT(source); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT(_mesh); + + // Set auxiliary fields spatial database. + source->auxFieldDB(data->auxDB); + + for (int i = 0; i < data->numAuxSubfields; ++i) { + const pylith::topology::FieldBase::Discretization& info = data->auxDiscretizations[i]; + source->auxSubfieldDiscretization(data->auxSubfields[i], info.basisOrder, info.quadOrder, info.isBasisContinuous, info.feSpace); + } // for + + CPPUNIT_ASSERT(_solutionFields); + source->initialize(_solutionFields->get("solution")); + + PYLITH_METHOD_END; +} // _initializeFull + + +// ---------------------------------------------------------------------- +// Set field to zero on the boundary. +void +pylith::sources::TestSource::_zeroBoundary(pylith::topology::Field* field) { + PYLITH_METHOD_BEGIN; + + CPPUNIT_ASSERT(field); + TestSource_Data* data = _data();CPPUNIT_ASSERT(data); + CPPUNIT_ASSERT(data->boundaryLabel); + + PetscDM dmMesh = field->mesh().dmMesh();CPPUNIT_ASSERT(dmMesh); + PetscDMLabel label = NULL; + PetscIS pointIS = NULL; + const PetscInt *points; + PetscInt numPoints = 0; + PetscBool hasLabel = PETSC_FALSE; + PetscErrorCode err; + err = DMHasLabel(dmMesh, data->boundaryLabel, &hasLabel);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(hasLabel); + err = DMGetLabel(dmMesh, data->boundaryLabel, &label);CPPUNIT_ASSERT(!err); + err = DMLabelGetStratumIS(label, 1, &pointIS);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(pointIS); + err = ISGetLocalSize(pointIS, &numPoints);CPPUNIT_ASSERT(!err); + err = ISGetIndices(pointIS, &points);CPPUNIT_ASSERT(!err); + + pylith::topology::VecVisitorMesh fieldVisitor(*field); + PylithScalar* fieldArray = fieldVisitor.localArray();CPPUNIT_ASSERT(fieldArray); + + for (PylithInt p = 0; p < numPoints; ++p) { + const PylithInt p_bc = points[p]; + + const PylithInt off = fieldVisitor.sectionOffset(p_bc); + const PylithInt dof = fieldVisitor.sectionDof(p_bc); + for (PylithInt i = 0; i < dof; ++i) { + fieldArray[off+i] = 0.0; + } // for + } // for + + err = ISRestoreIndices(pointIS, &points);PYLITH_CHECK_ERROR(err); + err = ISDestroy(&pointIS);PYLITH_CHECK_ERROR(err); + + PYLITH_METHOD_END; +} // _zeroBoundary + + +// ---------------------------------------------------------------------- +// Constructor +pylith::sources::TestSource_Data::TestSource_Data(void) : + dimension(0), + meshFilename(0), + boundaryLabel(NULL), + cs(NULL), + gravityField(NULL), + + normalizer(new spatialdata::units::Nondimensional), + + t(0.0), + dt(0.0), + s_tshift(0.0), + perturbation(1.0e-4), + + numSolnSubfields(0), + solnDiscretizations(NULL), + solnDB(new spatialdata::spatialdb::UserFunctionDB), + perturbDB(new spatialdata::spatialdb::UserFunctionDB), + + numAuxSubfields(0), + auxSubfields(NULL), + auxDiscretizations(NULL), + auxDB(new spatialdata::spatialdb::UserFunctionDB), + auxUpdateDB(NULL), + + isExplicit(false) { // constructor + CPPUNIT_ASSERT(normalizer); + + CPPUNIT_ASSERT(solnDB); + solnDB->setLabel("solution"); + + CPPUNIT_ASSERT(perturbDB); + perturbDB->setLabel("solution+perturbation"); + + CPPUNIT_ASSERT(auxDB); + auxDB->setLabel("auxiliary field"); +} // constructor + + +// ---------------------------------------------------------------------- +// Destructor +pylith::sources::TestSource_Data::~TestSource_Data(void) { + delete cs;cs = NULL; + delete gravityField;gravityField = NULL; + delete normalizer;normalizer = NULL; + delete solnDB;solnDB = NULL; + delete auxDB;auxDB = NULL; + delete auxUpdateDB;auxUpdateDB = NULL; +} // destructor + + +// End of file diff --git a/tests/libtests/sources/TestSource.hh b/tests/libtests/sources/TestSource.hh new file mode 100644 index 0000000000..9245c92889 --- /dev/null +++ b/tests/libtests/sources/TestSource.hh @@ -0,0 +1,211 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** + * @file tests/libtests/sources/TestSource.hh + * + * @brief C++ abstract base class for testing source objects. + */ + +#if !defined(pylith_sources_testSource_hh) +#define pylith_sources_testSource_hh + +#include +#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent + +#include "pylith/sources/sourcesfwd.hh" // forward declarations +#include "pylith/topology/topologyfwd.hh" // forward declarations +#include "pylith/topology/Field.hh" // HASA FieldBase::Discretization + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA UserFunctionDB +#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA CoordSys +#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional + +/// Namespace for pylith package +namespace pylith { + namespace sources { + class TestSource; + + class TestSource_Data; // test data + } // sources +} // pylith + +/// C++ abstract base class for testing source objects. +class pylith::sources::TestSource : public CppUnit::TestFixture, public pylith::utils::GenericComponent { + // CPPUNIT TEST SUITE ///////////////////////////////////////////////// + CPPUNIT_TEST_SUITE(TestSource); + + CPPUNIT_TEST(testAuxField); + CPPUNIT_TEST(testAuxSubfieldDiscretization); + CPPUNIT_TEST(testAuxFieldDB); + CPPUNIT_TEST(testNormalizer); + + CPPUNIT_TEST(testVerifyConfiguration); + + CPPUNIT_TEST(testAccessors); + CPPUNIT_TEST(testInitialize); + + CPPUNIT_TEST(testComputeResidual); + CPPUNIT_TEST(testComputeJacobian); + CPPUNIT_TEST(testComputeLHSJacobianImplicit); + CPPUNIT_TEST(testComputeLHSJacobianInverseExplicit); + CPPUNIT_TEST(testUpdateStateVars); + + CPPUNIT_TEST_SUITE_END_ABSTRACT(); + + // PUBLIC METHODS ///////////////////////////////////////////////////// +public: + + /// Setup testing data. + virtual + void setUp(void); + + /// Deallocate testing data. + void tearDown(void); + + /// Test auxField(). + void testAuxField(void); + + /// Test constructor. + void testConstructor(void); + + // /// Test accessors (field, dbTimeHistory, useInitial, useRate, useTimeHistory). + // void testAccessors(void); + + /// Test dimension(), id(), and getLabel(). + void testAccessors(void); + + /// Test auxFieldDiscretization(). + void testAuxFieldDiscretization(void); + + /// Test auxFieldDB(). + void testAuxFieldDB(void); + + /// Test normalizer(). + void testNormalizer(void); + + /// Test verifyConfiguration(). + void testVerifyConfiguration(void); + + /// Test checkConstraints(). + void testCheckConstraints(void); + + /// Test initialize(). + void testInitialize(void); + + /// Test computeRHSResidual(), computeLHSResidual(). + void testComputeResidual(void); + + /// Test computeJacobian(). + void testComputeJacobian(void); + + /// Test computeLHSJacobianImplicit(). + void testComputeLHSJacobianImplicit(void); + + /// Test computeLHSJacobianInverseExplicit(). + void testComputeLHSJacobianInverseExplicit(void); + + /// Test _updateStateVars(). + void testUpdateStateVars(void); + + // PROTECTED METHODS ////////////////////////////////////////////////// +protected: + + /** Get source. + * + * @returns Pointer to source. + */ + virtual + Source* _source(void) = 0; + + /** Get test data. + * + * @returns Pointer to test data. + */ + virtual + TestSource_Data* _data(void) = 0; + + /// Do minimal initilaization of test data. + void _initializeMin(void); + + /// Do full initilaization of test data. + void _initializeFull(void); + + /** Set field (and, optionally, matrix rows and columns) to zero on the boundary. + * + * @param[out] field Field in which to set boundary values to zero. + */ + void _zeroBoundary(pylith::topology::Field* field); + + /// Setup and populate solution fields. + virtual + void _setupSolutionFields(void) = 0; + + // PROTECTED MEMBERS ////////////////////////////////////////////////// +protected: + + // TestSource + pylith::topology::Mesh* _mesh; ///< Finite-element mesh. + pylith::topology::Fields* _solutionFields; ///< Contrainer for solution fields. + +}; // class TestSource + +// ============================================================================= +class pylith::sources::TestSource_Data { + // PUBLIC METHODS /////////////////////////////////////////////////////// +public: + + /// Constructor + TestSource_Data(void); + + /// Destructor + ~TestSource_Data(void); + + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + int dimension; ///< Dimension of source. + const char* meshFilename; ///< Name of file with ASCII mesh. + const char* boundaryLabel; ///< Group defining domain boundary. + + spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. + spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field. + spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. + + PylithReal t; ///< Time for solution in simulation. + PylithReal dt; ///< Time step in simulation. + PylithReal s_tshift; ///< Time shift for LHS Jacobian. + PylithReal perturbation; ///< Maximum amplitude of random perturbation. + + int numSolnSubfields; ///< Number of solution fields. + pylith::topology::Field::Discretization* solnDiscretizations; ///< Discretizations for solution fields. + spatialdata::spatialdb::UserFunctionDB* solnDB; ///< Spatial database with solution. + spatialdata::spatialdb::UserFunctionDB* perturbDB; ///< Spatial database with solution + perturbation. + + int numAuxSubfields; ///< Number of auxiliary subfields. + const char** auxSubfields; ///< Names of auxiliary subfields. + pylith::topology::Field::Discretization* auxDiscretizations; ///< Discretizations for auxiliary subfields. + spatialdata::spatialdb::UserFunctionDB* auxDB; ///< Spatial database with auxiliary field. + spatialdata::spatialdb::UserFunctionDB* auxUpdateDB; ///< Spatial database with updated auxiliary field. + + bool isExplicit; ///< True for explicit time stepping. +}; + +#endif // pylith_sources_testSource_hh + +// End of file diff --git a/tests/libtests/sources/data/Makefile.am b/tests/libtests/sources/data/Makefile.am new file mode 100644 index 0000000000..ad879dbb44 --- /dev/null +++ b/tests/libtests/sources/data/Makefile.am @@ -0,0 +1,29 @@ +# -*- Makefile -*- +# +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# + +dist_noinst_DATA = \ + tri_onecell.mesh \ + hex_onecell.mesh + +noinst_TMP = + +export_datadir = $(abs_builddir) +include $(top_srcdir)/tests/data.am + + +# End of file diff --git a/tests/libtests/sources/data/hex_onecell.mesh b/tests/libtests/sources/data/hex_onecell.mesh new file mode 100644 index 0000000000..76565397d3 --- /dev/null +++ b/tests/libtests/sources/data/hex_onecell.mesh @@ -0,0 +1,37 @@ +mesh = { + dimension = 3 + use-index-zero = true + vertices = { + dimension = 3 + count = 8 + coordinates = { + 0 -4.000000000000000000e+03 -4.000000000000000000e+03 4.000000000000000000e+03 + 1 -4.000000000000000000e+03 -4.000000000000000000e+03 2.000000000000000000e+03 + 2 -4.000000000000000000e+03 -2.000000000000000000e+03 2.000000000000000000e+03 + 3 -4.000000000000000000e+03 -2.000000000000000000e+03 4.000000000000000000e+03 + 4 -2.000000000000000000e+03 -4.000000000000000000e+03 4.000000000000000000e+03 + 5 -2.000000000000000000e+03 -4.000000000000000000e+03 2.000000000000000000e+03 + 6 -2.000000000000000000e+03 -2.000000000000000000e+03 2.000000000000000000e+03 + 7 -2.000000000000000000e+03 -2.000000000000000000e+03 4.000000000000000000e+03 + } + } + cells = { + count = 1 + num-corners = 8 + simplices = { + 0 0 1 2 3 4 5 6 7 + } + material-ids = { + 0 24 + } + } + group = { + type = vertices + name = boundary + count = 8 + indices = { + 0 1 2 3 4 5 6 7 + } + } + +} diff --git a/tests/libtests/sources/data/tri_onecell.mesh b/tests/libtests/sources/data/tri_onecell.mesh new file mode 100644 index 0000000000..aa364381eb --- /dev/null +++ b/tests/libtests/sources/data/tri_onecell.mesh @@ -0,0 +1,32 @@ +mesh = { + dimension = 2 + use-index-zero = true + vertices = { + dimension = 2 + count = 3 + coordinates = { + 0 -1.0e+3 -1.0e+3 + 1 +1.0e+3 -1.0e+3 + 2 -1.0e+3 +1.0e+3 + } + } + cells = { + count = 1 + num-corners = 3 + simplices = { + 0 0 1 2 + } + material-ids = { + 0 24 + } + } + group = { + type = vertices + name = boundary + count = 3 + indices = { + 0 1 2 + } + } + +} diff --git a/tests/pytests/sources/TestPointForce.py b/tests/pytests/sources/TestPointForce.py new file mode 100644 index 0000000000..722ea51b55 --- /dev/null +++ b/tests/pytests/sources/TestPointForce.py @@ -0,0 +1,41 @@ +#!/usr/bin/env nemesis +# +# ====================================================================== +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ====================================================================== +# +# @file tests/pytests/sources/TestPointForce.py +# +# @brief Unit testing of Python TestPointForce object. + +import unittest + +from pylith.testing.UnitTestApp import TestComponent +from pylith.sources.Source import (PointForce, source) + + +class TestPointForce(TestComponent): + """Unit testing of Elasticity object. + """ + _class = PointForce + _factory = source + + +if __name__ == "__main__": + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestPointForce)) + unittest.TextTestRunner(verbosity=2).run(suite) + + +# End of file diff --git a/tests/pytests/sources/TestSource.py b/tests/pytests/sources/TestSource.py new file mode 100644 index 0000000000..a17a14f0ae --- /dev/null +++ b/tests/pytests/sources/TestSource.py @@ -0,0 +1,40 @@ +#!/usr/bin/env nemesis +# +# ====================================================================== +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ====================================================================== +# +# @file tests/pytests/sources/TestSource.py +# +# @brief Unit testing of Python TestSource object. + +import unittest + +from pylith.testing.UnitTestApp import TestAbstractComponent +from pylith.sources.Source import Source + + +class TestSource(TestAbstractComponent): + """Unit testing of Source object. + """ + _class = Source + + +if __name__ == "__main__": + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestSource)) + unittest.TextTestRunner(verbosity=2).run(suite) + + +# End of file diff --git a/tests/pytests/sources/TestWellboreSource.py b/tests/pytests/sources/TestWellboreSource.py new file mode 100644 index 0000000000..cad8a4a8bb --- /dev/null +++ b/tests/pytests/sources/TestWellboreSource.py @@ -0,0 +1,41 @@ +#!/usr/bin/env nemesis +# +# ====================================================================== +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ====================================================================== +# +# @file tests/pytests/sources/TestWellboreSource.py +# +# @brief Unit testing of Python TestWellboreSource object. + +import unittest + +from pylith.testing.UnitTestApp import TestComponent +from pylith.sources.Source import (WellboreSource, source) + + +class TestWellboreSource(TestComponent): + """Unit testing of Elasticity object. + """ + _class = WellboreSource + _factory = source + + +if __name__ == "__main__": + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestWellboreSource)) + unittest.TextTestRunner(verbosity=2).run(suite) + + +# End of file diff --git a/tests/pytests/sources/__init__.py b/tests/pytests/sources/__init__.py new file mode 100644 index 0000000000..de99687c0a --- /dev/null +++ b/tests/pytests/sources/__init__.py @@ -0,0 +1,2 @@ +from .TestSource import TestSource +from .TestWellboreSource import TestWellboreSource \ No newline at end of file From 529f0411e0aa22ee9c4253ab9e04f3569792169c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 25 Oct 2023 14:20:37 -0700 Subject: [PATCH 19/65] Passes libtest for source --- .../AuxiliaryFactoryMomentTensorForce.cc | 2 +- .../sources/AuxiliaryFactorySourceTime.cc | 3 ++- .../TestAuxiliaryFactoryMomentTensorForce.cc | 4 ++-- ...AuxiliaryFactoryMomentTensorForce_Cases.cc | 24 +++++++++---------- .../sources/TestAuxiliaryFactorySourceTime.cc | 6 ++--- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc index 188d896253..8a986dc2a4 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -64,7 +64,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // m pylith::topology::Field::Description description; description.label = subfieldName; description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::OTHER; + description.vectorFieldType = (3 == _spaceDim) ? pylith::topology::Field::TENSOR : pylith::topology::Field::OTHER; description.numComponents = tensorSize; description.componentNames.resize(tensorSize); for (int i = 0; i < tensorSize; ++i) { diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index 9bd2ce3fd5..39b040f9db 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -50,6 +50,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { // cente PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); const char* subfieldName = "center_frequency"; + const PylithReal timeScale = _normalizer->getTimeScale(); pylith::topology::Field::Description description; description.label = subfieldName; @@ -58,7 +59,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { // cente description.numComponents = 1; description.componentNames.resize(1); description.componentNames[0] = subfieldName; - description.scale = 1.0; + description.scale = 1.0 / timeScale; description.validator = pylith::topology::FieldQuery::validatorNonnegative; _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc index 7267e22ddc..bda73860f4 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc @@ -72,7 +72,7 @@ pylith::sources::TestAuxiliaryFactoryMomentTensorForce::TestAuxiliaryFactoryMome info.fe = pylith::topology::Field::Discretization( 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false ); - info.index = 3; + info.index = 0; _data->subfields["moment_tensor"] = info; if (2 == _data->auxDim) { _data->subfields["moment_tensor"].description.numComponents = 4; @@ -94,7 +94,7 @@ pylith::sources::TestAuxiliaryFactoryMomentTensorForce::TestAuxiliaryFactoryMome info.fe = pylith::topology::Field::Discretization( 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true ); - info.index = 0; + info.index = 1; _data->subfields["time_delay"] = info; _initialize(); diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc index 6b59c2f6e2..aa0de17b7a 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc @@ -72,9 +72,9 @@ class pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases { } static - const char* pressure_units(void) { + const char* moment_tensor_units(void) { return "Pa"; - } // pressure_units + } // moment_tensor_units static double time_delay_2d(const double x, @@ -166,10 +166,10 @@ pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri(void) { data->cs->setSpaceDim(data->dimension); assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, moment_tensor_units()); data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); data->auxiliaryDB->setDescription("auxiliary"); data->auxiliaryDB->setCoordSys(*data->cs); @@ -191,12 +191,12 @@ pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex(void) { data->cs->setSpaceDim(data->dimension); assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, moment_tensor_units()); + data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, moment_tensor_units()); data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); data->auxiliaryDB->setDescription("auxiliary"); data->auxiliaryDB->setCoordSys(*data->cs); diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc index 03f57ea246..b45fb3ee43 100644 --- a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc +++ b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc @@ -73,7 +73,7 @@ pylith::sources::TestAuxiliaryFactorySourceTime::TestAuxiliaryFactorySourceTime( info.fe = pylith::topology::Field::Discretization( 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false ); - info.index = 3; + info.index = 0; _data->subfields["moment_tensor"] = info; if (2 == _data->auxDim) { _data->subfields["moment_tensor"].description.numComponents = 4; @@ -95,7 +95,7 @@ pylith::sources::TestAuxiliaryFactorySourceTime::TestAuxiliaryFactorySourceTime( info.fe = pylith::topology::Field::Discretization( 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true ); - info.index = 0; + info.index = 1; _data->subfields["time_delay"] = info; // centerFrequency @@ -113,7 +113,7 @@ pylith::sources::TestAuxiliaryFactorySourceTime::TestAuxiliaryFactorySourceTime( info.fe = pylith::topology::Field::Discretization( 2, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true ); - info.index = 0; + info.index = 2; _data->subfields["center_frequency"] = info; _initialize(); From a08a9e3a82c528e1f5f420f0b7c1da89c5fc7a9e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 22 Nov 2023 20:48:26 -0700 Subject: [PATCH 20/65] Intermediate update for unit tests --- tests/libtests/sources/Makefile.am | 2 + .../sources/TestAuxiliaryFactoryPointForce.cc | 216 +++++++++ .../sources/TestAuxiliaryFactoryPointForce.hh | 110 +++++ .../TestAuxiliaryFactoryPointForce_Cases.cc | 173 +++++++ .../TestAuxiliaryFactoryWellboreSource.cc | 458 ++++++++++++++++++ ...estAuxiliaryFactoryWellboreSource_Cases.cc | 254 ++++++++++ .../pytests/sources/TestMomentTensorForce.py | 41 ++ tests/pytests/sources/TestPointForce.py | 2 +- tests/pytests/sources/TestWellboreSource.py | 2 +- 9 files changed, 1256 insertions(+), 2 deletions(-) create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc create mode 100644 tests/pytests/sources/TestMomentTensorForce.py diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am index 8aac9a7db3..2c77df89ac 100644 --- a/tests/libtests/sources/Makefile.am +++ b/tests/libtests/sources/Makefile.am @@ -30,6 +30,8 @@ libtest_sources_SOURCES = \ TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ TestAuxiliaryFactorySourceTime.cc \ TestAuxiliaryFactorySourceTime_Cases.cc \ + TestAuxiliaryFactoryPointForce.cc \ + TestAuxiliaryFactoryPointForce_Cases.cc \ $(top_srcdir)/tests/src/FieldTester.cc \ $(top_srcdir)/tests/src/driver_catch2.cc diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc new file mode 100644 index 0000000000..9deaaf8aad --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc @@ -0,0 +1,216 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactoryPointForce.hh" // Implementation of class methods + +#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // Test subject +#include "tests/src/FieldTester.hh" // USES FieldTester + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +// ------------------------------------------------------------------------------------------------ +// Constructor. +pylith::sources::TestAuxiliaryFactoryPointForce::TestAuxiliaryFactoryPointForce(TestAuxiliaryFactoryPointForce_Data* data) : + _data(data) { + PYLITH_METHOD_BEGIN; + + assert(_data->normalizer); + _data->normalizer->setLengthScale(1.0e+03); + _data->normalizer->setTimeScale(2.0); + _data->normalizer->setDensityScale(3.0e+3); + _data->normalizer->setPressureScale(2.25e+10); + + pylith::topology::Field::SubfieldInfo info; + pylith::string_vector componentNames; + + // momentTensor + componentNames.resize(3); + componentNames[0] = "point_force_x"; + componentNames[1] = "point_force_y"; + componentNames[2] = "point_force_z"; + + info.description = pylith::topology::Field::Description( + "point_force", + "point_force", + componentNames, + componentNames.size(), + pylith::topology::Field::VECTOR, + _data->normalizer->getPressureScale() + ); + info.fe = pylith::topology::Field::Discretization( + 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false + ); + info.index = 0; + _data->subfields["point_force"] = info; + if (2 == _data->auxDim) { + _data->subfields["point_force"].description.numComponents = 2; + _data->subfields["point_force"].description.vectorFieldType = pylith::topology::Field::OTHER; + } // if + + // timeDelay + componentNames.resize(1); + componentNames[0] = "time_delay"; + info.description = pylith::topology::Field::Description( + "time_delay", + "time_delay", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getTimeScale(), + pylith::topology::FieldQuery::validatorNonnegative + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 1; + _data->subfields["time_delay"] = info; + + PYLITH_METHOD_END; +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor. +pylith::sources::TestAuxiliaryFactoryPointForce::~TestAuxiliaryFactoryPointForce(void) { + PYLITH_METHOD_BEGIN; + + delete _factory;_factory = NULL; + delete _data;_data = NULL; + delete _mesh;_mesh = NULL; + delete _auxiliaryField;_auxiliaryField = NULL; + + PYLITH_METHOD_END; +} // tearDown + + +// ------------------------------------------------------------------------------------------------ +// Test adding moment tensor and time delay subfields. +void +pylith::sources::TestAuxiliaryFactoryPointForce::testAdd(void) { + PYLITH_METHOD_BEGIN; + assert(_factory); + assert(_data); + + CHECK(!_auxiliaryField->hasSubfield("point_force")); + CHECK(!_auxiliaryField->hasSubfield("time_delay")); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + + assert(_data->normalizer); + + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["point_force"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); + + PYLITH_METHOD_END; +} // testAdd + + +// ------------------------------------------------------------------------------------------------ +// Test setValues(). +void +pylith::sources::TestAuxiliaryFactoryPointForce::testSetValuesFromDB(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + + _factory->addMomentTensor(); + _factory->addTimeDelay(); + _auxiliaryField->subfieldsSetup(); + _auxiliaryField->createDiscretization(); + _auxiliaryField->allocate(); + + assert(_data); + assert(_data->normalizer); + _factory->setValuesFromDB(); + pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testSetValues + + +// ------------------------------------------------------------------------------------------------ +// Initialze mesh, coordinate system, auxiliary field, and factory. +void +pylith::sources::TestAuxiliaryFactoryPointForce::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_data); + + pylith::meshio::MeshIOAscii iohandler; + assert(_data->meshFilename); + iohandler.setFilename(_data->meshFilename); + _mesh = new pylith::topology::Mesh();assert(_mesh); + iohandler.read(_mesh); + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Setup coordinates. + _mesh->setCoordSys(_data->cs); + assert(_data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); + + _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); + _auxiliaryField->setLabel("auxiliary"); + + _factory = new AuxiliaryFactoryPointForce(); + assert(_data->auxiliaryDB); + _factory->setQueryDB(_data->auxiliaryDB); + typedef std::map::const_iterator subfield_iter; + for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { + const char* subfieldName = iter->first.c_str(); + const pylith::topology::Field::Discretization& fe = iter->second.fe; + _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, + fe.feSpace, fe.isBasisContinuous); + } // for + assert(_data->normalizer); + _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryPointForce_Data::TestAuxiliaryFactoryPointForce_Data(void) : + meshFilename(NULL), + cs(NULL), + normalizer(new spatialdata::units::Nondimensional), + auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryPointForce_Data::~TestAuxiliaryFactoryPointForce_Data(void) { + delete cs;cs = NULL; + delete normalizer;normalizer = NULL; + delete auxiliaryDB;auxiliaryDB = NULL; +} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh new file mode 100644 index 0000000000..6e7bc371c0 --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// Robert L. Walker, Kegman, Inc. +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** + * @file tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh + * + * @brief C++ TestAuxiliaryFactoryPointForce object. + * + * C++ unit testing for AuxiliaryFactoryPointForce. + */ + +#if !defined(pylith_sources_testauxiliaryfactorypointforce_hh) +#define pylith_sources_testauxiliaryfactorypointforce_hh + +#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent + +#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryPointForce +#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo +#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB +#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys +#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional + +#include // USES std::map + +namespace pylith { + namespace sources { + class TestAuxiliaryFactoryPointForce; + class TestAuxiliaryFactoryPointForce_Data; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryPointForce : public pylith::utils::GenericComponent { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor. + TestAuxiliaryFactoryPointForce(TestAuxiliaryFactoryPointForce_Data* data); + + /// Destructor. + ~TestAuxiliaryFactoryPointForce(void); + + /// Test adding density, body force, and gravity subfields. + void testAdd(void); + + /// Test setValuesFromDB(). + void testSetValuesFromDB(void); + + // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// +protected: + + /// Initialze mesh, coordinate system, auxiliary field, and factory. + void _initialize(void); + + // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// +protected: + + AuxiliaryFactoryPointForce* _factory; ///< Test subject. + TestAuxiliaryFactoryPointForce_Data* _data; ///< Test data. + + pylith::topology::Mesh* _mesh; ///< Finite-element mesh. + pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. + +}; // class TestAuxiliaryFactoryPointForce + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryPointForce_Data { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + TestAuxiliaryFactoryPointForce_Data(void); + + /// Destructor + ~TestAuxiliaryFactoryPointForce_Data(void); + + // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// +public: + + size_t dimension; ///< Spatial dimension. + size_t auxDim; ///< Topological dimension of auxiliary field. + const char* meshFilename; ///< Name of file with ASCII mesh. + spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. + spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. + + std::map subfields; + spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. + spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. + +}; // class TestAuxiliaryFactoryPointForce_Data + +#endif // pylith_sources_testAuxiliaryFactoryPointForce_hh + +// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc new file mode 100644 index 0000000000..65ae75d12a --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc @@ -0,0 +1,173 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactoryPointForce.hh" // Implementation of cases + +#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // USES AuxiliaryFactoryPointForce +#include "spatialdata/geocoords/CSCart.hh" // USES CSCart +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +#include // USES fabs() + +// forward declarations +namespace pylith { + namespace sources { + class TestAuxiliaryFactoryPointForce_Cases; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryPointForce_Cases { +public: + + // Data factory methods + static TestAuxiliaryFactoryPointForce_Data* Tri(void); + + static TestAuxiliaryFactoryPointForce_Data* Hex(void); + +private: + + static + double point_force_2d_x(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // point_force_2d_x + + static + double point_force_2d_y(const double x, + const double y) { + return -0.8*x*y + 0.2*y*y; + } // point_force_2d_yy + + static + double point_force_2d_z(const double x, + const double y) { + return -0.3*x*x + 0.5*y*y; + } // point_force_2d_z + + static + const char* point_force_units(void) { + return "Pa"; + } // point_force_units + + static + double time_delay_2d(const double x, + const double y) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); + } // time_delay + + static + const char* time_units(void) { + return "s"; + } // time_units + + static + double point_force_3d_x(const double x, + const double y, + const double z) { + return -0.3*x*z + 0.1*x*z; + } // point_force_3d_x + + static + double point_force_3d_y(const double x, + const double y, + const double z) { + return -0.8*x*z + 0.2*y*y; + } // point_force_3d_y + + static + double point_force_3d_z(const double x, + const double y, + const double z) { + return -0.3*x*x + 0.5*y*z; + } // point_force_3d_z + + static + double time_delay_3d(const double x, + const double y, + const double z) { + return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); + } // time_delay + +}; + +// ------------------------------------------------------------------------------------------------ +TEST_CASE("TestAuxiliaryFactoryPointForce::Tri::testAdd", "[TestAuxiliaryFactoryPointForce][add]") { + pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactoryPointForce::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryPointForce][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri()).testSetValuesFromDB(); +} + +TEST_CASE("TestAuxiliaryFactoryPointForce::Hex::testAdd", "[TestAuxiliaryFactoryPointForce][add]") { + pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactoryPointForce::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryPointForce][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex()).testSetValuesFromDB(); +} + +// -------------------------------------------------------------------------------------------------------------------- +pylith::sources::TestAuxiliaryFactoryPointForce_Data* +pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri(void) { + pylith::sources::TestAuxiliaryFactoryPointForce_Data* data = new pylith::sources::TestAuxiliaryFactoryPointForce_Data(); + assert(data); + + data->auxDim = 2; + data->dimension = 2; + data->meshFilename = "data/tri_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("point_force_x", point_force_2d_x, point_force_units()); + data->auxiliaryDB->addValue("point_force_y", point_force_2d_y, point_force_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Tri + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryPointForce_Data* +pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex(void) { + pylith::sources::TestAuxiliaryFactoryPointForce_Data* data = new pylith::sources::TestAuxiliaryFactoryPointForce_Data(); + assert(data); + + data->auxDim = 3; + data->dimension = 3; + data->meshFilename = "data/hex_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("point_force_x", point_force_3d_x, point_force_units()); + data->auxiliaryDB->addValue("point_force_y", point_force_3d_y, point_force_units()); + data->auxiliaryDB->addValue("point_force_z", point_force_3d_z, point_force_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Hex diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc new file mode 100644 index 0000000000..a6cc2dba6b --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc @@ -0,0 +1,458 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactoryWellboreSource.hh" // Implementation of class methods + +#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // Test subject +#include "tests/src/FieldTester.hh" // USES FieldTester + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +// ------------------------------------------------------------------------------------------------ +// Constructor. +pylith::sources::TestAuxiliaryFactoryWellboreSource::TestAuxiliaryFactoryWellboreSource(TestAuxiliaryFactoryWellboreSource_Data* data) : + _data(data) { + PYLITH_METHOD_BEGIN; + + assert(_data->normalizer); + _data->normalizer->setLengthScale(1.0e+03); + _data->normalizer->setTimeScale(2.0); + _data->normalizer->setDensityScale(3.0e+3); + _data->normalizer->setPressureScale(2.25e+10); + + pylith::topology::Field::SubfieldInfo info; + pylith::string_vector componentNames; + + // fluid_density + componentNames.resize(1); + componentNames[0] = "fluid_density"; + info.description = pylith::topology::Field::Description( + "fluid_density", + "fluid_density", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getDensityScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["fluid_density"] = info; + + // fluid_viscosity + componentNames.resize(1); + componentNames[0] = "fluid_viscosity"; + info.description = pylith::topology::Field::Description( + "fluid_viscosity", + "fluid_viscosity", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getViscosityScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["fluid_viscosity"] = info; + + // isotropic_permeability + componentNames.resize(1); + componentNames[0] = "isotropic_permeability"; + info.description = pylith::topology::Field::Description( + "isotropic_permeability", + "isotropic_permeability", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getLengthScale() * normalizer->getLengthScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["isotropic_permeability"] = info; + + // wellbore_radius + componentNames.resize(1); + componentNames[0] = "wellbore_radius"; + info.description = pylith::topology::Field::Description( + "wellbore_radius", + "wellbore_radius", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getLengthScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["wellbore_radius"] = info; + + // wellbore_length + componentNames.resize(1); + componentNames[0] = "wellbore_length"; + info.description = pylith::topology::Field::Description( + "wellbore_length", + "wellbore_length", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getLengthScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["wellbore_length"] = info; + + // wellbore_pressure + componentNames.resize(1); + componentNames[0] = "wellbore_pressure"; + info.description = pylith::topology::Field::Description( + "wellbore_pressure", + "wellbore_pressure", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getPressureScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["wellbore_pressure"] = info; + + // wellbore_character + componentNames.resize(1); + componentNames[0] = "wellbore_character"; + info.description = pylith::topology::Field::Description( + "wellbore_character", + "wellbore_character", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + 1, + NULL + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 0; + _data->subfields["wellbore_character"] = info; + + // element_dimensions + componentNames.resize(3); + componentNames[0] = "element_dimensions_x"; + componentNames[1] = "element_dimensions_y"; + componentNames[2] = "element_dimensions_z"; + + info.description = pylith::topology::Field::Description( + "element_dimensions", + "element_dimensions", + componentNames, + componentNames.size(), + pylith::topology::Field::TENSOR, + _data->normalizer->getLengthScale(), + pylith::topology::FieldQuery::validatorPositive + ); + info.fe = pylith::topology::Field::Discretization( + 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false + ); + info.index = 0; + _data->subfields["element_dimensions"] = info; + if (2 == _data->auxDim) { + _data->subfields["element_dimensions"].description.numComponents = 2; + _data->subfields["element_dimensions"].description.vectorFieldType = pylith::topology::Field::OTHER; + } // if + + // timeDelay + componentNames.resize(1); + componentNames[0] = "time_delay"; + info.description = pylith::topology::Field::Description( + "time_delay", + "time_delay", + componentNames, + componentNames.size(), + pylith::topology::Field::SCALAR, + _data->normalizer->getTimeScale(), + pylith::topology::FieldQuery::validatorNonnegative + ); + info.fe = pylith::topology::Field::Discretization( + 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true + ); + info.index = 1; + _data->subfields["time_delay"] = info; + + _initialize(); + + PYLITH_METHOD_END; +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor. +pylith::sources::TestAuxiliaryFactoryWellboreSource::~TestAuxiliaryFactoryWellboreSource(void) { + PYLITH_METHOD_BEGIN; + + delete _factory;_factory = NULL; + delete _data;_data = NULL; + delete _mesh;_mesh = NULL; + delete _auxiliaryField;_auxiliaryField = NULL; + + PYLITH_METHOD_END; +} // tearDown + + +// ------------------------------------------------------------------------------------------------ +// Test adding moment tensor and time delay subfields. +void +pylith::sources::TestAuxiliaryFactoryWellboreSource::testAdd(void) { + PYLITH_METHOD_BEGIN; + assert(_factory); + assert(_data); + + CHECK(!_auxiliaryField->hasSubfield("fluid_density")); + CHECK(!_auxiliaryField->hasSubfield("fluid_viscosity")); + CHECK(!_auxiliaryField->hasSubfield("isotropic_permeability")); + CHECK(!_auxiliaryField->hasSubfield("wellbore_radius")); + CHECK(!_auxiliaryField->hasSubfield("wellbore_length")); + CHECK(!_auxiliaryField->hasSubfield("wellbore_pressure")); + CHECK(!_auxiliaryField->hasSubfield("wellbore_character")); + CHECK(!_auxiliaryField->hasSubfield("element_dimensions")); + CHECK(!_auxiliaryField->hasSubfield("time_delay")); + + _factory->addFluidDensity(); + _factory->addFluidViscosity(); + _factory->addIsotropicPermeability(); + _factory->addWellboreRadius(); + _factory->addWellboreLength(); + _factory->addTimeDelay(); + _factory->addCenterFrequency(); + + assert(_data->normalizer); + + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["fluid_density"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["fluid_viscosity"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["isotropic_permeability"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_radius"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_length"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_pressure"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_character"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["element_dimensions"]); + pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); + + PYLITH_METHOD_END; +} // testAdd + + +// ------------------------------------------------------------------------------------------------ +// Test setValues(). +void +pylith::sources::TestAuxiliaryFactoryWellboreSource::testSetValuesFromDB(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + + _factory->addFluidDensity(); + _factory->addFluidViscosity(); + _factory->addIsotropicPermeability(); + _factory->addWellboreRadius(); + _factory->addWellboreLength(); + _factory->addWellborePressure(); + _factory->addWellboreCharacter(); + _factory->addElementDimensions(); + _factory->addTimeDelay(); + _auxiliaryField->subfieldsSetup(); + _auxiliaryField->createDiscretization(); + _auxiliaryField->allocate(); + + assert(_data); + assert(_data->normalizer); + _factory->setValuesFromDB(); + pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testSetValues + + +// ------------------------------------------------------------------------------------------------ +// Initialze mesh, coordinate system, auxiliary field, and factory. +void +pylith::sources::TestAuxiliaryFactoryWellboreSource::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_data); + + pylith::meshio::MeshIOAscii iohandler; + assert(_data->meshFilename); + iohandler.setFilename(_data->meshFilename); + _mesh = new pylith::topology::Mesh();assert(_mesh); + iohandler.read(_mesh); + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Setup coordinates. + _mesh->setCoordSys(_data->cs); + assert(_data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); + + _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); + _auxiliaryField->setLabel("auxiliary"); + + _factory = new AuxiliaryFactoryWellboreSource(); + assert(_data->auxiliaryDB); + _factory->setQueryDB(_data->auxiliaryDB); + typedef std::map::const_iterator subfield_iter; + for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { + const char* subfieldName = iter->first.c_str(); + const pylith::topology::Field::Discretization& fe = iter->second.fe; + _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, + fe.feSpace, fe.isBasisContinuous); + } // for + assert(_data->normalizer); + _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::TestAuxiliaryFactoryWellboreSource_Data(void) : + meshFilename(NULL), + cs(NULL), + normalizer(new spatialdata::units::Nondimensional), + auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::~TestAuxiliaryFactoryWellboreSource_Data(void) { + delete cs;cs = NULL; + delete normalizer;normalizer = NULL; + delete auxiliaryDB;auxiliaryDB = NULL; +} // testAdd + + +// ------------------------------------------------------------------------------------------------ +// Test setValues(). +void +pylith::sources::TestAuxiliaryFactoryWellboreSource::testSetValuesFromDB(void) { + PYLITH_METHOD_BEGIN; + + assert(_factory); + + _factory->addFluidDensity(); + _factory->addFluidViscosity(); + _factory->addIsotropicPermeability(); + _factory->addWellboreRadius(); + _factory->addWellboreLength(); + _factory->addWellborePressure(); + _factory->addWellboreCharacter(); + _factory->addElementDimensions(); + _factory->addTimeDelay(); + _auxiliaryField->subfieldsSetup(); + _auxiliaryField->createDiscretization(); + _auxiliaryField->allocate(); + + assert(_data); + assert(_data->normalizer); + _factory->setValuesFromDB(); + pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); + + PYLITH_METHOD_END; +} // testSetValues + + +// ------------------------------------------------------------------------------------------------ +// Initialze mesh, coordinate system, auxiliary field, and factory. +void +pylith::sources::TestAuxiliaryFactoryWellboreSource::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_data); + + pylith::meshio::MeshIOAscii iohandler; + assert(_data->meshFilename); + iohandler.setFilename(_data->meshFilename); + _mesh = new pylith::topology::Mesh();assert(_mesh); + iohandler.read(_mesh); + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Setup coordinates. + _mesh->setCoordSys(_data->cs); + assert(_data->normalizer); + pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); + + _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); + _auxiliaryField->setLabel("auxiliary"); + + _factory = new AuxiliaryFactoryWellboreSource(); + assert(_data->auxiliaryDB); + _factory->setQueryDB(_data->auxiliaryDB); + typedef std::map::const_iterator subfield_iter; + for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { + const char* subfieldName = iter->first.c_str(); + const pylith::topology::Field::Discretization& fe = iter->second.fe; + _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, + fe.feSpace, fe.isBasisContinuous); + } // for + assert(_data->normalizer); + _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::TestAuxiliaryFactoryWellboreSource_Data(void) : + meshFilename(NULL), + cs(NULL), + normalizer(new spatialdata::units::Nondimensional), + auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::~TestAuxiliaryFactoryWellboreSource_Data(void) { + delete cs;cs = NULL; + delete normalizer;normalizer = NULL; + delete auxiliaryDB;auxiliaryDB = NULL; +} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc new file mode 100644 index 0000000000..797822affe --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc @@ -0,0 +1,254 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of cases + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "spatialdata/geocoords/CSCart.hh" // USES CSCart +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "catch2/catch_test_macros.hpp" + +#include // USES fabs() + +// forward declarations +namespace pylith { + namespace sources { + class TestAuxiliaryFactorySourceTime_Cases; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactorySourceTime_Cases { +public: + + // Data factory methods + static TestAuxiliaryFactorySourceTime_Data* Tri(void); + + static TestAuxiliaryFactorySourceTime_Data* Hex(void); + +private: + + static + double fluid_density_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // fluid_density_2d + + static + const char* fluid_density_units(void) { + return "kg/m**3"; + } // fluid_density_units + + static + double fluid_viscosity_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // fluid_viscosity_2d + + static + const char* fluid_viscosity_units(void) { + return "Pa*s"; + } // fluid_viscosity_units + + static + double isotropic_permeability_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // isotropic_permeability_2d + + static + const char* isotropic_permeability_units(void) { + return "m**2"; + } // isotropic_permeability_units + + static + double wellbore_radius_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_radius_2d + + static + const char* wellbore_radius_units(void) { + return "m"; + } // wellbore_radius_units + + static + double wellbore_length_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_length_2d + + static + const char* wellbore_length_units(void) { + return "m"; + } // wellbore_length_units + + static + double wellbore_pressure_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_pressure_2d + + static + const char* wellbore_pressure_units(void) { + return "Pa"; + } // wellbore_pressure_units + + static + double wellbore_character_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_character_2d + + static + const char* wellbore_character_units(void) { + return "one"; + } // wellbore_character_units + + static + double time_delay_2d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // time_delay_2d + + static + const char* time_delay_units(void) { + return "s"; + } // time_delay_units + + static + double fluid_density_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // fluid_density_3d + + static + double fluid_viscosity_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // fluid_viscosity_3d + + static + double isotropic_permeability_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // isotropic_permeability_3d + + static + double wellbore_radius_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_radius_3d + + static + double wellbore_length_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_length_3d + + static + double wellbore_pressure_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_pressure_3d + + static + double wellbore_character_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // wellbore_character_2d + + static + double time_delay_3d(const double x, + const double y) { + return -0.3*x*x + 0.1*x*y; + } // time_delay_3d + +}; + +// ------------------------------------------------------------------------------------------------ +TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testSetValuesFromDB(); +} + +TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testAdd(); +} +TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testSetValuesFromDB(); +} + +// -------------------------------------------------------------------------------------------------------------------- +pylith::sources::TestAuxiliaryFactorySourceTime_Data* +pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri(void) { + pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); + assert(data); + + data->auxDim = 2; + data->dimension = 2; + data->meshFilename = "data/tri_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("fluid_density", fluid_density_2d, fluid_density_units()); + data->auxiliaryDB->addValue("fluid_viscosity", fluid_viscosity_2d, fluid_viscosity_units()); + data->auxiliaryDB->addValue("isotropic_permeability", moment_tensor_2d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); + data->auxiliaryDB->addValue("center_frequency", center_frequency_2d, frequency_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Tri + + +// ------------------------------------------------------------------------------------------------ +pylith::sources::TestAuxiliaryFactorySourceTime_Data* +pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex(void) { + pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); + assert(data); + + data->auxDim = 3; + data->dimension = 3; + data->meshFilename = "data/hex_onecell.mesh"; + data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); + data->cs->setSpaceDim(data->dimension); + + assert(data->auxiliaryDB); + data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); + data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); + data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); + data->auxiliaryDB->addValue("center_frequency", center_frequency_3d, frequency_units()); + data->auxiliaryDB->setDescription("auxiliary"); + data->auxiliaryDB->setCoordSys(*data->cs); + + return data; +} // Hex diff --git a/tests/pytests/sources/TestMomentTensorForce.py b/tests/pytests/sources/TestMomentTensorForce.py new file mode 100644 index 0000000000..269a1c2d82 --- /dev/null +++ b/tests/pytests/sources/TestMomentTensorForce.py @@ -0,0 +1,41 @@ +#!/usr/bin/env nemesis +# +# ====================================================================== +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ====================================================================== +# +# @file tests/pytests/sources/TestMomentTensorForce.py +# +# @brief Unit testing of Python TestMomentTensorForce object. + +import unittest + +from pylith.testing.UnitTestApp import TestComponent +from pylith.sources.Source import (MomentTensorForce, source) + + +class TestMomentTensorForce(TestComponent): + """Unit testing of MomentTensorForce object. + """ + _class = MomentTensorForce + _factory = source + + +if __name__ == "__main__": + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestMomentTensorForce)) + unittest.TextTestRunner(verbosity=2).run(suite) + + +# End of file diff --git a/tests/pytests/sources/TestPointForce.py b/tests/pytests/sources/TestPointForce.py index 722ea51b55..25004e97d9 100644 --- a/tests/pytests/sources/TestPointForce.py +++ b/tests/pytests/sources/TestPointForce.py @@ -26,7 +26,7 @@ class TestPointForce(TestComponent): - """Unit testing of Elasticity object. + """Unit testing of PointForce object. """ _class = PointForce _factory = source diff --git a/tests/pytests/sources/TestWellboreSource.py b/tests/pytests/sources/TestWellboreSource.py index cad8a4a8bb..64e66a6553 100644 --- a/tests/pytests/sources/TestWellboreSource.py +++ b/tests/pytests/sources/TestWellboreSource.py @@ -26,7 +26,7 @@ class TestWellboreSource(TestComponent): - """Unit testing of Elasticity object. + """Unit testing of WellboreSource object. """ _class = WellboreSource _factory = source From c793863b227830b5d558e62236711d4d8dc2b7e1 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 23 Nov 2023 10:54:38 -0700 Subject: [PATCH 21/65] Minor changes --- tests/libtests/sources/Makefile.am | 2 + .../TestAuxiliaryFactoryWellboreSource.cc | 3 +- .../TestAuxiliaryFactoryWellboreSource.hh | 110 ++++++++++++++++++ ...estAuxiliaryFactoryWellboreSource_Cases.cc | 40 +++---- 4 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am index 2c77df89ac..83dcec56b9 100644 --- a/tests/libtests/sources/Makefile.am +++ b/tests/libtests/sources/Makefile.am @@ -32,6 +32,8 @@ libtest_sources_SOURCES = \ TestAuxiliaryFactorySourceTime_Cases.cc \ TestAuxiliaryFactoryPointForce.cc \ TestAuxiliaryFactoryPointForce_Cases.cc \ + TestAuxiliaryFactoryWellboreSource.cc \ + TestAuxiliaryFactoryWellboreSource_Cases.cc \ $(top_srcdir)/tests/src/FieldTester.cc \ $(top_srcdir)/tests/src/driver_catch2.cc diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc index a6cc2dba6b..9e4f72c9b1 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc @@ -265,8 +265,9 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource::testAdd(void) { _factory->addIsotropicPermeability(); _factory->addWellboreRadius(); _factory->addWellboreLength(); + _factory->addWellboreCharacter(); + _factory->addElementDimensions(); _factory->addTimeDelay(); - _factory->addCenterFrequency(); assert(_data->normalizer); diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh new file mode 100644 index 0000000000..efe8897499 --- /dev/null +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// Robert L. Walker, Kegman, Inc. +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** + * @file tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh + * + * @brief C++ TestAuxiliaryFactoryWellboreSource object. + * + * C++ unit testing for AuxiliaryFactoryWellboreSource. + */ + +#if !defined(pylith_sources_testauxiliaryfactorywellboresource_hh) +#define pylith_sources_testauxiliaryfactorywellboresource_hh + +#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent + +#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryWellboreSource +#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo +#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB +#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys +#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional + +#include // USES std::map + +namespace pylith { + namespace sources { + class TestAuxiliaryFactoryWellboreSource; + class TestAuxiliaryFactoryWellboreSource_Data; + } // sources +} // pylith + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryWellboreSource : public pylith::utils::GenericComponent { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor. + TestAuxiliaryFactoryWellboreSource(TestAuxiliaryFactoryWellboreSource_Data* data); + + /// Destructor. + ~TestAuxiliaryFactoryWellboreSource(void); + + /// Test adding density, body force, and gravity subfields. + void testAdd(void); + + /// Test setValuesFromDB(). + void testSetValuesFromDB(void); + + // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// +protected: + + /// Initialze mesh, coordinate system, auxiliary field, and factory. + void _initialize(void); + + // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// +protected: + + AuxiliaryFactoryWellboreSource* _factory; ///< Test subject. + TestAuxiliaryFactoryWellboreSource_Data* _data; ///< Test data. + + pylith::topology::Mesh* _mesh; ///< Finite-element mesh. + pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. + +}; // class TestAuxiliaryFactoryWellboreSource + +// ------------------------------------------------------------------------------------------------ +class pylith::sources::TestAuxiliaryFactoryWellboreSource_Data { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + TestAuxiliaryFactoryWellboreSource_Data(void); + + /// Destructor + ~TestAuxiliaryFactoryWellboreSource_Data(void); + + // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// +public: + + size_t dimension; ///< Spatial dimension. + size_t auxDim; ///< Topological dimension of auxiliary field. + const char* meshFilename; ///< Name of file with ASCII mesh. + spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. + spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. + + std::map subfields; + spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. + spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. + +}; // class TestAuxiliaryFactoryWellboreSource_Data + +#endif // pylith_sources_testAuxiliaryFactoryWellboreSource_hh + +// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc index 797822affe..b55a649134 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc @@ -18,9 +18,9 @@ #include -#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of cases +#include "TestAuxiliaryFactoryWellboreSource.hh" // Implementation of cases -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // USES AuxiliaryFactoryWellboreSource #include "spatialdata/geocoords/CSCart.hh" // USES CSCart #include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional @@ -32,18 +32,18 @@ // forward declarations namespace pylith { namespace sources { - class TestAuxiliaryFactorySourceTime_Cases; + class TestAuxiliaryFactoryWellboreSource_Cases; } // sources } // pylith // ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactorySourceTime_Cases { +class pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases { public: // Data factory methods - static TestAuxiliaryFactorySourceTime_Data* Tri(void); + static TestAuxiliaryFactoryWellboreSource_Data* Tri(void); - static TestAuxiliaryFactorySourceTime_Data* Hex(void); + static TestAuxiliaryFactoryWellboreSource_Data* Hex(void); private: @@ -186,24 +186,24 @@ class pylith::sources::TestAuxiliaryFactorySourceTime_Cases { }; // ------------------------------------------------------------------------------------------------ -TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testAdd(); +TEST_CASE("TestAuxiliaryFactoryWellboreSource::Tri::testAdd", "[TestAuxiliaryFactoryWellboreSource][add]") { + pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri()).testAdd(); } -TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testSetValuesFromDB(); +TEST_CASE("TestAuxiliaryFactoryWellboreSource::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryWellboreSource][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri()).testSetValuesFromDB(); } -TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testAdd(); +TEST_CASE("TestAuxiliaryFactoryWellboreSource::Hex::testAdd", "[TestAuxiliaryFactoryWellboreSource][add]") { + pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex()).testAdd(); } -TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testSetValuesFromDB(); +TEST_CASE("TestAuxiliaryFactoryWellboreSource::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryWellboreSource][testSetValuesFromDB]") { + pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex()).testSetValuesFromDB(); } // -------------------------------------------------------------------------------------------------------------------- -pylith::sources::TestAuxiliaryFactorySourceTime_Data* -pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri(void) { - pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* +pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri(void) { + pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* data = new pylith::sources::TestAuxiliaryFactoryWellboreSource_Data(); assert(data); data->auxDim = 2; @@ -227,9 +227,9 @@ pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri(void) { // ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactorySourceTime_Data* -pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex(void) { - pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); +pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* +pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex(void) { + pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* data = new pylith::sources::TestAuxiliaryFactoryWellboreSource_Data(); assert(data); data->auxDim = 3; From 236ba383dac2f29f6120b9059b847dbf380f2dcb Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 2 Jan 2024 15:29:06 -0800 Subject: [PATCH 22/65] Cleanup of testing loose ends, still not passing source check. See that time delay is implemented across sources. --- libsrc/pylith/fekernels/Makefile.am | 2 - .../sources/AuxiliaryFactoryPointForce.cc | 29 +++++- .../sources/AuxiliaryFactoryPointForce.hh | 3 + .../AuxiliaryFactorySquarePulseSource.cc | 39 +++++++- .../AuxiliaryFactorySquarePulseSource.hh | 8 +- .../sources/AuxiliaryFactoryWellboreSource.cc | 27 ++++++ .../sources/AuxiliaryFactoryWellboreSource.hh | 3 + libsrc/pylith/sources/PointForce.cc | 1 + libsrc/pylith/sources/WellboreSource.cc | 1 + tests/libtests/sources/Makefile.am | 2 - .../sources/TestAuxiliaryFactoryPointForce.cc | 4 +- .../TestAuxiliaryFactoryWellboreSource.cc | 91 +------------------ ...estAuxiliaryFactoryWellboreSource_Cases.cc | 24 +++-- 13 files changed, 121 insertions(+), 113 deletions(-) diff --git a/libsrc/pylith/fekernels/Makefile.am b/libsrc/pylith/fekernels/Makefile.am index 3875836334..815273565f 100644 --- a/libsrc/pylith/fekernels/Makefile.am +++ b/libsrc/pylith/fekernels/Makefile.am @@ -31,8 +31,6 @@ subpkginclude_HEADERS = \ NeumannTimeDependent.hh \ AbsorbingDampers.hh \ FaultCohesiveKin.hh \ - IsotropicLinearPoroelasticity.hh \ - Poroelasticity.hh \ WellboreSource.hh \ SquarePulseSource.hh \ SquareWavelet.hh \ diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc index c941a40904..417dcdd42f 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc @@ -73,7 +73,34 @@ pylith::sources::AuxiliaryFactoryPointForce::addPointForce(void) { this->setSubfieldQuery(subfieldName); PYLITH_METHOD_END; -} // addFluidDensity +} // addPointForce + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryPointForce::addTimeDelay(void) { // timeDelay + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh index ac1b629624..93b3a446f1 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh @@ -44,6 +44,9 @@ public: /// Add point force subfield to auxiliary subfields. void addPointForce(void); + /// Add time delay subfield to auxiliary subfields. + void addTimeDelay(void); + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc index 9c0bae5953..f2cf200fdd 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc @@ -32,19 +32,20 @@ // --------------------------------------------------------------------------------------------------------------------- // Default constructor. -pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(void) -{ +pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(void) { GenericComponent::setName("auxiliaryfactorysquarepulsesource"); } // constructor + // --------------------------------------------------------------------------------------------------------------------- // Destructor. pylith::sources::AuxiliaryFactorySquarePulseSource::~AuxiliaryFactorySquarePulseSource(void) {} + // ---------------------------------------------------------------------- // Add fluid density subfield to auxiliary fields. -void pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) -{ // fluidDensity +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) { // fluidDensity PYLITH_METHOD_BEGIN; PYLITH_JOURNAL_DEBUG("addVolumeFlowRate(void)"); @@ -66,6 +67,34 @@ void pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) this->setSubfieldQuery(subfieldName); PYLITH_METHOD_END; -} // addFluidDensity +} // addVolumeFlowRate + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeDelay(void) { // timeDelay + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay + // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh index a008dcd541..2caa0c7f9d 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh +++ b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh @@ -29,12 +29,12 @@ #include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField -class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory -{ +class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory { friend class TestAuxiliaryFactorySquarePulseSource; // unit testing // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// public: + /// Default constructor. AuxiliaryFactorySquarePulseSource(void); @@ -44,8 +44,12 @@ public: /// Add fluid density subfield to auxiliary subfields. void addVolumeFlowRate(void); + /// Add time delay subfield to auxiliary subfields. + void addTimeDelay(void); + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: + AuxiliaryFactorySquarePulseSource(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented. const AuxiliaryFactorySquarePulseSource &operator=(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc index 5017d305a7..58d1373958 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc @@ -273,4 +273,31 @@ pylith::sources::AuxiliaryFactoryWellboreSource::addElementDimensions(void) { // } // addElementLength +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addTimeDelay(void) { // timeDelay + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay + + // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh index 061f7ab3a4..f22e013c2f 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh @@ -65,6 +65,9 @@ public: /// Add element dimensions subfield to auxiliary subfields. void addElementDimensions(void); + /// Add time delay subfield to auxiliary subfields. + void addTimeDelay(void); + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc index a445c7df8e..d3b4214795 100644 --- a/libsrc/pylith/sources/PointForce.cc +++ b/libsrc/pylith/sources/PointForce.cc @@ -166,6 +166,7 @@ pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field // add in aux specific to square pulse _auxiliaryFactory->addPointForce(); // 0 + _auxiliaryFactory->addTimeDelay(); // 1 assert(_auxiliaryFactory); _auxiliaryFactory->setValuesFromDB(); diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc index 3518300383..62f7f56f5f 100644 --- a/libsrc/pylith/sources/WellboreSource.cc +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -175,6 +175,7 @@ pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Fi _auxiliaryFactory->addWellborePressure(); // 5 _auxiliaryFactory->addWellboreCharacter(); // 6 _auxiliaryFactory->addElementDimensions(); // 7 + _auxiliaryFactory->addTimeDelay(); // 8 auxiliaryField->subfieldsSetup(); auxiliaryField->createDiscretization(); diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am index 83dcec56b9..2c77df89ac 100644 --- a/tests/libtests/sources/Makefile.am +++ b/tests/libtests/sources/Makefile.am @@ -32,8 +32,6 @@ libtest_sources_SOURCES = \ TestAuxiliaryFactorySourceTime_Cases.cc \ TestAuxiliaryFactoryPointForce.cc \ TestAuxiliaryFactoryPointForce_Cases.cc \ - TestAuxiliaryFactoryWellboreSource.cc \ - TestAuxiliaryFactoryWellboreSource_Cases.cc \ $(top_srcdir)/tests/src/FieldTester.cc \ $(top_srcdir)/tests/src/driver_catch2.cc diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc index 9deaaf8aad..37be72e7c8 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc @@ -124,7 +124,7 @@ pylith::sources::TestAuxiliaryFactoryPointForce::testAdd(void) { CHECK(!_auxiliaryField->hasSubfield("point_force")); CHECK(!_auxiliaryField->hasSubfield("time_delay")); - _factory->addMomentTensor(); + _factory->addPointForce(); _factory->addTimeDelay(); assert(_data->normalizer); @@ -144,7 +144,7 @@ pylith::sources::TestAuxiliaryFactoryPointForce::testSetValuesFromDB(void) { assert(_factory); - _factory->addMomentTensor(); + _factory->addPointForce(); _factory->addTimeDelay(); _auxiliaryField->subfieldsSetup(); _auxiliaryField->createDiscretization(); diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc index 9e4f72c9b1..f4111e96d6 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc @@ -80,7 +80,7 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource::TestAuxiliaryFactoryWellbor componentNames, componentNames.size(), pylith::topology::Field::SCALAR, - _data->normalizer->getViscosityScale(), + _data->normalizer->getPressureScale() * _data->normalizer->getTimeScale(), pylith::topology::FieldQuery::validatorPositive ); info.fe = pylith::topology::Field::Discretization( @@ -98,7 +98,7 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource::TestAuxiliaryFactoryWellbor componentNames, componentNames.size(), pylith::topology::Field::SCALAR, - _data->normalizer->getLengthScale() * normalizer->getLengthScale(), + _data->normalizer->getLengthScale() * _data->normalizer->getLengthScale(), pylith::topology::FieldQuery::validatorPositive ); info.fe = pylith::topology::Field::Discretization( @@ -370,90 +370,3 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::~TestAuxiliaryFactoryW delete normalizer;normalizer = NULL; delete auxiliaryDB;auxiliaryDB = NULL; } // testAdd - - -// ------------------------------------------------------------------------------------------------ -// Test setValues(). -void -pylith::sources::TestAuxiliaryFactoryWellboreSource::testSetValuesFromDB(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - - _factory->addFluidDensity(); - _factory->addFluidViscosity(); - _factory->addIsotropicPermeability(); - _factory->addWellboreRadius(); - _factory->addWellboreLength(); - _factory->addWellborePressure(); - _factory->addWellboreCharacter(); - _factory->addElementDimensions(); - _factory->addTimeDelay(); - _auxiliaryField->subfieldsSetup(); - _auxiliaryField->createDiscretization(); - _auxiliaryField->allocate(); - - assert(_data); - assert(_data->normalizer); - _factory->setValuesFromDB(); - pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testSetValues - - -// ------------------------------------------------------------------------------------------------ -// Initialze mesh, coordinate system, auxiliary field, and factory. -void -pylith::sources::TestAuxiliaryFactoryWellboreSource::_initialize(void) { - PYLITH_METHOD_BEGIN; - assert(_data); - - pylith::meshio::MeshIOAscii iohandler; - assert(_data->meshFilename); - iohandler.setFilename(_data->meshFilename); - _mesh = new pylith::topology::Mesh();assert(_mesh); - iohandler.read(_mesh); - - assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); - assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); - - // Setup coordinates. - _mesh->setCoordSys(_data->cs); - assert(_data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); - - _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); - _auxiliaryField->setLabel("auxiliary"); - - _factory = new AuxiliaryFactoryWellboreSource(); - assert(_data->auxiliaryDB); - _factory->setQueryDB(_data->auxiliaryDB); - typedef std::map::const_iterator subfield_iter; - for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { - const char* subfieldName = iter->first.c_str(); - const pylith::topology::Field::Discretization& fe = iter->second.fe; - _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, - fe.feSpace, fe.isBasisContinuous); - } // for - assert(_data->normalizer); - _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); - - PYLITH_METHOD_END; -} // _initialize - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::TestAuxiliaryFactoryWellboreSource_Data(void) : - meshFilename(NULL), - cs(NULL), - normalizer(new spatialdata::units::Nondimensional), - auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::~TestAuxiliaryFactoryWellboreSource_Data(void) { - delete cs;cs = NULL; - delete normalizer;normalizer = NULL; - delete auxiliaryDB;auxiliaryDB = NULL; -} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc index b55a649134..617e1ef8e5 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc @@ -215,10 +215,13 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri(void) { assert(data->auxiliaryDB); data->auxiliaryDB->addValue("fluid_density", fluid_density_2d, fluid_density_units()); data->auxiliaryDB->addValue("fluid_viscosity", fluid_viscosity_2d, fluid_viscosity_units()); - data->auxiliaryDB->addValue("isotropic_permeability", moment_tensor_2d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); + data->auxiliaryDB->addValue("isotropic_permeability", isotropic_permeability_2d, isotropic_permeability_units()); + data->auxiliaryDB->addValue("wellbore_radius", wellbore_radius_2d, wellbore_radius_units()); + data->auxiliaryDB->addValue("wellbore_length", wellbore_length_2d, wellbore_length_units()); + data->auxiliaryDB->addValue("wellbore_pressure", wellbore_pressure_2d, wellbore_pressure_units()); + data->auxiliaryDB->addValue("wellbore_character", wellbore_character_2d, wellbore_character_units radius_units()); + data->auxiliaryDB->addValue("element_dimensions", element_dimensions_2d, element_dimensions_units()); data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); - data->auxiliaryDB->addValue("center_frequency", center_frequency_2d, frequency_units()); data->auxiliaryDB->setDescription("auxiliary"); data->auxiliaryDB->setCoordSys(*data->cs); @@ -239,14 +242,15 @@ pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex(void) { data->cs->setSpaceDim(data->dimension); assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); + data->auxiliaryDB->addValue("fluid_density", fluid_density_3d, fluid_density_units()); + data->auxiliaryDB->addValue("fluid_viscosity", fluid_viscosity_3d, fluid_viscosity_units()); + data->auxiliaryDB->addValue("isotropic_permeability", isotropic_permeability_3d, isotropic_permeability_units()); + data->auxiliaryDB->addValue("wellbore_radius", wellbore_radius_3d, wellbore_radius_units()); + data->auxiliaryDB->addValue("wellbore_length", wellbore_length_3d, wellbore_length_units()); + data->auxiliaryDB->addValue("wellbore_pressure", wellbore_pressure_3d, wellbore_pressure_units()); + data->auxiliaryDB->addValue("wellbore_character", wellbore_character_3d, wellbore_character_units radius_units()); + data->auxiliaryDB->addValue("element_dimensions", element_dimensions_3d, element_dimensions_units()); data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); - data->auxiliaryDB->addValue("center_frequency", center_frequency_3d, frequency_units()); data->auxiliaryDB->setDescription("auxiliary"); data->auxiliaryDB->setCoordSys(*data->cs); From 77db4ad26c772d1c9924000baacc8ad378dd722e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 4 Jan 2024 18:55:01 -0700 Subject: [PATCH 23/65] added point force header to makefile --- tests/libtests/sources/Makefile.am | 3 ++- tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc | 3 ++- tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am index 2c77df89ac..151014e900 100644 --- a/tests/libtests/sources/Makefile.am +++ b/tests/libtests/sources/Makefile.am @@ -38,7 +38,8 @@ libtest_sources_SOURCES = \ dist_noinst_HEADERS = \ TestAuxiliaryFactoryMomentTensorForce.hh \ - TestAuxiliaryFactorySourceTime.hh + TestAuxiliaryFactorySourceTime.hh \ + TestAuxiliaryFactoryPointForce.hh # End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc index 37be72e7c8..b8468ac9fc 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc @@ -114,10 +114,11 @@ pylith::sources::TestAuxiliaryFactoryPointForce::~TestAuxiliaryFactoryPointForce // ------------------------------------------------------------------------------------------------ -// Test adding moment tensor and time delay subfields. +// Test adding point force and time delay subfields. void pylith::sources::TestAuxiliaryFactoryPointForce::testAdd(void) { PYLITH_METHOD_BEGIN; + assert(_factory); assert(_data); diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh index 6e7bc371c0..36c8f52d04 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh @@ -56,7 +56,7 @@ public: /// Destructor. ~TestAuxiliaryFactoryPointForce(void); - /// Test adding density, body force, and gravity subfields. + /// Test adding subfields. void testAdd(void); /// Test setValuesFromDB(). From ef6d3cf6ff259297e1eb6c2338f7de67781b701e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Mon, 15 Jan 2024 22:37:53 -0800 Subject: [PATCH 24/65] Point Force libtest fails on factory assertion --- libsrc/pylith/sources/PointForce.cc | 7 +++---- libsrc/pylith/sources/PointForce.hh | 1 - .../sources/TestAuxiliaryFactoryMomentTensorForce.cc | 1 - .../sources/TestAuxiliaryFactoryMomentTensorForce.hh | 1 - tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc | 1 - tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh | 1 - 6 files changed, 3 insertions(+), 9 deletions(-) diff --git a/libsrc/pylith/sources/PointForce.cc b/libsrc/pylith/sources/PointForce.cc index d3b4214795..bbd9ac7d75 100644 --- a/libsrc/pylith/sources/PointForce.cc +++ b/libsrc/pylith/sources/PointForce.cc @@ -44,7 +44,7 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- // Default constructor. -pylith::sources::PointForce::PointForce(void) : _useInertia(false), +pylith::sources::PointForce::PointForce(void) : _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryPointForce) { pylith::utils::PyreComponent::setName("pointforce"); } // constructor @@ -143,13 +143,13 @@ pylith::sources::PointForce::createIntegrator(const pylith::topology::Field &sol // --------------------------------------------------------------------------------------------------------------------- // Create auxiliary field. -pylith::topology::Field * +pylith::topology::Field* pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field &solution, const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); - pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); + pylith::topology::Field* auxiliaryField = new pylith::topology::Field(domainMesh); assert(auxiliaryField); auxiliaryField->setLabel("PointForce auxiliary field"); @@ -164,7 +164,6 @@ pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field // acceleration will have a scale of pressure divided by length and should be within a few orders // of magnitude of 1. - // add in aux specific to square pulse _auxiliaryFactory->addPointForce(); // 0 _auxiliaryFactory->addTimeDelay(); // 1 diff --git a/libsrc/pylith/sources/PointForce.hh b/libsrc/pylith/sources/PointForce.hh index 085e24171d..c9eaa614e7 100644 --- a/libsrc/pylith/sources/PointForce.hh +++ b/libsrc/pylith/sources/PointForce.hh @@ -132,7 +132,6 @@ private: // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: - bool _useInertia; ///< Flag to include inertial term. spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. pylith::sources::AuxiliaryFactoryPointForce *_auxiliaryFactory; ///< Factory for auxiliary subfields. diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc index bda73860f4..dc233c1c0b 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc @@ -31,7 +31,6 @@ #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField #include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh index 0d9080b53d..795dcc090f 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh @@ -101,7 +101,6 @@ public: std::map subfields; spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. }; // class TestAuxiliaryFactoryMomentTensorForce_Data diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc index b8468ac9fc..114b32139f 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc @@ -32,7 +32,6 @@ #include "pylith/utils/journals.hh" // USES pythia::journal::debug_t #include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField #include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh index 36c8f52d04..e26d5fe05d 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh @@ -101,7 +101,6 @@ public: std::map subfields; spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. }; // class TestAuxiliaryFactoryPointForce_Data From 1d8421db17761743293f2c9b2ea2f1b2b80655a0 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 17 Jan 2024 14:06:05 -0800 Subject: [PATCH 25/65] Libtests pass, moving to implement timehistorydb --- .../sources/AuxiliaryFactoryPointForce.cc | 4 +- libsrc/pylith/sources/TimeHistoryWavelet.cc | 121 ++++++++++++++++++ libsrc/pylith/sources/TimeHistoryWavelet.hh | 82 ++++++++++++ .../sources/TestAuxiliaryFactoryPointForce.cc | 4 +- .../TestAuxiliaryFactoryPointForce_Cases.cc | 6 +- 5 files changed, 211 insertions(+), 6 deletions(-) create mode 100644 libsrc/pylith/sources/TimeHistoryWavelet.cc create mode 100644 libsrc/pylith/sources/TimeHistoryWavelet.hh diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc index 417dcdd42f..3979f010d7 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc @@ -60,14 +60,14 @@ pylith::sources::AuxiliaryFactoryPointForce::addPointForce(void) { pylith::topology::Field::Description description; description.label = subfieldName; description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::VECTOR; + description.vectorFieldType = (3 == _spaceDim) ? pylith::topology::Field::VECTOR : pylith::topology::Field::OTHER; description.numComponents = _spaceDim; description.componentNames.resize(_spaceDim); for (int i = 0; i < _spaceDim; ++i) { description.componentNames[i] = componentNames[i]; } // for description.scale = pressureScale; - description.validator = pylith::topology::FieldQuery::validatorPositive; + description.validator = NULL; _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc new file mode 100644 index 0000000000..7e6c3df5ee --- /dev/null +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -0,0 +1,121 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/TimeHistoryWavelet.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/fekernels/TimeHistoryWavelet.hh" // USES TimeHistoryWavelet kernels +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::TimeHistoryWavelet::TimeHistoryWavelet(void) : + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + pylith::utils::PyreComponent::setName("timehistorywavelet"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::TimeHistoryWavelet::~TimeHistoryWavelet(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void +pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); + + _dbTimeHistory = th; +} // setTimeHistoryDB + + +// --------------------------------------------------------------------------------------------------------------------- +// Get time history database. +const spatialdata::spatialdb::TimeHistory * +pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { + return _dbTimeHistory; +} // getTimeHistoryDB + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::TimeHistoryWavelet::deallocate(void) { + SourceTimeFunctionMomentTensorForce::deallocate(); + + delete _auxiliaryFactory;_auxiliaryFactory = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::sources::AuxiliaryFactoryMomentTensorForce* +pylith::sources::TimeHistoryWavelet::getAuxiliaryFactory(void) { + return _auxiliaryFactory; +} // getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Add source time subfields to auxiliary field. +void +pylith::sources::TimeHistoryWavelet::addAuxiliarySubfields(void) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("addAuxiliarySubfields(void)"); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise + // functions (kernels). + + _auxiliaryFactory->addCenterFrequency(); // numA - 1 + _auxiliaryFactory->addTimeHistoryAmplitude(); + _auxiliaryFactory->addTimeHistoryStartTime(); + _auxiliaryFactory->addTimeHistoryValue(); + if (_dbTimeHistory) { + _dbTimeHistory->open(); + } // if + PYLITH_METHOD_END; +} // addAuxiliarySubfields + + +// --------------------------------------------------------------------------------------------------------------------- +// Get g1v kernel for residual, G(t,s). +PetscPointFunc +pylith::sources::TimeHistoryWavelet::getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("getKernelg1v_explicit(coordsys="<getSpaceDim(); + PetscPointFunc g1v = + (3 == spaceDim) ? pylith::fekernels::TimeHistoryWavelet3D::g1v : + (2 == spaceDim) ? pylith::fekernels::TimeHistoryWaveletPlaneStrain::g1v : + NULL; + + PYLITH_METHOD_RETURN(g1v); +} // getKernelResidualStress + + +// End of file diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh new file mode 100644 index 0000000000..f3446c5e7b --- /dev/null +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -0,0 +1,82 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/TimeHistoryWavelet.hh + * + * @brief C++ class for Ricker source time function. + */ + +#if !defined(pylith_materials_timehistorywavelet_hh) +#define pylith_materials_timehistorywavelet_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // ISA SourceTimeFunctionMomentTensorForce + +class pylith::sources::TimeHistoryWavelet : public pylith::sources::SourceTimeFunctionMomentTensorForce { + friend class TestTimeHistoryWavelet; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + TimeHistoryWavelet(void); + + /// Destructor. + ~TimeHistoryWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v. + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. + pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + TimeHistoryWavelet(const TimeHistoryWavelet&); ///< Not implemented. + const TimeHistoryWavelet& operator=(const TimeHistoryWavelet&); /// Not implemented. + +}; // class TimeHistoryWavelet + +#endif // pylith_materials_timehistorywavelet_hh + +// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc index 114b32139f..c9f3e3cb8c 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc @@ -52,7 +52,7 @@ pylith::sources::TestAuxiliaryFactoryPointForce::TestAuxiliaryFactoryPointForce( pylith::topology::Field::SubfieldInfo info; pylith::string_vector componentNames; - // momentTensor + // pointForce componentNames.resize(3); componentNames[0] = "point_force_x"; componentNames[1] = "point_force_y"; @@ -94,6 +94,8 @@ pylith::sources::TestAuxiliaryFactoryPointForce::TestAuxiliaryFactoryPointForce( info.index = 1; _data->subfields["time_delay"] = info; + _initialize(); + PYLITH_METHOD_END; } // constructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc index 65ae75d12a..8371f47b82 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc @@ -50,19 +50,19 @@ class pylith::sources::TestAuxiliaryFactoryPointForce_Cases { static double point_force_2d_x(const double x, const double y) { - return -0.3*x*x + 0.1*x*y; + return 0.3*x*x + 0.1*x*y; } // point_force_2d_x static double point_force_2d_y(const double x, const double y) { - return -0.8*x*y + 0.2*y*y; + return 0.8*x*y + 0.2*y*y; } // point_force_2d_yy static double point_force_2d_z(const double x, const double y) { - return -0.3*x*x + 0.5*y*y; + return 0.3*x*x + 0.5*y*y; } // point_force_2d_z static From 769945989e7c887843684b28cff07b7cd12e625d Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Sun, 4 Feb 2024 17:31:26 -0800 Subject: [PATCH 26/65] Added change to allow moment tensor force STFs to use time history db --- libsrc/pylith/Makefile.am | 2 +- libsrc/pylith/fekernels/RickerWavelet.hh | 68 +++- libsrc/pylith/fekernels/TimeHistoryWavelet.hh | 168 ++++++++ .../sources/AuxiliaryFactorySourceTime.cc | 116 ++++++ .../sources/AuxiliaryFactorySourceTime.hh | 22 ++ libsrc/pylith/sources/GaussianWavelet.cc | 1 + libsrc/pylith/sources/Makefile.am | 1 + libsrc/pylith/sources/MomentTensorForce.cc | 60 ++- libsrc/pylith/sources/MomentTensorForce.hh | 35 ++ libsrc/pylith/sources/RickerWavelet.cc | 1 + libsrc/pylith/sources/SquareWavelet.cc | 1 + .../sources/TimeDependentAuxiliaryFactory.cc | 365 ++++++++++++++++++ .../sources/TimeDependentAuxiliaryFactory.hh | 110 ++++++ libsrc/pylith/sources/TimeHistoryWavelet.cc | 12 +- libsrc/pylith/sources/TimeHistoryWavelet.hh | 12 + libsrc/pylith/sources/sourcesfwd.hh | 1 + 16 files changed, 963 insertions(+), 12 deletions(-) create mode 100644 libsrc/pylith/fekernels/TimeHistoryWavelet.hh create mode 100644 libsrc/pylith/sources/TimeDependentAuxiliaryFactory.cc create mode 100644 libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index 1331ee1b6f..a457f6c93d 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -73,7 +73,6 @@ libpylith_la_SOURCES = \ fekernels/SquareWavelet.cc \ fekernels/GaussianWavelet.cc \ fekernels/PointForce.cc \ - fekernels/RickerWavelet.cc \ fekernels/SquarePulseSource.cc \ fekernels/WellboreSource.cc \ materials/Material.cc \ @@ -146,6 +145,7 @@ libpylith_la_SOURCES = \ sources/PointForce.cc \ sources/SquareWavelet.cc \ sources/RickerWavelet.cc \ + sources/TimeHistoryWavelet.cc \ sources/Source.cc \ sources/SourceTimeFunctionMomentTensorForce.cc \ sources/SquarePulseSource.cc \ diff --git a/libsrc/pylith/fekernels/RickerWavelet.hh b/libsrc/pylith/fekernels/RickerWavelet.hh index b332240837..7c31cd57d2 100644 --- a/libsrc/pylith/fekernels/RickerWavelet.hh +++ b/libsrc/pylith/fekernels/RickerWavelet.hh @@ -28,6 +28,8 @@ #include "pylith/utils/types.hh" +#include // USES assert() + // ===================================================================================================================== // Kernels for the Ricker Source Time Function in 2D. // ===================================================================================================================== @@ -79,7 +81,40 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 2; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_rickerwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; + + // RickerWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * rickerwavelet; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); + } // for + } // g1v }; // RickerWaveletPlaneStrain @@ -116,7 +151,7 @@ public: /** g1 function for velocity equation * */ - static + static inline void g1v(const PylithInt dim, const PylithInt numS, const PylithInt numA, @@ -134,7 +169,34 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_rickerwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; + + // RickerWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * rickerwavelet; + } // for + } // g1v }; // RickerWaveletPlaneStrain diff --git a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh new file mode 100644 index 0000000000..b5330088e2 --- /dev/null +++ b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh @@ -0,0 +1,168 @@ +/* -*- C++ -*- + * + * ---------------------------------------------------------------------- + * + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- + */ + +/** @file libsrc/fekernels/TimeHistoryWavelet.hh + * + */ + +#if !defined(pylith_fekernels_rickerwavelet_hh) +#define pylith_fekernels_rickerwavelet_hh + +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations + +#include "pylith/utils/types.hh" + +// ===================================================================================================================== +// Kernels for the TimeHistory Source Time Function in 2D. +// ===================================================================================================================== + +class pylith::fekernels::TimeHistoryWaveletPlaneStrain { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]); + +}; // TimeHistoryWaveletPlaneStrain + +// ===================================================================================================================== +// Kernels for the TimeHistory Source Time Function in 3D. +// ===================================================================================================================== + +class pylith::fekernels::TimeHistoryWavelet3D { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + /** g1 function for velocity equation + * + */ + static inline + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; + + // TimeHistoryWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * + PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * rickerwavelet; + } // for + } // g1v + +}; // g1v + +#endif /* pylith_fekernels_rickerwavelet_hh */ + +/* End of file */ diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index 39b040f9db..da630e1090 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -22,7 +22,9 @@ #include "pylith/topology/Field.hh" // USES Field #include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include "pylith/utils/error.hh" // USES PYLITH_METHOD* @@ -69,4 +71,118 @@ pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { // cente } // addCenterFrequency +// --------------------------------------------------------------------------------------------------------------------- +// Add time history start time field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); + + const char* subfieldName = "time_history_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history value field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryValue(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); + + const char* subfieldName = "time_history_value"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); + // No subfield query; populated by integrator or constraint at beginning of time step. + + PYLITH_METHOD_END; +} // addTimeHistoryValue + + +// --------------------------------------------------------------------------------------------------------------------- +void +pylith::sources::AuxiliaryFactorySourceTime::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { + PYLITH_METHOD_BEGIN; + // pythia::journal::debug_t debug(_TimeDependentAuxiliaryFactory::genericComponent); + // debug << pythia::journal::at(__HERE__) + // << "TimeDependentAuxiliaryFactory::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); + pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); + PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); + + // Compute offset of time history subfields in auxiliary field. + const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; + const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; + + // Loop over all points in section. + for (PetscInt p = pStart; p < pEnd; ++p) { + // Skip points without values in section. + if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} + + // Get starting time and compute relative time for point. + const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); + const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; + const PylithScalar tRel = t - tStart; + + // Query time history for value (normalized amplitude). + PylithScalar value = 0.0; + if (tRel >= 0.0) { + PylithScalar tDim = tRel * timeScale; + const int err = dbTimeHistory->query(&value, tDim); + if (err) { + std::ostringstream msg; + msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; + throw std::runtime_error(msg.str()); + } // if + } // if + + // Update value (normalized amplitude) in auxiliary field. + const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); + auxiliaryFieldArray[offValue] = value; + } // for + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh index 08e63de7ce..fef8ad3759 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.hh @@ -42,6 +42,28 @@ public: /// Add center frequency subfield to auxiliary subfields. void addCenterFrequency(void); + /// Add time history amplitude field to auxiliary fields. + void addTimeHistoryAmplitude(void); + + /// Add time history start time field to auxiliary fields. + void addTimeHistoryStartTime(void); + + /// Add time history value field to auxiliary fields. + void addTimeHistoryValue(void); + + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + * @param[in] dbTimeHistory Time history database. + */ + static + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory); + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/GaussianWavelet.cc b/libsrc/pylith/sources/GaussianWavelet.cc index 6ec4ab138a..96799b9cf7 100644 --- a/libsrc/pylith/sources/GaussianWavelet.cc +++ b/libsrc/pylith/sources/GaussianWavelet.cc @@ -72,6 +72,7 @@ pylith::sources::GaussianWavelet::addAuxiliarySubfields(void) { // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise // functions (kernels). + _auxiliaryFactory->addTimeDelay(); // numA - 2 _auxiliaryFactory->addCenterFrequency(); // numA - 1 PYLITH_METHOD_END; diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index 9af94918f1..f21b17b055 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -32,6 +32,7 @@ subpkginclude_HEADERS = \ SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ + TimeHistoryWavelet.hh \ PointForce.hh \ AuxiliaryFactoryPointForce.hh \ SourceTimeFunctionMomentTensorForce.hh \ diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 4a32c8d822..8030ed4d66 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -20,6 +20,7 @@ #include "pylith/sources/MomentTensorForce.hh" // implementation of object methods +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime #include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // HASA SourceTimeFunctionMomentTensorSource #include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce #include "pylith/sources/DerivedFactoryMomentTensorForce.hh" // USES DerivedFactoryMomentTensorForce @@ -28,6 +29,7 @@ #include "pylith/topology/Field.hh" // USES Field::SubfieldInfo #include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/fekernels/DispVel.hh" // USES DispVel kernels +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* @@ -47,7 +49,8 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // Default constructor. pylith::sources::MomentTensorForce::MomentTensorForce(void) : _sourceTimeFunction(NULL), - _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce) { + _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce), + _useTimeHistory(false) { pylith::utils::PyreComponent::setName("momenttensorforce"); } // constructor @@ -70,6 +73,42 @@ pylith::sources::MomentTensorForce::deallocate(void) { } // deallocate +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void +pylith::sources::MomentTensorForce::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th) { + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th"<addMomentTensor(); // 0 - auxiliaryFactory->addTimeDelay(); // 1 _sourceTimeFunction->addAuxiliarySubfields(); @@ -164,6 +202,24 @@ pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology: } // createAuxiliaryField +// --------------------------------------------------------------------------------------------------------------------- +// Update auxiliary subfields at beginning of time step. +void +pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const double t) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField="<getTimeScale(); + AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); + } // if + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + // --------------------------------------------------------------------------------------------------------------------- // Create derived field. pylith::topology::Field* diff --git a/libsrc/pylith/sources/MomentTensorForce.hh b/libsrc/pylith/sources/MomentTensorForce.hh index 0f83b6fe1d..6beaa55341 100644 --- a/libsrc/pylith/sources/MomentTensorForce.hh +++ b/libsrc/pylith/sources/MomentTensorForce.hh @@ -61,6 +61,30 @@ public: */ void verifyConfiguration(const pylith::topology::Field& solution) const; + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + /** Create integrator and set kernels. * * @param[in] solution Solution field. @@ -79,6 +103,14 @@ public: pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, const pylith::topology::Mesh& domainMesh); + /** Update auxiliary subfields at beginning of time step. + * + * @param[out] auxiliaryField Auxiliary field. + * @param[in] t Current time. + */ + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const double t); + /** Create derived field. * * @param[in] solution Solution field. @@ -151,6 +183,9 @@ private: pylith::sources::SourceTimeFunctionMomentTensorForce* _sourceTimeFunction; ///< Source time function for ///< momenttensor force. pylith::sources::DerivedFactoryMomentTensorForce* _derivedFactory; ///< Factory for creating derived fields. + spatialdata::spatialdb::TimeHistory* _dbTimeHistory; ///< Time history database. + + bool _useTimeHistory; ///< Use time history term. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/RickerWavelet.cc b/libsrc/pylith/sources/RickerWavelet.cc index 97f8c1cf39..410e8487f9 100644 --- a/libsrc/pylith/sources/RickerWavelet.cc +++ b/libsrc/pylith/sources/RickerWavelet.cc @@ -72,6 +72,7 @@ pylith::sources::RickerWavelet::addAuxiliarySubfields(void) { // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise // functions (kernels). + _auxiliaryFactory->addTimeDelay(); // numA - 2 _auxiliaryFactory->addCenterFrequency(); // numA - 1 PYLITH_METHOD_END; diff --git a/libsrc/pylith/sources/SquareWavelet.cc b/libsrc/pylith/sources/SquareWavelet.cc index 027cea68d7..8036ff386d 100644 --- a/libsrc/pylith/sources/SquareWavelet.cc +++ b/libsrc/pylith/sources/SquareWavelet.cc @@ -72,6 +72,7 @@ pylith::sources::SquareWavelet::addAuxiliarySubfields(void) { // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise // functions (kernels). + _auxiliaryFactory->addTimeDelay(); // numA - 2 _auxiliaryFactory->addCenterFrequency(); // numA - 1 PYLITH_METHOD_END; diff --git a/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.cc b/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.cc new file mode 100644 index 0000000000..73a4559a05 --- /dev/null +++ b/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.cc @@ -0,0 +1,365 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "TimeDependentAuxiliaryFactory.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // HOLDSA AuxiliaryField +#include "pylith/topology/FieldQuery.hh" // USES FieldQuery +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh + +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +namespace pylith { + namespace sources { + class _TimeDependentAuxiliaryFactory { +public: + + ///< Names of field components in XYZ coordinate system. + static const char* componentsXYZ[3]; + + ///< Names of field components in 2-D tangential/normal coordinate system. + static const char* componentsTN[2]; + + ///< Names of field components in 3-D tangential/normal coordinate system. + static const char* componentsTTN[3]; + + static const char* genericComponent; + }; // _TimeDependentAuxiliaryFactory + + const char* _TimeDependentAuxiliaryFactory::componentsXYZ[3] = { "_x", "_y", "_z" }; + const char* _TimeDependentAuxiliaryFactory::componentsTN[2] = { "_tangential", "_normal" }; + const char* _TimeDependentAuxiliaryFactory::componentsTTN[3] = { "_tangential_1", "_tangential_2", "_normal" }; + + const char* _TimeDependentAuxiliaryFactory::genericComponent = "timedependentauxiliaryfactory"; + } // sources +} // pylith + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::TimeDependentAuxiliaryFactory::TimeDependentAuxiliaryFactory(const ReferenceEnum reference) : + _auxComponents(reference) { + GenericComponent::setName(_TimeDependentAuxiliaryFactory::genericComponent); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::TimeDependentAuxiliaryFactory::~TimeDependentAuxiliaryFactory(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Set names of vector components in auxiliary subfield. +void +pylith::sources::TimeDependentAuxiliaryFactory::_setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("_setVectorFieldComponentNames(description)"); + + assert(description); + + const char** componentNames = NULL; + if (XYZ == _auxComponents) { + componentNames = _TimeDependentAuxiliaryFactory::componentsXYZ; + } else if (TANGENTIAL_NORMAL == _auxComponents) { + if (2 == _spaceDim) { + componentNames = _TimeDependentAuxiliaryFactory::componentsTN; + } else if (3 == _spaceDim) { + componentNames = _TimeDependentAuxiliaryFactory::componentsTTN; + } // if/else + } // if/else + if (!componentNames) { + PYLITH_JOURNAL_ERROR("Unknown case for auxiliary component reference ("<<_auxComponents<<") and spatial dimension ("<<_spaceDim<<")."); + throw std::logic_error("Unknown case for auxiliary component reference and spatial dimension."); + } // if + + assert(size_t(_spaceDim) == description->numComponents); + for (int i = 0; i < _spaceDim; ++i) { + description->componentNames[i] = description->label + std::string(componentNames[i]); + } // for + + PYLITH_METHOD_END; +} // _setVectorFieldComponentNames + + +// --------------------------------------------------------------------------------------------------------------------- +// Add initial amplitude field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addInitialAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addInitialAmplitude(void)"); + + const char* subfieldName = "initial_amplitude"; + + assert(_defaultDescription); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.validator = NULL; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::initialAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addInitialAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add rate amplitude field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addRateAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addRateAmplitude(void)"); + + const char* subfieldName = "rate_amplitude"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.scale = _defaultDescription->scale / _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::addRateAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addRateAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add rate start time field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addRateStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addRateStartTime(void)"); + + const char* subfieldName = "rate_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addRateStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history amplitude field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryAmplitude(void)"); + + const char* subfieldName = "time_history_amplitude"; + + assert(_defaultDescription); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::addTimeHistoryAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history start time field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); + + const char* subfieldName = "time_history_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history value field to auxiliary fields. +void +pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryValue(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); + + const char* subfieldName = "time_history_value"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); + // No subfield query; populated by integrator or constraint at beginning of time step. + + PYLITH_METHOD_END; +} // addTimeHistoryValue + + +// --------------------------------------------------------------------------------------------------------------------- +void +pylith::sources::TimeDependentAuxiliaryFactory::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { + PYLITH_METHOD_BEGIN; + pythia::journal::debug_t debug(_TimeDependentAuxiliaryFactory::genericComponent); + debug << pythia::journal::at(__HERE__) + << "TimeDependentAuxiliaryFactory::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); + pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); + PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); + + // Compute offset of time history subfields in auxiliary field. + const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; + const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; + + // Loop over all points in section. + for (PetscInt p = pStart; p < pEnd; ++p) { + // Skip points without values in section. + if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} + + // Get starting time and compute relative time for point. + const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); + const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; + const PylithScalar tRel = t - tStart; + + // Query time history for value (normalized amplitude). + PylithScalar value = 0.0; + if (tRel >= 0.0) { + PylithScalar tDim = tRel * timeScale; + const int err = dbTimeHistory->query(&value, tDim); + if (err) { + std::ostringstream msg; + msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; + throw std::runtime_error(msg.str()); + } // if + } // if + + // Update value (normalized amplitude) in auxiliary field. + const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); + auxiliaryFieldArray[offValue] = value; + } // for + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + +// End of file diff --git a/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh b/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh new file mode 100644 index 0000000000..d717e6860b --- /dev/null +++ b/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh @@ -0,0 +1,110 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2022 University of California, Davis +// +// See LICENSE.md.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/TimeDependentAuxiliaryFactory.hh + * + * @brief C++ helper class for setting up auxiliary fields for time-dependent sources. + */ + +#if !defined(pylith_sources_timedependentauxiliaryfactory_hh) +#define pylith_sources_timedependentauxiliaryfactory_hh + +#include "sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES TimeHistory + +class pylith::sources::TimeDependentAuxiliaryFactory : public pylith::feassemble::AuxiliaryFactory { + friend class TestDirichletAuxiliaryFactory; // unit testing + + // PUBLIC ENUMS //////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + enum ReferenceEnum { + XYZ=0, ///< Coordinate directions (x, y, z). + TANGENTIAL_NORMAL=1, ///< Directions tangential and normal to the boundary (tangential_1, tangential_2, normal). + }; + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /** Default constructor. + * + * @param[in] reference Reference for coordinate directions in auxiliary subfield.s + */ + TimeDependentAuxiliaryFactory(const ReferenceEnum reference=XYZ); + + /// Destructor. + ~TimeDependentAuxiliaryFactory(void); + + /// Add initial amplitude field to auxiliary fields. + void addInitialAmplitude(void); + + /// Add rate amplitude field to auxiliary fields. + void addRateAmplitude(void); + + /// Add rate start time amplitude field to auxiliary fields. + void addRateStartTime(void); + + /// Add time history amplitude field to auxiliary fields. + void addTimeHistoryAmplitude(void); + + /// Add time history start time field to auxiliary fields. + void addTimeHistoryStartTime(void); + + /// Add time history value field to auxiliary fields. + void addTimeHistoryValue(void); + + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + * @param[in] dbTimeHistory Time history database. + */ + static + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory); + + // PRIVATE METHODS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + /** Set names of vector field components in auxiliary subfield. + * + * @param[in] description Subfield description. + */ + void _setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description); + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + ReferenceEnum _auxComponents; ///< Coordinate system reference for field components. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + TimeDependentAuxiliaryFactory(const TimeDependentAuxiliaryFactory &); ///< Not implemented. + const TimeDependentAuxiliaryFactory& operator=(const TimeDependentAuxiliaryFactory&); ///< Not implemented + +}; // class TimeDependentAuxiliaryFactory + +#endif // pylith_sources_timedependentauxiliaryfactory_hh + +// End of file diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc index 7e6c3df5ee..6ee54cbe45 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.cc +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -32,7 +32,8 @@ // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::TimeHistoryWavelet::TimeHistoryWavelet(void) : - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime), + _useTimeHistory(true) { pylith::utils::PyreComponent::setName("timehistorywavelet"); } // constructor @@ -47,7 +48,7 @@ pylith::sources::TimeHistoryWavelet::~TimeHistoryWavelet(void) { // --------------------------------------------------------------------------------------------------------------------- // Set time history database. void -pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { +pylith::sources::TimeHistoryWavelet::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); _dbTimeHistory = th; @@ -57,7 +58,7 @@ pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::Tim // --------------------------------------------------------------------------------------------------------------------- // Get time history database. const spatialdata::spatialdb::TimeHistory * -pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { +pylith::sources::TimeHistoryWavelet::getTimeHistoryDB(void) { return _dbTimeHistory; } // getTimeHistoryDB @@ -90,10 +91,9 @@ pylith::sources::TimeHistoryWavelet::addAuxiliarySubfields(void) { // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise // functions (kernels). - _auxiliaryFactory->addCenterFrequency(); // numA - 1 _auxiliaryFactory->addTimeHistoryAmplitude(); - _auxiliaryFactory->addTimeHistoryStartTime(); - _auxiliaryFactory->addTimeHistoryValue(); + _auxiliaryFactory->addTimeHistoryStartTime(); // numA - 1 + _auxiliaryFactory->addTimeHistoryValue(); // numA - 1 if (_dbTimeHistory) { _dbTimeHistory->open(); } // if diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index f3446c5e7b..a218db2dba 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -43,6 +43,18 @@ public: /// Deallocate PETSc and local data structures. void deallocate(void); + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); + /** Get auxiliary factory associated with physics. * * @return Auxiliary factory for physics object. diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh index 2a625d28da..d8a245f3e5 100644 --- a/libsrc/pylith/sources/sourcesfwd.hh +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -41,6 +41,7 @@ namespace pylith { class SquareWavelet; class RickerWavelet; class GaussianWavelet; + class TimeHistoryWavelet; class PointForce; class AuxiliaryFactoryPointForce; From ff96de90e8d684b7b6ca6577a5bd547eddbd5d20 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Sun, 4 Feb 2024 17:50:19 -0800 Subject: [PATCH 27/65] Added fekernel for timehistorywavelet --- libsrc/pylith/fekernels/TimeHistoryWavelet.hh | 57 ++++++++++++------- libsrc/pylith/sources/TimeHistoryWavelet.cc | 4 +- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh index b5330088e2..37c3720da7 100644 --- a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh +++ b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh @@ -79,7 +79,28 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + const PylithInt _numA = 4; + assert(_numA == numA); + assert(aOff); + assert(a); + + // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_start_time = aOff[numA - 2]; + const PylithInt i_value = aOff[numA - 1]; + + PylithInt _dim = 2; + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * a[i_value]; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); + } // for + } // g1v }; // TimeHistoryWaveletPlaneStrain @@ -135,34 +156,30 @@ public: const PylithInt numConstants, const PylithScalar constants[], PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 3; + const PylithInt _numA = 4; + assert(_numA == numA); + assert(aOff); + assert(a); - // Incoming re-packed solution field. + // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_start_time = aOff[numA - 2]; + const PylithInt i_value = aOff[numA - 1]; - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; - - // TimeHistoryWavelet source time function (time domain) + PylithInt _dim = 3; - PylithScalar rt = t - timeDelay; - PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * - PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * rickerwavelet; + g1[i] -= momentTensor[i] * a[i_value]; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); } // for } // g1v }; // g1v -#endif /* pylith_fekernels_rickerwavelet_hh */ +#endif /* pylith_fekernels_timehistorywavelet_hh */ /* End of file */ diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc index 6ee54cbe45..df42ae0077 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.cc +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -91,8 +91,8 @@ pylith::sources::TimeHistoryWavelet::addAuxiliarySubfields(void) { // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the point-wise // functions (kernels). - _auxiliaryFactory->addTimeHistoryAmplitude(); - _auxiliaryFactory->addTimeHistoryStartTime(); // numA - 1 + // _auxiliaryFactory->addTimeHistoryAmplitude(); // numA - 3 + _auxiliaryFactory->addTimeHistoryStartTime(); // numA - 2 _auxiliaryFactory->addTimeHistoryValue(); // numA - 1 if (_dbTimeHistory) { _dbTimeHistory->open(); From a819d5d7f57d1143b42fecece59fa6c7ec963577 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Sun, 4 Feb 2024 18:04:15 -0800 Subject: [PATCH 28/65] need to find out how to pass _dbtimehistory --- libsrc/pylith/fekernels/TimeHistoryWavelet.hh | 24 ++++++++++++------- libsrc/pylith/fekernels/fekernelsfwd.hh | 4 ++++ libsrc/pylith/sources/MomentTensorForce.cc | 2 ++ libsrc/pylith/sources/TimeHistoryWavelet.cc | 21 +--------------- libsrc/pylith/sources/TimeHistoryWavelet.hh | 13 ---------- 5 files changed, 23 insertions(+), 41 deletions(-) diff --git a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh index 37c3720da7..600427c36a 100644 --- a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh +++ b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh @@ -20,14 +20,16 @@ * */ -#if !defined(pylith_fekernels_rickerwavelet_hh) -#define pylith_fekernels_rickerwavelet_hh +#if !defined(pylith_fekernels_timehistorywavelet_hh) +#define pylith_fekernels_timehistorywavelet_hh // Include directives --------------------------------------------------- #include "fekernelsfwd.hh" // forward declarations #include "pylith/utils/types.hh" +#include // USES assert() + // ===================================================================================================================== // Kernels for the TimeHistory Source Time Function in 2D. // ===================================================================================================================== @@ -86,6 +88,7 @@ public: assert(a); // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_moment_tensor = aOff[0]; const PylithInt i_start_time = aOff[numA - 2]; const PylithInt i_value = aOff[numA - 1]; @@ -93,12 +96,14 @@ public: // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorywaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "timehistoryWavelet %f\n", (double)timehistorywavelet); + + const PylithScalar* momentTensor = &a[aOff[i_moment_tensor]]; for (PylithInt i = 0; i < dim*dim; ++i) { g1[i] -= momentTensor[i] * a[i_value]; - // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); } // for } // g1v @@ -162,6 +167,7 @@ public: assert(a); // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_moment_tensor = aOff[0]; const PylithInt i_start_time = aOff[numA - 2]; const PylithInt i_value = aOff[numA - 1]; @@ -169,12 +175,14 @@ public: // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorywaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "timehistoryWavelet %f\n", (double)timehistorywavelet); + + const PylithScalar* momentTensor = &a[aOff[i_moment_tensor]]; for (PylithInt i = 0; i < dim*dim; ++i) { g1[i] -= momentTensor[i] * a[i_value]; - // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); } // for } // g1v diff --git a/libsrc/pylith/fekernels/fekernelsfwd.hh b/libsrc/pylith/fekernels/fekernelsfwd.hh index 33fc94d255..3260382aec 100644 --- a/libsrc/pylith/fekernels/fekernelsfwd.hh +++ b/libsrc/pylith/fekernels/fekernelsfwd.hh @@ -72,6 +72,10 @@ namespace pylith { class GaussianWaveletPlaneStrain; class GaussianWavelet3D; + class TimeHistoryWavelet; + class TimeHistoryWaveletPlaneStrain; + class TimeHistoryWavelet3D; + class PointForce; class BoundaryDirections; diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 8030ed4d66..485b90f9b4 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -48,6 +48,7 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::MomentTensorForce::MomentTensorForce(void) : + _dbTimeHistory(NULL), _sourceTimeFunction(NULL), _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce), _useTimeHistory(false) { @@ -70,6 +71,7 @@ pylith::sources::MomentTensorForce::deallocate(void) { delete _derivedFactory;_derivedFactory = NULL; _sourceTimeFunction = NULL; + _dbTimeHistory = NULL; } // deallocate diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc index df42ae0077..b260a10665 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.cc +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -32,8 +32,7 @@ // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::TimeHistoryWavelet::TimeHistoryWavelet(void) : - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime), - _useTimeHistory(true) { + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { pylith::utils::PyreComponent::setName("timehistorywavelet"); } // constructor @@ -45,24 +44,6 @@ pylith::sources::TimeHistoryWavelet::~TimeHistoryWavelet(void) { } // destructor -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::TimeHistoryWavelet::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); - - _dbTimeHistory = th; -} // setTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Get time history database. -const spatialdata::spatialdb::TimeHistory * -pylith::sources::TimeHistoryWavelet::getTimeHistoryDB(void) { - return _dbTimeHistory; -} // getTimeHistoryDB - - // --------------------------------------------------------------------------------------------------------------------- // Deallocate PETSc and local data structures. void diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index a218db2dba..30ebc2d5ad 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -43,18 +43,6 @@ public: /// Deallocate PETSc and local data structures. void deallocate(void); - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); - /** Get auxiliary factory associated with physics. * * @return Auxiliary factory for physics object. @@ -78,7 +66,6 @@ public: // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: - spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// From db18b1d05bca1a374c63e66a433b6d054c0a2452 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 7 Feb 2024 13:52:15 -0800 Subject: [PATCH 29/65] Kicked dbtimehistory down a level --- libsrc/pylith/sources/MomentTensorForce.cc | 40 +- libsrc/pylith/sources/MomentTensorForce.hh | 2 - .../sources/TimeDependentAuxiliaryFactory.cc | 365 ------------------ .../sources/TimeDependentAuxiliaryFactory.hh | 110 ------ libsrc/pylith/sources/TimeHistoryWavelet.cc | 53 ++- libsrc/pylith/sources/TimeHistoryWavelet.hh | 36 ++ 6 files changed, 88 insertions(+), 518 deletions(-) delete mode 100644 libsrc/pylith/sources/TimeDependentAuxiliaryFactory.cc delete mode 100644 libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 485b90f9b4..1c12dfa201 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -48,10 +48,8 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::MomentTensorForce::MomentTensorForce(void) : - _dbTimeHistory(NULL), _sourceTimeFunction(NULL), - _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce), - _useTimeHistory(false) { + _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce) { pylith::utils::PyreComponent::setName("momenttensorforce"); } // constructor @@ -75,42 +73,6 @@ pylith::sources::MomentTensorForce::deallocate(void) { } // deallocate -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::MomentTensorForce::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th"< - -#include "TimeDependentAuxiliaryFactory.hh" // implementation of object methods - -#include "pylith/topology/Field.hh" // HOLDSA AuxiliaryField -#include "pylith/topology/FieldQuery.hh" // USES FieldQuery -#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh - -#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* - -#include - -// --------------------------------------------------------------------------------------------------------------------- -namespace pylith { - namespace sources { - class _TimeDependentAuxiliaryFactory { -public: - - ///< Names of field components in XYZ coordinate system. - static const char* componentsXYZ[3]; - - ///< Names of field components in 2-D tangential/normal coordinate system. - static const char* componentsTN[2]; - - ///< Names of field components in 3-D tangential/normal coordinate system. - static const char* componentsTTN[3]; - - static const char* genericComponent; - }; // _TimeDependentAuxiliaryFactory - - const char* _TimeDependentAuxiliaryFactory::componentsXYZ[3] = { "_x", "_y", "_z" }; - const char* _TimeDependentAuxiliaryFactory::componentsTN[2] = { "_tangential", "_normal" }; - const char* _TimeDependentAuxiliaryFactory::componentsTTN[3] = { "_tangential_1", "_tangential_2", "_normal" }; - - const char* _TimeDependentAuxiliaryFactory::genericComponent = "timedependentauxiliaryfactory"; - } // sources -} // pylith - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::TimeDependentAuxiliaryFactory::TimeDependentAuxiliaryFactory(const ReferenceEnum reference) : - _auxComponents(reference) { - GenericComponent::setName(_TimeDependentAuxiliaryFactory::genericComponent); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::TimeDependentAuxiliaryFactory::~TimeDependentAuxiliaryFactory(void) {} - - -// --------------------------------------------------------------------------------------------------------------------- -// Set names of vector components in auxiliary subfield. -void -pylith::sources::TimeDependentAuxiliaryFactory::_setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("_setVectorFieldComponentNames(description)"); - - assert(description); - - const char** componentNames = NULL; - if (XYZ == _auxComponents) { - componentNames = _TimeDependentAuxiliaryFactory::componentsXYZ; - } else if (TANGENTIAL_NORMAL == _auxComponents) { - if (2 == _spaceDim) { - componentNames = _TimeDependentAuxiliaryFactory::componentsTN; - } else if (3 == _spaceDim) { - componentNames = _TimeDependentAuxiliaryFactory::componentsTTN; - } // if/else - } // if/else - if (!componentNames) { - PYLITH_JOURNAL_ERROR("Unknown case for auxiliary component reference ("<<_auxComponents<<") and spatial dimension ("<<_spaceDim<<")."); - throw std::logic_error("Unknown case for auxiliary component reference and spatial dimension."); - } // if - - assert(size_t(_spaceDim) == description->numComponents); - for (int i = 0; i < _spaceDim; ++i) { - description->componentNames[i] = description->label + std::string(componentNames[i]); - } // for - - PYLITH_METHOD_END; -} // _setVectorFieldComponentNames - - -// --------------------------------------------------------------------------------------------------------------------- -// Add initial amplitude field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addInitialAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addInitialAmplitude(void)"); - - const char* subfieldName = "initial_amplitude"; - - assert(_defaultDescription); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.validator = NULL; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::initialAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addInitialAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add rate amplitude field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addRateAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addRateAmplitude(void)"); - - const char* subfieldName = "rate_amplitude"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.scale = _defaultDescription->scale / _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::addRateAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addRateAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add rate start time field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addRateStartTime(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addRateStartTime(void)"); - - const char* subfieldName = "rate_start_time"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addRateStartTime - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history amplitude field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryAmplitude(void)"); - - const char* subfieldName = "time_history_amplitude"; - - assert(_defaultDescription); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in TimeDependentAuxiliaryFactory::addTimeHistoryAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeHistoryAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history start time field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryStartTime(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); - - const char* subfieldName = "time_history_start_time"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeHistoryStartTime - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history value field to auxiliary fields. -void -pylith::sources::TimeDependentAuxiliaryFactory::addTimeHistoryValue(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); - - const char* subfieldName = "time_history_value"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); - // No subfield query; populated by integrator or constraint at beginning of time step. - - PYLITH_METHOD_END; -} // addTimeHistoryValue - - -// --------------------------------------------------------------------------------------------------------------------- -void -pylith::sources::TimeDependentAuxiliaryFactory::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const PylithReal t, - const PylithReal timeScale, - spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { - PYLITH_METHOD_BEGIN; - pythia::journal::debug_t debug(_TimeDependentAuxiliaryFactory::genericComponent); - debug << pythia::journal::at(__HERE__) - << "TimeDependentAuxiliaryFactory::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); - PetscInt pStart = 0, pEnd = 0; - err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); - pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); - PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); - - // Compute offset of time history subfields in auxiliary field. - const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; - const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; - - // Loop over all points in section. - for (PetscInt p = pStart; p < pEnd; ++p) { - // Skip points without values in section. - if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} - - // Get starting time and compute relative time for point. - const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); - const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; - const PylithScalar tRel = t - tStart; - - // Query time history for value (normalized amplitude). - PylithScalar value = 0.0; - if (tRel >= 0.0) { - PylithScalar tDim = tRel * timeScale; - const int err = dbTimeHistory->query(&value, tDim); - if (err) { - std::ostringstream msg; - msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; - throw std::runtime_error(msg.str()); - } // if - } // if - - // Update value (normalized amplitude) in auxiliary field. - const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); - auxiliaryFieldArray[offValue] = value; - } // for - - PYLITH_METHOD_END; -} // updateAuxiliaryField - - -// End of file diff --git a/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh b/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh deleted file mode 100644 index d717e6860b..0000000000 --- a/libsrc/pylith/sources/TimeDependentAuxiliaryFactory.hh +++ /dev/null @@ -1,110 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/TimeDependentAuxiliaryFactory.hh - * - * @brief C++ helper class for setting up auxiliary fields for time-dependent sources. - */ - -#if !defined(pylith_sources_timedependentauxiliaryfactory_hh) -#define pylith_sources_timedependentauxiliaryfactory_hh - -#include "sourcesfwd.hh" // forward declarations -#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES TimeHistory - -class pylith::sources::TimeDependentAuxiliaryFactory : public pylith::feassemble::AuxiliaryFactory { - friend class TestDirichletAuxiliaryFactory; // unit testing - - // PUBLIC ENUMS //////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - enum ReferenceEnum { - XYZ=0, ///< Coordinate directions (x, y, z). - TANGENTIAL_NORMAL=1, ///< Directions tangential and normal to the boundary (tangential_1, tangential_2, normal). - }; - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /** Default constructor. - * - * @param[in] reference Reference for coordinate directions in auxiliary subfield.s - */ - TimeDependentAuxiliaryFactory(const ReferenceEnum reference=XYZ); - - /// Destructor. - ~TimeDependentAuxiliaryFactory(void); - - /// Add initial amplitude field to auxiliary fields. - void addInitialAmplitude(void); - - /// Add rate amplitude field to auxiliary fields. - void addRateAmplitude(void); - - /// Add rate start time amplitude field to auxiliary fields. - void addRateStartTime(void); - - /// Add time history amplitude field to auxiliary fields. - void addTimeHistoryAmplitude(void); - - /// Add time history start time field to auxiliary fields. - void addTimeHistoryStartTime(void); - - /// Add time history value field to auxiliary fields. - void addTimeHistoryValue(void); - - /** Update auxiliary field for current time. - * - * @param[inout] auxiliaryField Auxiliary field to update. - * @param[in] t Current time. - * @param[in] timeScale Time scale for nondimensionalization. - * @param[in] dbTimeHistory Time history database. - */ - static - void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const PylithReal t, - const PylithReal timeScale, - spatialdata::spatialdb::TimeHistory* const dbTimeHistory); - - // PRIVATE METHODS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - /** Set names of vector field components in auxiliary subfield. - * - * @param[in] description Subfield description. - */ - void _setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - ReferenceEnum _auxComponents; ///< Coordinate system reference for field components. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - TimeDependentAuxiliaryFactory(const TimeDependentAuxiliaryFactory &); ///< Not implemented. - const TimeDependentAuxiliaryFactory& operator=(const TimeDependentAuxiliaryFactory&); ///< Not implemented - -}; // class TimeDependentAuxiliaryFactory - -#endif // pylith_sources_timedependentauxiliaryfactory_hh - -// End of file diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc index b260a10665..9c13d40bb5 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.cc +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -24,6 +24,7 @@ #include "pylith/fekernels/TimeHistoryWavelet.hh" // USES TimeHistoryWavelet kernels #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* #include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys @@ -32,7 +33,9 @@ // --------------------------------------------------------------------------------------------------------------------- // Default constructor. pylith::sources::TimeHistoryWavelet::TimeHistoryWavelet(void) : - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime) { + _dbTimeHistory(NULL), + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime),\ + _useTimeHistory(True) { pylith::utils::PyreComponent::setName("timehistorywavelet"); } // constructor @@ -53,10 +56,44 @@ pylith::sources::TimeHistoryWavelet::deallocate(void) { delete _auxiliaryFactory;_auxiliaryFactory = NULL; } // deallocate +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void +pylith::sources::TimeHistoryWavelet::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th) { + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th"<getTimeScale(); + AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); + } // if + } // End of file diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index 30ebc2d5ad..43834d2c0c 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -43,6 +43,30 @@ public: /// Deallocate PETSc and local data structures. void deallocate(void); + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + /** Get auxiliary factory associated with physics. * * @return Auxiliary factory for physics object. @@ -63,10 +87,22 @@ public: */ PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + */ + PetscPointFunc updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale); + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: pylith::sources::AuxiliaryFactorySourceTime* _auxiliaryFactory; ///< Factory for creating auxiliary subfields. + spatialdata::spatialdb::TimeHistory* _dbTimeHistory; ///< Time history database. + bool _useTimeHistory; ///< Use time history term. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: From a233ff96048836cc1fe2a5352b5fec8f75abf35c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Sun, 18 Feb 2024 21:59:54 -0800 Subject: [PATCH 30/65] first pass for libsrc finished --- libsrc/pylith/sources/MomentTensorForce.cc | 16 +++++++----- .../SourceTimeFunctionMomentTensorForce.cc | 18 ++++++++++++- .../SourceTimeFunctionMomentTensorForce.hh | 11 ++++++++ libsrc/pylith/sources/TimeHistoryWavelet.cc | 26 +++++++++++-------- libsrc/pylith/sources/TimeHistoryWavelet.hh | 6 ++--- 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 1c12dfa201..96b301beda 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -69,7 +69,6 @@ pylith::sources::MomentTensorForce::deallocate(void) { delete _derivedFactory;_derivedFactory = NULL; _sourceTimeFunction = NULL; - _dbTimeHistory = NULL; } // deallocate @@ -174,11 +173,16 @@ pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField="<getTimeScale(); - AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); - } // if + assert(_sourceTimeFunction); + const PylithScalar timeScale = _normalizer->getTimeScale(); + + _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale); + + // if (_useTimeHistory) { + // assert(_normalizer); + // const PylithScalar timeScale = _normalizer->getTimeScale(); + // AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); + // } // if PYLITH_METHOD_END; } // updateAuxiliaryField diff --git a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc index c00e736b50..18c60777dc 100644 --- a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc +++ b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc @@ -45,7 +45,8 @@ pylith::sources::SourceTimeFunctionMomentTensorForce::~SourceTimeFunctionMomentT // --------------------------------------------------------------------------------------------------------------------- // Deallocate PETSc and local data structures. void -pylith::sources::SourceTimeFunctionMomentTensorForce::deallocate(void) {} +pylith::sources::SourceTimeFunctionMomentTensorForce::deallocate(void) { +} // --------------------------------------------------------------------------------------------------------------------- @@ -84,4 +85,19 @@ pylith::sources::SourceTimeFunctionMomentTensorForce::addKernelsUpdateStateVars( } // addKernelsUpdateStateVars +// --------------------------------------------------------------------------------------------------------------------- +// Update auxiliary field values. +void +pylith::sources::SourceTimeFunctionMomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField"< +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime #include "pylith/sources/TimeHistoryWavelet.hh" // implementation of object methods -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime #include "pylith/fekernels/TimeHistoryWavelet.hh" // USES TimeHistoryWavelet kernels #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* #include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END -#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys @@ -34,8 +34,8 @@ // Default constructor. pylith::sources::TimeHistoryWavelet::TimeHistoryWavelet(void) : _dbTimeHistory(NULL), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime),\ - _useTimeHistory(True) { + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySourceTime), \ + _useTimeHistory(true) { pylith::utils::PyreComponent::setName("timehistorywavelet"); } // constructor @@ -56,6 +56,7 @@ pylith::sources::TimeHistoryWavelet::deallocate(void) { delete _auxiliaryFactory;_auxiliaryFactory = NULL; } // deallocate + // --------------------------------------------------------------------------------------------------------------------- // Set time history database. void @@ -91,9 +92,10 @@ pylith::sources::TimeHistoryWavelet::useTimeHistory(void) const { // useTimeHist return _useTimeHistory; } // useTimeHistory + // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. -pylith::sources::AuxiliaryFactoryTimeHistoryWavelet* +pylith::sources::AuxiliaryFactorySourceTime* pylith::sources::TimeHistoryWavelet::getAuxiliaryFactory(void) { return _auxiliaryFactory; } // getAuxiliaryFactory @@ -135,17 +137,19 @@ pylith::sources::TimeHistoryWavelet::getKernelg1v_explicit(const spatialdata::ge PYLITH_METHOD_RETURN(g1v); } // getKernelResidualStress + // --------------------------------------------------------------------------------------------------------------------- // Update auxiliary fields. -PetscPointFunc +void pylith::sources::TimeHistoryWavelet::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const PylithReal t, - const PylithReal timeScale,) const { + const PylithReal t, + const PylithReal timeScale) { if (_useTimeHistory) { - assert(_normalizer); - const PylithScalar timeScale = _normalizer->getTimeScale(); + // assert(_normalizer); + // const PylithScalar timeScale = _normalizer->getTimeScale(); AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); } // if - } +} + // End of file diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index 43834d2c0c..7d71600752 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -71,7 +71,7 @@ public: * * @return Auxiliary factory for physics object. */ - pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + pylith::sources::AuxiliaryFactorySourceTime* getAuxiliaryFactory(void); /** Add source time subfields to auxiliary field. * @@ -93,10 +93,10 @@ public: * @param[in] t Current time. * @param[in] timeScale Time scale for nondimensionalization. */ - PetscPointFunc updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, const PylithReal timeScale); - + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: From 815e4e402adbf6db6f4041c446b0cd769d81e46e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Mon, 18 Mar 2024 16:39:10 -0700 Subject: [PATCH 31/65] Updated modulesrc --- modulesrc/sources/Makefile.am | 1 + modulesrc/sources/TimeHistoryWavelet.i | 101 +++++++++++++++++++++++++ modulesrc/sources/sources.i | 2 + 3 files changed, 104 insertions(+) create mode 100644 modulesrc/sources/TimeHistoryWavelet.i diff --git a/modulesrc/sources/Makefile.am b/modulesrc/sources/Makefile.am index 3ec50b593d..bdfbddea20 100644 --- a/modulesrc/sources/Makefile.am +++ b/modulesrc/sources/Makefile.am @@ -35,6 +35,7 @@ swig_sources = \ SourceTimeFunctionMomentTensorForce.i \ RickerWavelet.i \ GaussianWavelet.i \ + TimeHistoryWavelet.i \ ../utils/PyreComponent.i swigincludedir = $(pkgdatadir)/swig/$(subpackage) diff --git a/modulesrc/sources/TimeHistoryWavelet.i b/modulesrc/sources/TimeHistoryWavelet.i new file mode 100644 index 0000000000..31cd1c5851 --- /dev/null +++ b/modulesrc/sources/TimeHistoryWavelet.i @@ -0,0 +1,101 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University at Buffalo +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2021 University of California, Davis +// +// See LICENSE.md for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file modulesrc/sources/TimeHistoryWavelet.i + * + * Python interface to C++ TimeHistoryWavelet. + */ + +namespace pylith { + namespace sources { + class TimeHistoryWavelet: public pylith::sources::SourceTimeFunctionMomentTensorForce { + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + TimeHistoryWavelet(void); + + /// Destructor. + ~TimeHistoryWavelet(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); + + /** Add source time function subfields to auxiliary field. + * + * @param[inout] auxiliaryField Auxiliary field. + */ + void addAuxiliarySubfields(void); + + /** Get g1v kernel for residual, G(t,s). + * + * @param[in] coordsys Coordinate system. + * + * @return residual kernel for g1v + * . + */ + PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const; + + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + */ + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale); + + }; + + // class TimeHistoryWavelet + + } // sources +} // pylith + +// End of file diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i index ea2e3db9bb..5bc04cca9b 100644 --- a/modulesrc/sources/sources.i +++ b/modulesrc/sources/sources.i @@ -27,6 +27,7 @@ #include "pylith/sources/RickerWavelet.hh" #include "pylith/sources/GaussianWavelet.hh" #include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" +#include "pylith/sources/TimeHistoryWavelet.hh" #include "pylith/utils/arrayfwd.hh" %} @@ -66,5 +67,6 @@ import_array(); %include "SquareWavelet.i" %include "RickerWavelet.i" %include "GaussianWavelet.i" +%include "TimeHistoryWavelet.i" // End of file From faf8972afe38840def807d10a2096ba035b735b6 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Mon, 18 Mar 2024 17:03:20 -0700 Subject: [PATCH 32/65] Gave up and returned everything to AuxiliaryFactoryMomentTensorForce --- .../AuxiliaryFactoryMomentTensorForce.cc | 143 ++++++++++++++++++ .../AuxiliaryFactoryMomentTensorForce.hh | 25 +++ libsrc/pylith/sources/TimeHistoryWavelet.cc | 6 +- libsrc/pylith/sources/TimeHistoryWavelet.hh | 2 +- .../sources/AuxSubfieldsMomentTensorForce.py | 6 +- pylith/sources/AuxSubfieldsSourceTime.py | 8 + pylith/sources/TimeHistoryWavelet.py | 67 ++++++++ pylith/sources/__init__.py | 1 + 8 files changed, 252 insertions(+), 6 deletions(-) create mode 100644 pylith/sources/TimeHistoryWavelet.py diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc index 8a986dc2a4..34948e3371 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -22,7 +22,9 @@ #include "pylith/topology/Field.hh" // USES Field #include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include "pylith/utils/error.hh" // USES PYLITH_METHOD* @@ -107,4 +109,145 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { // time } // addTimeDelay +// --------------------------------------------------------------------------------------------------------------------- +// Add center frequency of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::addCenterFrequency(void) { // centerFrequency + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); + + const char* subfieldName = "center_frequency"; + const PylithReal timeScale = _normalizer->getTimeScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = 1.0 / timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addCenterFrequency + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history start time field to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeHistoryStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); + + const char* subfieldName = "time_history_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history value field to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeHistoryValue(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); + + const char* subfieldName = "time_history_value"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); + // No subfield query; populated by integrator or constraint at beginning of time step. + + PYLITH_METHOD_END; +} // addTimeHistoryValue + + +// --------------------------------------------------------------------------------------------------------------------- +void +pylith::sources::AuxiliaryFactoryMomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { + PYLITH_METHOD_BEGIN; + // pythia::journal::debug_t debug(_TimeDependentAuxiliaryFactory::genericComponent); + // debug << pythia::journal::at(__HERE__) + // << "TimeDependentAuxiliaryFactory::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); + pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); + PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); + + // Compute offset of time history subfields in auxiliary field. + const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; + const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; + + // Loop over all points in section. + for (PetscInt p = pStart; p < pEnd; ++p) { + // Skip points without values in section. + if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} + + // Get starting time and compute relative time for point. + const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); + const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; + const PylithScalar tRel = t - tStart; + + // Query time history for value (normalized amplitude). + PylithScalar value = 0.0; + if (tRel >= 0.0) { + PylithScalar tDim = tRel * timeScale; + const int err = dbTimeHistory->query(&value, tDim); + if (err) { + std::ostringstream msg; + msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; + throw std::runtime_error(msg.str()); + } // if + } // if + + // Update value (normalized amplitude) in auxiliary field. + const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); + auxiliaryFieldArray[offValue] = value; + } // for + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + // End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh index 024ee4f78d..b69b5b1b24 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.hh @@ -47,6 +47,31 @@ public: /// Add time delay subfield to auxiliary subfields. void addTimeDelay(void); + /// Add center frequency subfield to auxiliary subfields. + void addCenterFrequency(void); + + /// Add time history amplitude field to auxiliary fields. + void addTimeHistoryAmplitude(void); + + /// Add time history start time field to auxiliary fields. + void addTimeHistoryStartTime(void); + + /// Add time history value field to auxiliary fields. + void addTimeHistoryValue(void); + + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + * @param[in] dbTimeHistory Time history database. + */ + static + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory); + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.cc b/libsrc/pylith/sources/TimeHistoryWavelet.cc index bfecc63b9e..085922acf8 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.cc +++ b/libsrc/pylith/sources/TimeHistoryWavelet.cc @@ -18,10 +18,10 @@ #include #include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime - #include "pylith/sources/TimeHistoryWavelet.hh" // implementation of object methods +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime + #include "pylith/fekernels/TimeHistoryWavelet.hh" // USES TimeHistoryWavelet kernels #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* #include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END @@ -95,7 +95,7 @@ pylith::sources::TimeHistoryWavelet::useTimeHistory(void) const { // useTimeHist // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. -pylith::sources::AuxiliaryFactorySourceTime* +pylith::sources::AuxiliaryFactoryMomentTensorForce* pylith::sources::TimeHistoryWavelet::getAuxiliaryFactory(void) { return _auxiliaryFactory; } // getAuxiliaryFactory diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index 7d71600752..540649d2d9 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -71,7 +71,7 @@ public: * * @return Auxiliary factory for physics object. */ - pylith::sources::AuxiliaryFactorySourceTime* getAuxiliaryFactory(void); + pylith::sources::AuxiliaryFactoryMomentTensorForce* getAuxiliaryFactory(void); /** Add source time subfields to auxiliary field. * diff --git a/pylith/sources/AuxSubfieldsMomentTensorForce.py b/pylith/sources/AuxSubfieldsMomentTensorForce.py index 6d71e827a4..5285fba760 100644 --- a/pylith/sources/AuxSubfieldsMomentTensorForce.py +++ b/pylith/sources/AuxSubfieldsMomentTensorForce.py @@ -30,10 +30,12 @@ class AuxSubfieldsMomentTensorForce(PetscComponent): from pylith.topology.Subfield import Subfield - momentTensor = pythia.pyre.inventory.facility("moment_tensor", family="auxiliary_subfield", factory=Subfield) + momentTensor = pythia.pyre.inventory.facility( + "moment_tensor", family="auxiliary_subfield", factory=Subfield) momentTensor.meta['tip'] = "Moment tensor subfield." - TimeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) + TimeDelay = pythia.pyre.inventory.facility( + "time_delay", family="auxiliary_subfield", factory=Subfield) TimeDelay.meta['tip'] = "time delay subfield." # PUBLIC METHODS ///////////////////////////////////////////////////// diff --git a/pylith/sources/AuxSubfieldsSourceTime.py b/pylith/sources/AuxSubfieldsSourceTime.py index 8b3df75454..dd0390a5fa 100644 --- a/pylith/sources/AuxSubfieldsSourceTime.py +++ b/pylith/sources/AuxSubfieldsSourceTime.py @@ -33,6 +33,14 @@ class AuxSubfieldsSourceTime(PetscComponent): CenterFrequency = pythia.pyre.inventory.facility("center_frequency", family="auxiliary_subfield", factory=Subfield) CenterFrequency.meta['tip'] = "center frequency subfield." + useTimeHistory = pythia.pyre.inventory.bool( + "use_time_history", default=False) + useTimeHistory.meta['tip'] = "Use time history term in time-dependent expression." + + dbTimeHistory = pythia.pyre.inventory.facility( + "time_history", factory=NullComponent, family="temporal_database") + dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time. + # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="auxsubfieldssourcetime"): diff --git a/pylith/sources/TimeHistoryWavelet.py b/pylith/sources/TimeHistoryWavelet.py new file mode 100644 index 0000000000..48f14aaa4a --- /dev/null +++ b/pylith/sources/TimeHistoryWavelet.py @@ -0,0 +1,67 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2021 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/TimeHistoryWavelet.py +# +# @brief Python source time functiof for a ricker wavelet. +# +# Factory: pointforce_sourcetimefunction + +from .SourceTimeFunctionMomentTensorForce import SourceTimeFunctionMomentTensorForce +from .sources import TimeHistoryWavelet as ModuleTimeHistoryWavelet + + +class TimeHistoryWavelet(SourceTimeFunctionMomentTensorForce, ModuleTimeHistoryWavelet): + """Python source time function for time history source. + + FACTORY: pointforce_sourcetimefunction + """ + + import pythia.pyre.inventory + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="timehistorywavelet"): + """Constructor. + """ + SourceTimeFunctionMomentTensorForce.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSourceTime import AuxSubfieldsSourceTime + self.auxiliarySubfields = AuxSubfieldsSourceTime("auxiliary_subfields") + + def preinitialize(self, problem): + SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) + + return + + # PRIVATE METHODS //////////////////////////////////////////////////// + + def _createModuleObj(self): + """Call constructor for module object for access to C++ object. + """ + ModuleTimeHistoryWavelet.__init__(self) + + +# FACTORIES //////////////////////////////////////////////////////////// + +def momenttensorforce_sourcetimefunction(): + """Factory associated with TimeHistoryWavelet. + """ + return TimeHistoryWavelet() + + +# End of file diff --git a/pylith/sources/__init__.py b/pylith/sources/__init__.py index 837c625920..8649ad0bce 100644 --- a/pylith/sources/__init__.py +++ b/pylith/sources/__init__.py @@ -31,6 +31,7 @@ "AuxSubfieldsSourceTime", "SquareWavelet", "RickerWavelet", + "TimeHistoryWavelet", "GaussianWavelet" ] From 2600227bf23f1d70ebd3d9a6f45e682b3a13c9fd Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 3 Apr 2024 14:32:53 -0700 Subject: [PATCH 33/65] Moved time history from an aux field --- pylith/sources/AuxSubfieldsSourceTime.py | 11 ++--------- pylith/sources/MomentTensorForce.py | 13 ++++++++----- pylith/sources/PointForce.py | 3 --- pylith/sources/RickerWavelet.py | 1 - pylith/sources/Source.py | 13 ++++++++----- .../sources/SourceTimeFunctionMomentTensorForce.py | 3 ++- pylith/sources/TimeHistoryWavelet.py | 5 +++++ tests/pytests/sources/__init__.py | 4 +++- 8 files changed, 28 insertions(+), 25 deletions(-) diff --git a/pylith/sources/AuxSubfieldsSourceTime.py b/pylith/sources/AuxSubfieldsSourceTime.py index dd0390a5fa..1132158623 100644 --- a/pylith/sources/AuxSubfieldsSourceTime.py +++ b/pylith/sources/AuxSubfieldsSourceTime.py @@ -30,17 +30,10 @@ class AuxSubfieldsSourceTime(PetscComponent): from pylith.topology.Subfield import Subfield - CenterFrequency = pythia.pyre.inventory.facility("center_frequency", family="auxiliary_subfield", factory=Subfield) + CenterFrequency = pythia.pyre.inventory.facility( + "center_frequency", family="auxiliary_subfield", factory=Subfield) CenterFrequency.meta['tip'] = "center frequency subfield." - useTimeHistory = pythia.pyre.inventory.bool( - "use_time_history", default=False) - useTimeHistory.meta['tip'] = "Use time history term in time-dependent expression." - - dbTimeHistory = pythia.pyre.inventory.facility( - "time_history", factory=NullComponent, family="temporal_database") - dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time. - # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="auxsubfieldssourcetime"): diff --git a/pylith/sources/MomentTensorForce.py b/pylith/sources/MomentTensorForce.py index 8dd57add15..3a6b5015cb 100644 --- a/pylith/sources/MomentTensorForce.py +++ b/pylith/sources/MomentTensorForce.py @@ -19,7 +19,7 @@ # # Factory: source -from pylith.sources.RickerWavelet import RickerWavelet +from pylith.sources.TimeHistoryWavelet import TimeHistoryWavelet from .Source import Source from .sources import MomentTensorForce as ModuleMomentTensorForce @@ -32,7 +32,8 @@ class MomentTensorForce(Source, ModuleMomentTensorForce): import pythia.pyre.inventory - source_time_function = pythia.pyre.inventory.facility("source_time_function", family="momenttensorforce_sourcetimefunction", factory=RickerWavelet) + source_time_function = pythia.pyre.inventory.facility( + "source_time_function", family="momenttensorforce_sourcetimefunction", factory=TimeHistoryWavelet) source_time_function.meta['tip'] = "Source time function for moment tensor force." # PUBLIC METHODS ///////////////////////////////////////////////////// @@ -45,8 +46,8 @@ def __init__(self, name="momenttensorforce"): def _defaults(self): from .AuxSubfieldsMomentTensorForce import AuxSubfieldsMomentTensorForce - self.auxiliarySubfields = AuxSubfieldsMomentTensorForce("auxiliary_subfields") - + self.auxiliarySubfields = AuxSubfieldsMomentTensorForce( + "auxiliary_subfields") def preinitialize(self, problem): """Setup source. @@ -62,7 +63,9 @@ def _createModuleObj(self): """Create handle to C++ MomentTensorForce. """ ModuleMomentTensorForce.__init__(self) - ModuleMomentTensorForce.setSourceTimeFunction(self, self.source_time_function) # Material sets auxiliary db in source_time_function. + # Material sets auxiliary db in source_time_function. + ModuleMomentTensorForce.setSourceTimeFunction( + self, self.source_time_function) return diff --git a/pylith/sources/PointForce.py b/pylith/sources/PointForce.py index 53f71d8b26..87c4f97dfc 100644 --- a/pylith/sources/PointForce.py +++ b/pylith/sources/PointForce.py @@ -31,7 +31,6 @@ class PointForce(Source, ModulePointForce): import pythia.pyre.inventory - # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="pointforce"): @@ -44,13 +43,11 @@ def _defaults(self): from .AuxSubfieldsPointForce import AuxSubfieldsPointForce self.auxiliarySubfields = AuxSubfieldsPointForce("auxiliary_subfields") - def preinitialize(self, problem): """Setup source. """ Source.preinitialize(self, problem) - return def _createModuleObj(self): diff --git a/pylith/sources/RickerWavelet.py b/pylith/sources/RickerWavelet.py index c986e52e78..ab21245dd5 100644 --- a/pylith/sources/RickerWavelet.py +++ b/pylith/sources/RickerWavelet.py @@ -46,7 +46,6 @@ def _defaults(self): def preinitialize(self, problem): SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) - return # PRIVATE METHODS //////////////////////////////////////////////////// diff --git a/pylith/sources/Source.py b/pylith/sources/Source.py index b144c61396..9c29170e7a 100644 --- a/pylith/sources/Source.py +++ b/pylith/sources/Source.py @@ -15,7 +15,7 @@ # # @file pylith/sources/Source.py # -# @brief Python abstract base class for managing input and out put +# @brief Python abstract base class for managing input and out put # sources not necessarily pertaining to domain boundaries # # Factory: source @@ -43,7 +43,8 @@ class Source(Physics, ModuleSource): field = pythia.pyre.inventory.str("field", default="displacement") field.meta['tip'] = "Solution subfield associated with boundary condition." - description = pythia.pyre.inventory.str("description", default="", validator=validateDescription) + description = pythia.pyre.inventory.str( + "description", default="", validator=validateDescription) description.meta['tip'] = "Descriptive label for material." # labelName = pythia.pyre.inventory.str("label", default="source-id", validator=pythia.pyre.inventory.choice(["source-id"])) @@ -54,7 +55,8 @@ class Source(Physics, ModuleSource): labelValue.meta['tip'] = "Value of label identifying source." from pylith.meshio.PointsList import PointsList - reader = pythia.pyre.inventory.facility("reader", factory=PointsList, family="points_list") + reader = pythia.pyre.inventory.facility( + "reader", factory=PointsList, family="points_list") reader.meta['tip'] = "Reader for points list." def __init__(self, name="source"): @@ -79,10 +81,11 @@ def preinitialize(self, problem): convert(sourceCoords, problem.mesh().getCoordSys(), self.reader.coordsys) # Nondimensionalize - if hasattr(problem.normalizer,'lengthScale'): + if hasattr(problem.normalizer, 'lengthScale'): sourceCoords /= problem.normalizer.lengthScale.value else: - sourceCoords /= (problem.normalizer.shearWaveSpeed.value * problem.normalizer.wavePeriod.value) + sourceCoords /= (problem.normalizer.shearWaveSpeed.value * + problem.normalizer.wavePeriod.value) ModuleSource.setPoints(self, sourceCoords, sourceNames) return diff --git a/pylith/sources/SourceTimeFunctionMomentTensorForce.py b/pylith/sources/SourceTimeFunctionMomentTensorForce.py index 21c181f40b..6b9054256c 100644 --- a/pylith/sources/SourceTimeFunctionMomentTensorForce.py +++ b/pylith/sources/SourceTimeFunctionMomentTensorForce.py @@ -43,7 +43,8 @@ class SourceTimeFunctionMomentTensorForce(PetscComponent, ModuleSourceTimeFuncti def __init__(self, name): """Constructor. """ - PetscComponent.__init__(self, name, facility="sourcetimefunctionmomenttensorforce") + PetscComponent.__init__( + self, name, facility="sourcetimefunctionmomenttensorforce") return def preinitialize(self, problem): diff --git a/pylith/sources/TimeHistoryWavelet.py b/pylith/sources/TimeHistoryWavelet.py index 48f14aaa4a..fb86cd8226 100644 --- a/pylith/sources/TimeHistoryWavelet.py +++ b/pylith/sources/TimeHistoryWavelet.py @@ -21,6 +21,7 @@ from .SourceTimeFunctionMomentTensorForce import SourceTimeFunctionMomentTensorForce from .sources import TimeHistoryWavelet as ModuleTimeHistoryWavelet +from pylith.utils.NullComponent import NullComponent class TimeHistoryWavelet(SourceTimeFunctionMomentTensorForce, ModuleTimeHistoryWavelet): @@ -31,6 +32,10 @@ class TimeHistoryWavelet(SourceTimeFunctionMomentTensorForce, ModuleTimeHistoryW import pythia.pyre.inventory + dbTimeHistory = pythia.pyre.inventory.facility( + "time_history", factory=NullComponent, family="temporal_database") + dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time." + # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="timehistorywavelet"): diff --git a/tests/pytests/sources/__init__.py b/tests/pytests/sources/__init__.py index de99687c0a..38b6d26c09 100644 --- a/tests/pytests/sources/__init__.py +++ b/tests/pytests/sources/__init__.py @@ -1,2 +1,4 @@ from .TestSource import TestSource -from .TestWellboreSource import TestWellboreSource \ No newline at end of file +from .TestWellboreSource import TestWellboreSource +from .TestMomentTensorForce import TestMomentTensorForce +from .TestPointForce import TestPointForce From 0c833da4d5583dddf0a495e2f74b736c42917154 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 11 Jun 2024 08:23:17 -0600 Subject: [PATCH 34/65] Added explanation of wellbore character --- libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc index 58d1373958..68004839f0 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc @@ -213,6 +213,13 @@ pylith::sources::AuxiliaryFactoryWellboreSource::addWellborePressure(void) { // // ---------------------------------------------------------------------- // Add wellbore character subfield to auxiliary fields. +// If zero then borehole does nothing. +// If positive the borehole acts as a sink (production well) for porepressure > borehole pressure, and does nothing +// otherwise. +// If negative the borehole acts as a source (injection well) for porepressure < borehole pressure, and does nothing +// otherwise. +// The flow rate to/from the borehole is multiplied by |character|, so usually character = +/- 1, +// but you can specify other quantities to provide an overall scaling to the flow if you like. void pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreCharacter(void) { // wellboreCharacter PYLITH_METHOD_BEGIN; From cf29a6fe44860d59ba3a2bad67cce62494dbec2a Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 13 Jun 2024 10:01:04 -0600 Subject: [PATCH 35/65] Added ability to set r_e constant --- libsrc/pylith/fekernels/WellboreSource.cc | 6 +++-- .../sources/AuxiliaryFactoryWellboreSource.cc | 27 +++++++++++++++++++ .../sources/AuxiliaryFactoryWellboreSource.hh | 3 +++ libsrc/pylith/sources/WellboreSource.cc | 3 ++- pylith/sources/TimeHistoryWavelet.py | 2 +- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/libsrc/pylith/fekernels/WellboreSource.cc b/libsrc/pylith/fekernels/WellboreSource.cc index a403a65ed7..d178a4c34d 100644 --- a/libsrc/pylith/fekernels/WellboreSource.cc +++ b/libsrc/pylith/fekernels/WellboreSource.cc @@ -112,6 +112,7 @@ pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, const PylithInt i_wellboreLength = 4; const PylithInt i_wellboreCharacter = 6; const PylithInt i_elementDimensions = 7; + const PylithInt i_r_e_constant = 8; const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; @@ -120,9 +121,10 @@ pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, const PylithScalar wellboreLength = a[aOff[i_wellboreLength]]; const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; + const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; - PylithScalar r_e = 0.28 * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / - ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); + PylithScalar r_e = r_e_constant * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / + ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); PylithScalar W = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); Jf0[0] += W * wellboreCharacter * (1.0 / fluidViscosity); diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc index 68004839f0..e7435278ce 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc @@ -245,6 +245,33 @@ pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreCharacter(void) { // } // addWellboreCharacter +// ---------------------------------------------------------------------- +// Add r_e constant subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactoryWellboreSource::addr_e_constant(void) { // r_e constant + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addr_e_constant(void)"); + + const char* subfieldName = "r_e_constant"; + const PylithReal noScale = 1; + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = noScale; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addWellboreCharacter + + // ---------------------------------------------------------------------------- // Add isotropic permeability subfield to auxiliary fields. void diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh index f22e013c2f..2250a291e6 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh +++ b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh @@ -62,6 +62,9 @@ public: /// Add wellbore character subfield to auxiliary subfields. void addWellboreCharacter(void); + /// Add r_e constant character subfield to auxiliary subfields. + void addr_e_constant(void); + /// Add element dimensions subfield to auxiliary subfields. void addElementDimensions(void); diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc index 62f7f56f5f..d73e2da317 100644 --- a/libsrc/pylith/sources/WellboreSource.cc +++ b/libsrc/pylith/sources/WellboreSource.cc @@ -175,7 +175,8 @@ pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Fi _auxiliaryFactory->addWellborePressure(); // 5 _auxiliaryFactory->addWellboreCharacter(); // 6 _auxiliaryFactory->addElementDimensions(); // 7 - _auxiliaryFactory->addTimeDelay(); // 8 + _auxiliaryFactory->addr_e_constant(); // 8 + _auxiliaryFactory->addTimeDelay(); // 9 auxiliaryField->subfieldsSetup(); auxiliaryField->createDiscretization(); diff --git a/pylith/sources/TimeHistoryWavelet.py b/pylith/sources/TimeHistoryWavelet.py index fb86cd8226..f267f8705c 100644 --- a/pylith/sources/TimeHistoryWavelet.py +++ b/pylith/sources/TimeHistoryWavelet.py @@ -15,7 +15,7 @@ # # @file pylith/sources/TimeHistoryWavelet.py # -# @brief Python source time functiof for a ricker wavelet. +# @brief Python source time function for a user defined wavelet. # # Factory: pointforce_sourcetimefunction From cd381231851b175c6ce0f4e3cd25903b94afef32 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 13 Jun 2024 14:12:27 -0600 Subject: [PATCH 36/65] TimeHistoryWavelet compiles --- .vscode/settings.json | 4 +- libsrc/pylith/fekernels/TimeHistoryWavelet.hh | 4 +- .../sources/AuxiliaryFactorySourceTime.cc | 44 ++- libsrc/pylith/sources/MomentTensorForce.cc | 4 +- .../sources/MomentTensorForceTimeHistory.cc | 298 ++++++++++++++++++ .../SourceTimeFunctionMomentTensorForce.cc | 3 +- .../SourceTimeFunctionMomentTensorForce.hh | 5 +- libsrc/pylith/sources/TimeHistoryWavelet.cc | 11 +- libsrc/pylith/sources/TimeHistoryWavelet.hh | 3 +- modulesrc/sources/TimeHistoryWavelet.i | 3 +- pylith/sources/TimeHistoryWavelet.py | 20 +- 11 files changed, 362 insertions(+), 37 deletions(-) create mode 100644 libsrc/pylith/sources/MomentTensorForceTimeHistory.cc diff --git a/.vscode/settings.json b/.vscode/settings.json index cb180ef037..74acf4f946 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,9 @@ }, "files.associations": { "*.icc": "cpp", - "iosfwd": "cpp" + "iosfwd": "cpp", + "*.tcc": "cpp", + "fstream": "cpp" }, "python.formatting.autopep8Args": [ "-max-line-length", diff --git a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh index 600427c36a..00bd103982 100644 --- a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh +++ b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh @@ -82,7 +82,7 @@ public: const PylithInt numConstants, const PylithScalar constants[], PylithScalar g1[]) { - const PylithInt _numA = 4; + const PylithInt _numA = 3; assert(_numA == numA); assert(aOff); assert(a); @@ -161,7 +161,7 @@ public: const PylithInt numConstants, const PylithScalar constants[], PylithScalar g1[]) { - const PylithInt _numA = 4; + const PylithInt _numA = 3; assert(_numA == numA); assert(aOff); assert(a); diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index da630e1090..b3375e994a 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -80,19 +80,18 @@ pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryStartTime(void) { const char* subfieldName = "time_history_start_time"; - assert(_defaultDescription); assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::FieldBase::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = _normalizer->getTimeScale(); + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); PYLITH_METHOD_END; @@ -108,18 +107,17 @@ pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryValue(void) { const char* subfieldName = "time_history_value"; - assert(_defaultDescription); assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::FieldBase::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.validator = NULL; + + _field->subfieldAdd(description, getSubfieldDiscretization("time_history_amplitude")); // No subfield query; populated by integrator or constraint at beginning of time step. PYLITH_METHOD_END; diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 96b301beda..dcf1664060 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -20,7 +20,7 @@ #include "pylith/sources/MomentTensorForce.hh" // implementation of object methods -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +// #include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime #include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // HASA SourceTimeFunctionMomentTensorSource #include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce #include "pylith/sources/DerivedFactoryMomentTensorForce.hh" // USES DerivedFactoryMomentTensorForce @@ -176,7 +176,7 @@ pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field assert(_sourceTimeFunction); const PylithScalar timeScale = _normalizer->getTimeScale(); - _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale); + _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale, _normalizer); // if (_useTimeHistory) { // assert(_normalizer); diff --git a/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc b/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc new file mode 100644 index 0000000000..96b301beda --- /dev/null +++ b/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc @@ -0,0 +1,298 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "pylith/sources/MomentTensorForce.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime +#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // HASA SourceTimeFunctionMomentTensorSource +#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce +#include "pylith/sources/DerivedFactoryMomentTensorForce.hh" // USES DerivedFactoryMomentTensorForce +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps +#include "pylith/fekernels/DispVel.hh" // USES DispVel kernels +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::MomentTensorForce::MomentTensorForce(void) : + _sourceTimeFunction(NULL), + _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce) { + pylith::utils::PyreComponent::setName("momenttensorforce"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::MomentTensorForce::~MomentTensorForce(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::MomentTensorForce::deallocate(void) { + Source::deallocate(); + + delete _derivedFactory;_derivedFactory = NULL; + _sourceTimeFunction = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Set source time function. +void +pylith::sources::MomentTensorForce::setSourceTimeFunction(pylith::sources::SourceTimeFunctionMomentTensorForce* const sourceTimeFunction) { + _sourceTimeFunction = sourceTimeFunction; +} // setSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Get bulk source time function. +pylith::sources::SourceTimeFunctionMomentTensorForce* +pylith::sources::MomentTensorForce::getSourceTimeFunction(void) const { + return _sourceTimeFunction; +} // getSourceTimeFunction + + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void +pylith::sources::MomentTensorForce::verifyConfiguration(const pylith::topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution="<setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + + _setKernelsResidual(integrator, solution); + + _setKernelsUpdateStateVars(integrator, solution); + _setKernelsDerivedField(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field* +pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution="<setLabel("MomentTensorForce auxiliary field"); + + assert(_sourceTimeFunction); + pylith::sources::AuxiliaryFactoryMomentTensorForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); + + assert(_normalizer); + auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + auxiliaryFactory->addMomentTensor(); // 0 + + _sourceTimeFunction->addAuxiliarySubfields(); + + auxiliaryField->subfieldsSetup(); + auxiliaryField->createDiscretization(); + pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); + auxiliaryField->allocate(); + auxiliaryField->createOutputVector(); + + assert(auxiliaryFactory); + auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("MomentTensor auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + + +// --------------------------------------------------------------------------------------------------------------------- +// Update auxiliary subfields at beginning of time step. +void +pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const double t) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField="<getTimeScale(); + + _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale); + + // if (_useTimeHistory) { + // assert(_normalizer); + // const PylithScalar timeScale = _normalizer->getTimeScale(); + // AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); + // } // if + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field* +pylith::sources::MomentTensorForce::createDerivedField(const pylith::topology::Field& solution, + const pylith::topology::Mesh& domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution="<getAuxiliaryFactory(); +} // _getAuxiliaryFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Update kernel constants. +void +pylith::sources::MomentTensorForce::_updateKernelConstants(const PylithReal dt) { + assert(_sourceTimeFunction); + _sourceTimeFunction->updateKernelConstants(&_kernelConstants, dt); +} // _updateKernelConstants + + +// --------------------------------------------------------------------------------------------------------------------- +// Get derived factory associated with physics. +pylith::topology::FieldFactory* +pylith::sources::MomentTensorForce::_getDerivedFactory(void) { + return _derivedFactory; +} // _getDerivedFactory + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for RHS residual G(t,s). +void +pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator="< kernels(1); + switch (_formulation) { + case QUASISTATIC: { + break; + } // QUASISTATIC + case DYNAMIC_IMEX: + case DYNAMIC: { + // Velocity + const PetscPointFunc g0v = NULL; + const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); + kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::RHS, g0v, g1v); + // kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + break; + } // DYNAMIC + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsResidual + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for computing updated state variables in auxiliary field. +void +pylith::sources::MomentTensorForce::_setKernelsUpdateStateVars(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsUpdateStateVars(integrator="< kernels; + _sourceTimeFunction->addKernelsUpdateStateVars(&kernels, coordsys); + + integrator->setKernelsUpdateStateVars(kernels); + + PYLITH_METHOD_END; +} // _setKernelsUpdateStateVars + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for computing derived field. +void +pylith::sources::MomentTensorForce::_setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, + const topology::Field& solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsDerivedField(integrator="<getTimeScale(); + assert(_normalizer); + const PylithScalar timeScale = _normalizer->getTimeScale(); AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); } // if } diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index 540649d2d9..17bd6252ac 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -95,7 +95,8 @@ public: */ void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, - const PylithReal timeScale); + const PylithReal timeScale, + spatialdata::units::Nondimensional* _normalizer); // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/modulesrc/sources/TimeHistoryWavelet.i b/modulesrc/sources/TimeHistoryWavelet.i index 31cd1c5851..1f7b2f8143 100644 --- a/modulesrc/sources/TimeHistoryWavelet.i +++ b/modulesrc/sources/TimeHistoryWavelet.i @@ -89,7 +89,8 @@ public: */ void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, - const PylithReal timeScale); + const PylithReal timeScale, + spatialdata::units::Nondimensional* _normalizer); }; diff --git a/pylith/sources/TimeHistoryWavelet.py b/pylith/sources/TimeHistoryWavelet.py index f267f8705c..2b67f9b098 100644 --- a/pylith/sources/TimeHistoryWavelet.py +++ b/pylith/sources/TimeHistoryWavelet.py @@ -32,6 +32,9 @@ class TimeHistoryWavelet(SourceTimeFunctionMomentTensorForce, ModuleTimeHistoryW import pythia.pyre.inventory + useTimeHistory = pythia.pyre.inventory.bool("use_time_history", default=True) + useTimeHistory.meta['tip'] = "Use time history term in time-dependent expression." + dbTimeHistory = pythia.pyre.inventory.facility( "time_history", factory=NullComponent, family="temporal_database") dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time." @@ -50,8 +53,23 @@ def _defaults(self): def preinitialize(self, problem): SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) - + ModuleTimeHistoryWavelet.useTimeHistory(self, self.useTimeHistory) + if not isinstance(self.dbTimeHistory, NullComponent): + ModuleTimeHistoryWavelet.setTimeHistoryDB( + self, self.dbTimeHistory) return + + def _validate(self, context): + if isinstance(self.inventory.dbTimeHistory, NullComponent): + trait = self.inventory.getTrait("time_history") + self._validationError(context, trait, + f"Missing time history database for time history wavelet source '{self.aliases[-1]}'.") + + def _validationError(self, context, trait, msg): + from pythia.pyre.inventory.Item import Item + error = ValueError(msg) + descriptor = self.getTraitDescriptor(trait.name) + context.error(error, items=[Item(trait, descriptor)]) # PRIVATE METHODS //////////////////////////////////////////////////// From 6fa92265a3590be5ae6c294567ed0407e591697d Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 13 Jun 2024 16:44:54 -0600 Subject: [PATCH 37/65] Updated for MPI --- libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index b3375e994a..a9328707a8 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -131,11 +131,6 @@ pylith::sources::AuxiliaryFactorySourceTime::updateAuxiliaryField(pylith::topolo const PylithReal timeScale, spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { PYLITH_METHOD_BEGIN; - // pythia::journal::debug_t debug(_TimeDependentAuxiliaryFactory::genericComponent); - // debug << pythia::journal::at(__HERE__) - // << "TimeDependentAuxiliaryFactory::updateAuxiliaryField(auxiliaryField="<getSubfieldInfo("time_history_start_time").index; From fbc9bd6964f2cbe8759ad74585716cc44eef7c13 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Mon, 1 Jul 2024 17:55:23 -0700 Subject: [PATCH 38/65] remembered r_e constant --- libsrc/pylith/fekernels/WellboreSource.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/fekernels/WellboreSource.cc b/libsrc/pylith/fekernels/WellboreSource.cc index d178a4c34d..159fbcbfb8 100644 --- a/libsrc/pylith/fekernels/WellboreSource.cc +++ b/libsrc/pylith/fekernels/WellboreSource.cc @@ -61,6 +61,8 @@ pylith::fekernels::WellboreSource::f0p(const PylithInt dim, const PylithInt i_wellborePressure = 5; const PylithInt i_wellboreCharacter = 6; const PylithInt i_elementDimensions = 7; + const PylithInt i_r_e_constant = 8; + const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; const PylithScalar pressure = s[sOff[i_pressure]]; @@ -73,8 +75,8 @@ pylith::fekernels::WellboreSource::f0p(const PylithInt dim, const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; - PylithScalar r_e = 0.28 * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / - ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); + PylithScalar r_e = r_e_constant * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / + ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); // Well Index, L**3 PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); From 2fea53c664b819bc4d56840ee72162e59965dbc5 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 12 Jul 2024 22:19:12 -0700 Subject: [PATCH 39/65] Added squarepulsesource, still issues --- libsrc/pylith/fekernels/SquarePulseSource.cc | 7 +- libsrc/pylith/fekernels/TimeHistorySource.hh | 596 ++++++++++++++++++ libsrc/pylith/fekernels/WellboreSource.cc | 17 +- .../AuxiliaryFactorySquarePulseSource.cc | 2 +- .../AuxiliaryFactoryTimeHistorySource.cc | 421 +++++++++++++ .../AuxiliaryFactoryTimeHistorySource.hh | 114 ++++ libsrc/pylith/sources/SquarePulseSource.cc | 7 + libsrc/pylith/sources/SquarePulseSource.hh | 12 +- libsrc/pylith/sources/TimeHistorySource.cc | 424 +++++++++++++ libsrc/pylith/sources/TimeHistorySource.hh | 156 +++++ .../sources/AuxSubfieldsMomentTensorForce.py | 4 +- pylith/sources/AuxSubfieldsPointForce.py | 4 +- .../sources/AuxSubfieldsSquarePulseSource.py | 5 + pylith/sources/AuxSubfieldsWellboreSource.py | 3 + pylith/sources/TimeHistorySource.py | 113 ++++ pylith/sources/TimeHistoryWavelet.py | 8 + 16 files changed, 1882 insertions(+), 11 deletions(-) create mode 100644 libsrc/pylith/fekernels/TimeHistorySource.hh create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc create mode 100644 libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh create mode 100644 libsrc/pylith/sources/TimeHistorySource.cc create mode 100644 libsrc/pylith/sources/TimeHistorySource.hh create mode 100644 pylith/sources/TimeHistorySource.py diff --git a/libsrc/pylith/fekernels/SquarePulseSource.cc b/libsrc/pylith/fekernels/SquarePulseSource.cc index b7861c8394..7f22562282 100644 --- a/libsrc/pylith/fekernels/SquarePulseSource.cc +++ b/libsrc/pylith/fekernels/SquarePulseSource.cc @@ -54,10 +54,15 @@ pylith::fekernels::SquarePulseSource::f0p(const PylithInt dim, // Incoming re-packed auxiliary field. const PylithInt i_volumeFlowRate = 0; + const PylithInt i_timeDelay = 1; const PylithScalar volumeFlowRate = a[aOff[i_volumeFlowRate]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - f0[0] += volumeFlowRate; + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; + + f0[0] += volumeFlowRate * squarewavelet; } // f0p diff --git a/libsrc/pylith/fekernels/TimeHistorySource.hh b/libsrc/pylith/fekernels/TimeHistorySource.hh new file mode 100644 index 0000000000..ce94532f3c --- /dev/null +++ b/libsrc/pylith/fekernels/TimeHistorySource.hh @@ -0,0 +1,596 @@ +/* + * ================================================================================================ + * 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 + +/** @file libsrc/fekernels/SquarePulseSource.h + * + * Kernels for computing value from parameters for Neumann time dependent boundary conditions. + * + * \int_{\Gamma_\tau} \trialvec[u] \vec{\tau}(\vec{x},t) d\Gamma + */ + +// Include directives --------------------------------------------------- +#include "pylith/fekernels/fekernelsfwd.hh" // forward declarations + +#include "pylith/fekernels/BoundaryDirections.hh" // USES tangential_directions() +#include "pylith/fekernels/TimeDependentFn.hh" // USES TimeDependentFn + +#include "pylith/utils/types.hh" + +#include // USES assert() + +class pylith::fekernels::SquarePulseSource { +public: + + /** Kernel interface. + * + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] n Unit vector normal to boundary. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. + */ + + // -------------------------------------------------------------------------------------------- + /** Scalar initial value term for time-dependent boundary condition. + * + * f_0(x) + */ + static inline + void f0_initial_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::initial_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_initial_scalar + + // -------------------------------------------------------------------------------------------- + /** Vector initial value term for time-dependent boundary condition. + * + * f_0(x) + */ + static inline + void f0_initial_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::initial_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_initial_vector + + // -------------------------------------------------------------------------------------------- + /** Scalar rate term for time-dependent boundary condition. + * + * \dot{f}_1(x) * (t-t_1(x)) for t >= t_1(x). + */ + static inline + void f0_rate_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::rate_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_rate_scalar + + // -------------------------------------------------------------------------------------------- + /** Vector rate term for time-dependent boundary condition. + * + * \dot{f}_1(x) * (t-t_1(x)) for t >= t_1(x). + */ + static inline + void f0_rate_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::rate_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_rate_vector + + // -------------------------------------------------------------------------------------------- + /** Scalar time history term for time-dependent boundary condition. + * + * f_2(x) * a(t-t_2(x)) for t >= t_2(x). + */ + static inline + void f0_timeHistory_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::timeHistory_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_timeHistory_scalar + + // -------------------------------------------------------------------------------------------- + /** Vector time history term for time-dependent boundary condition. + * + * f_2(x) * a(t-t_2(x)) for t >= t_2(x). + */ + static inline + void f0_timeHistory_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::timeHistory_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_timeHistory_vector + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition scalar value using initial and rate terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + */ + static inline + void f0_initialRate_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::initialRate_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_initialRate_scalar + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition vector value using initial and rate terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + */ + static inline + void f0_initialRate_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::initialRate_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_initialRate_vector + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition scalar value using initial and time history terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_initialTimeHistory_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::initialTimeHistory_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_initialTimeHistory_scalar + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition vector value using initial and time history terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_initialTimeHistory_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::initialTimeHistory_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_initialTimeHistory_vector + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition scalar value using rate and time history terms. + * + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_rateTimeHistory_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::rateTimeHistory_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_rateTimeHistory_scalar + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition vector value using rate and time history terms. + * + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_rateTimeHistory_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::rateTimeHistory_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_rateTimeHistory_vector + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition scalar value using initial, rate ,and time history terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_initialRateTimeHistory_scalar(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + pylith::fekernels::TimeDependentFn::initialRateTimeHistory_scalar_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, f0); + } // f0_initialRateTimeHistory_scalar + + // -------------------------------------------------------------------------------------------- + /** Compute boundary condition vector value using initial, rate, and time history terms. + * + * f_0(x) + + * \dot{f}_1(x) * H(t-t_1(x)) + + * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + */ + static inline + void f0_initialRateTimeHistory_vector(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal x[], + const PylithReal n[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar f0[]) { + PylithScalar values[3] = { 0.0, 0.0, 0.0 }; + pylith::fekernels::TimeDependentFn::initialRateTimeHistory_vector_boundary( + dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, + t, x, n, numConstants, constants, values); + + switch (dim) { + case 2: + pylith::fekernels::BoundaryDirections::toXY(f0, values, n); + break; + case 3: { + const PylithScalar* refDir1 = &constants[0]; + const PylithScalar* refDir2 = &constants[3]; + pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); + break; + } + default: + assert(0); + } // switch + } // f0_initialRateTimeHistory_vector + +}; // SquarePulseSource + +// End of file diff --git a/libsrc/pylith/fekernels/WellboreSource.cc b/libsrc/pylith/fekernels/WellboreSource.cc index 159fbcbfb8..d0f742a508 100644 --- a/libsrc/pylith/fekernels/WellboreSource.cc +++ b/libsrc/pylith/fekernels/WellboreSource.cc @@ -62,7 +62,13 @@ pylith::fekernels::WellboreSource::f0p(const PylithInt dim, const PylithInt i_wellboreCharacter = 6; const PylithInt i_elementDimensions = 7; const PylithInt i_r_e_constant = 8; + const PylithInt i_timeDelay = 9; + const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; const PylithScalar pressure = s[sOff[i_pressure]]; @@ -80,7 +86,7 @@ pylith::fekernels::WellboreSource::f0p(const PylithInt dim, // Well Index, L**3 PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); - f0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity) * (pressure - wellborePressure); + f0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity) * (pressure - wellborePressure) * squarewavelet; } // f0p @@ -115,6 +121,7 @@ pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, const PylithInt i_wellboreCharacter = 6; const PylithInt i_elementDimensions = 7; const PylithInt i_r_e_constant = 8; + const PylithInt i_timeDelay = 9; const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; @@ -124,12 +131,16 @@ pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; PylithScalar r_e = r_e_constant * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); - PylithScalar W = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); + PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); - Jf0[0] += W * wellboreCharacter * (1.0 / fluidViscosity); + Jf0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity)* squarewavelet; } // Jf0pp diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc index f2cf200fdd..43f7b78ee0 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc @@ -61,7 +61,7 @@ pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) { // description.componentNames.resize(1); description.componentNames[0] = subfieldName; description.scale = lengthScale * lengthScale * lengthScale / timeScale; - description.validator = pylith::topology::FieldQuery::validatorPositive; + description.validator = NULL; _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); diff --git a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc new file mode 100644 index 0000000000..f9ef22974a --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc @@ -0,0 +1,421 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include + +#include "AuxiliaryFactorySquarePulseSource.hh" // implementation of object methods + +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh + +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD* +#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* + +#include + +// --------------------------------------------------------------------------------------------------------------------- +namespace pylith { + namespace sources { + class _AuxiliaryFactorySquarePulseSource { +public: + + ///< Names of field components in XYZ coordinate system. + static const char* componentsXYZ[3]; + + ///< Names of field components in 2-D tangential/normal coordinate system. + static const char* componentsTN[2]; + + ///< Names of field components in 3-D tangential/normal coordinate system. + static const char* componentsTTN[3]; + + static const char* genericComponent; + }; // _AuxiliaryFactorySquarePulseSource + + const char* _AuxiliaryFactorySquarePulseSource::componentsXYZ[3] = { "_x", "_y", "_z" }; + const char* _AuxiliaryFactorySquarePulseSource::componentsTN[2] = { "_tangential", "_normal" }; + const char* _AuxiliaryFactorySquarePulseSource::componentsTTN[3] = { "_tangential_1", "_tangential_2", "_normal" }; + + const char* _AuxiliaryFactorySquarePulseSource::genericComponent = "auxiliaryfactorysquarepulsesource"; + } // sources +} // pylith + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(const ReferenceEnum reference) : + _auxComponents(reference) { + GenericComponent::setName("auxiliaryfactorysquarepulsesource"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::AuxiliaryFactorySquarePulseSource::~AuxiliaryFactorySquarePulseSource(void) {} + + +// --------------------------------------------------------------------------------------------------------------------- +// Set names of vector components in auxiliary subfield. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::_setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("_setVectorFieldComponentNames(description)"); + + assert(description); + + const char** componentNames = NULL; + if (XYZ == _auxComponents) { + componentNames = _AuxiliaryFactorySquarePulseSource::componentsXYZ; + } else if (TANGENTIAL_NORMAL == _auxComponents) { + if (2 == _spaceDim) { + componentNames = _AuxiliaryFactorySquarePulseSource::componentsTN; + } else if (3 == _spaceDim) { + componentNames = _AuxiliaryFactorySquarePulseSource::componentsTTN; + } // if/else + } // if/else + if (!componentNames) { + PYLITH_JOURNAL_ERROR("Unknown case for auxiliary component reference ("<<_auxComponents<<") and spatial dimension ("<<_spaceDim<<")."); + throw std::logic_error("Unknown case for auxiliary component reference and spatial dimension."); + } // if + + assert(size_t(_spaceDim) == description->numComponents); + for (int i = 0; i < _spaceDim; ++i) { + description->componentNames[i] = description->label + std::string(componentNames[i]); + } // for + + PYLITH_METHOD_END; +} // _setVectorFieldComponentNames + + +// ---------------------------------------------------------------------- +// Add fluid density subfield to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) { // fluidDensity + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addVolumeFlowRate(void)"); + + const char *subfieldName = "volume_flow_rate"; + const PylithReal lengthScale = _normalizer->getLengthScale(); + const PylithReal timeScale = _normalizer->getTimeScale(); + + pylith::topology::Field::Description description; + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = lengthScale * lengthScale * lengthScale / timeScale; + description.validator = pylith::topology::FieldQuery::validatorPositive; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addVolumeFlowRate + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time delay of source time function to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeDelay(void) { // timeDelay + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); + + const char* subfieldName = "time_delay"; + + pylith::topology::Field::Description description; + const PylithReal timeScale = _normalizer->getTimeScale(); + description.label = subfieldName; + description.alias = subfieldName; + description.vectorFieldType = pylith::topology::Field::SCALAR; + description.numComponents = 1; + description.componentNames.resize(1); + description.componentNames[0] = subfieldName; + description.scale = timeScale; + description.validator = pylith::topology::FieldQuery::validatorNonnegative; + + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeDelay + + +// --------------------------------------------------------------------------------------------------------------------- +// Add initial amplitude field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addInitialAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addInitialAmplitude(void)"); + + const char* subfieldName = "initial_amplitude"; + + assert(_defaultDescription); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.validator = NULL; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::initialAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addInitialAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add rate amplitude field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addRateAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addRateAmplitude(void)"); + + const char* subfieldName = "rate_amplitude"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.scale = _defaultDescription->scale / _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::addRateAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addRateAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add rate start time field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addRateStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addRateStartTime(void)"); + + const char* subfieldName = "rate_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addRateStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history amplitude field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryAmplitude(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryAmplitude(void)"); + + const char* subfieldName = "time_history_amplitude"; + + assert(_defaultDescription); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + switch (subfieldDescription.vectorFieldType) { + case pylith::topology::FieldBase::SCALAR: { + const size_t numComponents = 1; + assert(numComponents == subfieldDescription.numComponents); + assert(numComponents == subfieldDescription.componentNames.size()); + subfieldDescription.componentNames[0] = subfieldName; + break; + } // SCALAR + case pylith::topology::FieldBase::VECTOR: { + _setVectorFieldComponentNames(&subfieldDescription); + break; + } // VECTOR + default: + PYLITH_JOURNAL_ERROR("Unknown vector field case."); + throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::addTimeHistoryAmplitude()."); + } // switch + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryAmplitude + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history start time field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryStartTime(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); + + const char* subfieldName = "time_history_start_time"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); + this->setSubfieldQuery(subfieldName); + + PYLITH_METHOD_END; +} // addTimeHistoryStartTime + + +// --------------------------------------------------------------------------------------------------------------------- +// Add time history value field to auxiliary fields. +void +pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryValue(void) { + PYLITH_METHOD_BEGIN; + PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); + + const char* subfieldName = "time_history_value"; + + assert(_defaultDescription); + assert(_normalizer); + pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); + subfieldDescription.label = subfieldName; + subfieldDescription.alias = subfieldName; + subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; + subfieldDescription.numComponents = 1; + subfieldDescription.componentNames.resize(1); + subfieldDescription.componentNames[0] = subfieldName; + subfieldDescription.validator = NULL; + + _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); + // No subfield query; populated by integrator or constraint at beginning of time step. + + PYLITH_METHOD_END; +} // addTimeHistoryValue + + +// --------------------------------------------------------------------------------------------------------------------- +void +pylith::sources::AuxiliaryFactorySquarePulseSource::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { + PYLITH_METHOD_BEGIN; + pythia::journal::debug_t debug(_AuxiliaryFactorySquarePulseSource::genericComponent); + debug << pythia::journal::at(__HERE__) + << "AuxiliaryFactorySquarePulseSource::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); + PetscInt pStart = 0, pEnd = 0; + err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); + pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); + PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); + + // Compute offset of time history subfields in auxiliary field. + const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; + const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; + + // Loop over all points in section. + for (PetscInt p = pStart; p < pEnd; ++p) { + // Skip points without values in section. + if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} + + // Get starting time and compute relative time for point. + const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); + const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; + const PylithScalar tRel = t - tStart; + + // Query time history for value (normalized amplitude). + PylithScalar value = 0.0; + if (tRel >= 0.0) { + PylithScalar tDim = tRel * timeScale; + const int err = dbTimeHistory->query(&value, tDim); + if (err) { + std::ostringstream msg; + msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; + throw std::runtime_error(msg.str()); + } // if + } // if + + // Update value (normalized amplitude) in auxiliary field. + const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); + auxiliaryFieldArray[offValue] = value; + } // for + + PYLITH_METHOD_END; +} // updateAuxiliaryField + + +// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh new file mode 100644 index 0000000000..33488295c6 --- /dev/null +++ b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh @@ -0,0 +1,114 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2017 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// +#pragma once + +/** @file libsrc/sources/AuxiliaryFactorySquarePulseSource.hh + * + * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. + */ + +#if !defined(pylith_sources_auxiliaryfactorysquarepulsesource_hh) +#define pylith_sources_auxiliaryfactorysquarepulsesource_hh + +#include "pylith/sources/sourcesfwd.hh" // forward declarations +#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory + +#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField + +class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory { + friend class TestAuxiliaryFactorySquarePulseSource; // unit testing + + // PUBLIC ENUMS //////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + enum ReferenceEnum { + XYZ=0, ///< Coordinate directions (x, y, z). + TANGENTIAL_NORMAL=1, ///< Directions tangential and normal to the boundary (tangential_1, tangential_2, normal). + }; + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + AuxiliaryFactorySquarePulseSource(const ReferenceEnum reference=XYZ); + + /// Destructor. + virtual ~AuxiliaryFactorySquarePulseSource(void); + + /// Add fluid density subfield to auxiliary subfields. + void addVolumeFlowRate(void); + + /// Add time delay subfield to auxiliary subfields. + void addTimeDelay(void); + + /// Add initial amplitude field to auxiliary fields. + void addInitialAmplitude(void); + + /// Add rate amplitude field to auxiliary fields. + void addRateAmplitude(void); + + /// Add rate start time amplitude field to auxiliary fields. + void addRateStartTime(void); + + /// Add time history amplitude field to auxiliary fields. + void addTimeHistoryAmplitude(void); + + /// Add time history start time field to auxiliary fields. + void addTimeHistoryStartTime(void); + + /// Add time history value field to auxiliary fields. + void addTimeHistoryValue(void); + + /** Update auxiliary field for current time. + * + * @param[inout] auxiliaryField Auxiliary field to update. + * @param[in] t Current time. + * @param[in] timeScale Time scale for nondimensionalization. + * @param[in] dbTimeHistory Time history database. + */ + static + void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, + const PylithReal t, + const PylithReal timeScale, + spatialdata::spatialdb::TimeHistory* const dbTimeHistory); + + // PRIVATE METHODS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + /** Set names of vector field components in auxiliary subfield. + * + * @param[in] description Subfield description. + */ + void _setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description); + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + ReferenceEnum _auxComponents; ///< Coordinate system reference for field components. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + AuxiliaryFactorySquarePulseSource(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented. + const AuxiliaryFactorySquarePulseSource &operator=(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented + +}; // class AuxiliaryFactorySquarePulseSource + +#endif // pylith_sources_auxiliaryfactorysquarepulsesource_hh + +// End of file diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc index 6461dc64d6..f1b5917786 100644 --- a/libsrc/pylith/sources/SquarePulseSource.cc +++ b/libsrc/pylith/sources/SquarePulseSource.cc @@ -168,6 +168,13 @@ pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology: // add in aux specific to square pulse _auxiliaryFactory->addVolumeFlowRate(); // 0 + _auxiliaryFactory->addTimeDelay(); // 1 + + auxiliaryField->subfieldsSetup(); + auxiliaryField->createDiscretization(); + pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); + auxiliaryField->allocate(); + auxiliaryField->createOutputVector(); assert(_auxiliaryFactory); _auxiliaryFactory->setValuesFromDB(); diff --git a/libsrc/pylith/sources/SquarePulseSource.hh b/libsrc/pylith/sources/SquarePulseSource.hh index 24940de773..14a8ce0919 100644 --- a/libsrc/pylith/sources/SquarePulseSource.hh +++ b/libsrc/pylith/sources/SquarePulseSource.hh @@ -28,12 +28,12 @@ #include "pylith/sources/Source.hh" // ISA Source -class pylith::sources::SquarePulseSource : public pylith::sources::Source -{ +class pylith::sources::SquarePulseSource : public pylith::sources::Source { friend class TestSquarePulseSource; // unit testing // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// public: + /// Default constructor. SquarePulseSource(void); @@ -103,6 +103,7 @@ public: // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// protected: + /** Get auxiliary factory associated with physics. * * @return Auxiliary factory for physics object. @@ -111,6 +112,7 @@ protected: // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: + /** Set kernels for residual. * * @param[out] integrator Integrator for source. @@ -129,16 +131,22 @@ private: // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: + bool _useInertia; ///< Flag to include inertial term. spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. pylith::sources::AuxiliaryFactorySquarePulseSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. + std::string _scaleName; ///< Name of scale associated with Neumann boundary condition. + bool _useInitial; ///< Use initial value term. + bool _useRate; ///< Use rate term. bool _useTimeHistory; ///< Use time history term. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// private: + SquarePulseSource(const SquarePulseSource &); ///< Not implemented. const SquarePulseSource &operator=(const SquarePulseSource &); /// Not implemented. + }; // class SquarePulseSource diff --git a/libsrc/pylith/sources/TimeHistorySource.cc b/libsrc/pylith/sources/TimeHistorySource.cc new file mode 100644 index 0000000000..a54eb8e831 --- /dev/null +++ b/libsrc/pylith/sources/TimeHistorySource.cc @@ -0,0 +1,424 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +#include +#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory +#include "pylith/sources/SquarePulseSource.hh" // implementation of object methods + +#include "pylith/sources/AuxiliaryFactorySquarePulseSource.hh" // USES AuxiliaryFactorySquarePulseSource +#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo +#include "pylith/topology/FieldOps.hh" // USES FieldOps + +#include "pylith/fekernels/SquarePulseSource.hh" // USES SquarePulseSource kernels + +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* +#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* + +#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys +#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional + +#include // USES typeid() + +// --------------------------------------------------------------------------------------------------------------------- +typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; +typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; +typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; +typedef pylith::feassemble::Integrator::EquationPart EquationPart; + +// --------------------------------------------------------------------------------------------------------------------- +namespace pylith { + namespace sources { + class _SquarePulseSource { + // PUBLIC MEMBERS ////////////////////////////////////////////////////////////////////////////////////////// +public: + + /** Set kernels for RHS residual. + * + * @param[out] integrator Integrator for source condition. + * @param[in] sources Square Pulse time-dependent source condition. + * @param[in] solution Solution field. + * @param[in] formulation Formulation for equations. + */ + static + void setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const pylith::sources::SquarePulseSource& sources, + const pylith::topology::Field& solution, + const pylith::problems::Physics::FormulationEnum formulation); + + static const char* pyreComponent; + + }; // _SquarePulseSource + const char* _SquarePulseSource::pyreComponent = "squarepulsesource"; + + } // sources +} // pylith + +// --------------------------------------------------------------------------------------------------------------------- +// Default constructor. +pylith::sources::SquarePulseSource::SquarePulseSource(void) : + _dbTimeHistory(NULL), + _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource(pylith::sources::AuxiliaryFactorySquarePulseSource::XYZ)), + _useInitial(true), + _useRate(false), + _useTimeHistory(false) { + PyreComponent::setName(_SquarePulseSource::pyreComponent); + + pylith::utils::PyreComponent::setName("squarepulsesource"); +} // constructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Destructor. +pylith::sources::SquarePulseSource::~SquarePulseSource(void) { + deallocate(); +} // destructor + + +// --------------------------------------------------------------------------------------------------------------------- +// Deallocate PETSc and local data structures. +void +pylith::sources::SquarePulseSource::deallocate(void) { + Source::deallocate(); + + delete _auxiliaryFactory; + _auxiliaryFactory = NULL; +} // deallocate + + +// --------------------------------------------------------------------------------------------------------------------- +// Set time history database. +void +pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { + PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); + + _dbTimeHistory = th; +} // setTimeHistoryDB + + +// --------------------------------------------------------------------------------------------------------------------- +// Get time history database. +const spatialdata::spatialdb::TimeHistory * +pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { + return _dbTimeHistory; +} // getTimeHistoryDB + + +// --------------------------------------------------------------------------------------------------------------------- +// Use time history term in time history expression. +void +pylith::sources::SquarePulseSource::useTimeHistory(const bool value) { + PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); + + _useTimeHistory = value; +} // useTimeHistory + + +// --------------------------------------------------------------------------------------------------------------------- +// Get flag associated with using time history term in time history expression. +bool +pylith::sources::SquarePulseSource::useTimeHistory(void) const { + return _useTimeHistory; +} // useTimeHistory + + +// --------------------------------------------------------------------------------------------------------------------- +// Verify configuration is acceptable. +void +pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); + + // Verify solution contains expected fields. + if (!solution.hasSubfield("pressure")) { + throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'SquarePulseSource'."); + } // if + + PYLITH_METHOD_END; +} // verifyConfiguration + + +// --------------------------------------------------------------------------------------------------------------------- +// Create integrator and set kernels. +pylith::feassemble::Integrator * +pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); + + pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); + + pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); + assert(integrator); + integrator->setLabelName(getLabelName()); + integrator->setLabelValue(getLabelValue()); + // printf("In SquarePulseSource end\n"); + // DMView(dmSoln, NULL); + + _setKernelsResidual(integrator, solution); + _setKernelsJacobian(integrator, solution); + + PYLITH_METHOD_RETURN(integrator); +} // createIntegrator + + +// --------------------------------------------------------------------------------------------------------------------- +// Create auxiliary field. +pylith::topology::Field * +pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); + + pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); + assert(auxiliaryField); + auxiliaryField->setLabel("SquarePulseSource auxiliary field"); + + assert(_normalizer); + _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + + // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. + + // :ATTENTION: In quasi-static problems, the time scale is usually quite large + // (order of tens to hundreds of years), which means that the density scale is very large, + // and the acceleration scale is very small. Nevertheless, density times gravitational + // acceleration will have a scale of pressure divided by length and should be within a few orders + // of magnitude of 1. + + // add in aux specific to square pulse + _auxiliaryFactory->addVolumeFlowRate(); // 0 + + if (_useInitial) { + _auxiliaryFactory->addInitialAmplitude(); + } // if + if (_useRate) { + _auxiliaryFactory->addRateAmplitude(); + _auxiliaryFactory->addRateStartTime(); + } // _useRate + if (_useTimeHistory) { + _auxiliaryFactory->addTimeHistoryAmplitude(); + _auxiliaryFactory->addTimeHistoryStartTime(); + _auxiliaryFactory->addTimeHistoryValue(); + if (_dbTimeHistory) { + _dbTimeHistory->open(); + } // if + } // _useTimeHistory + + assert(_auxiliaryFactory); + _auxiliaryFactory->setValuesFromDB(); + + // Debug option + auxiliaryField->view("SquarePulse auxiliary field."); + + PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField + + +// --------------------------------------------------------------------------------------------------------------------- +// Create derived field. +pylith::topology::Field * +pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh) { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); + + PYLITH_METHOD_RETURN(NULL); +} // createDerivedField + + +// --------------------------------------------------------------------------------------------------------------------- +// Get auxiliary factory associated with physics. +pylith::feassemble::AuxiliaryFactory * +pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { + return _auxiliaryFactory; +} // _getAuxiliaryFactory + + +// // +// --------------------------------------------------------------------------------------------------------------------- +// // Set kernels for LHS residual F(t,s,\dot{s}). +// void +// pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, +// const topology::Field &solution) const { +// PYLITH_METHOD_BEGIN; +// PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << +// ")"); + +// const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + +// std::vector kernels; + +// switch (_formulation) { +// case QUASISTATIC: +// { +// // Pressure +// const PetscPointFunc f0p = pylith::fekernels::SquarePulseSource::f0p; +// const PetscPointFunc f1p = NULL; + +// kernels.resize(1); +// kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::LHS, f0p, f1p); +// break; +// } // QUASISTATIC +// case DYNAMIC_IMEX: +// { +// break; +// } // DYNAMIC +// case DYNAMIC: +// { +// break; +// } // DYNAMIC +// default: +// PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); +// } // switch + +// assert(integrator); +// integrator->setKernelsResidual(kernels, solution); + +// PYLITH_METHOD_END; +// } // _setKernelsResidual + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for residual. +void +pylith::sources::_SquarePulseSource::setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const pylith::sources::SquarePulseSource& sources, + const topology::Field& solution, + const pylith::problems::Physics::FormulationEnum formulation) { + PYLITH_METHOD_BEGIN; + pythia::journal::debug_t debug(_SquarePulseSource::pyreComponent); + debug << pythia::journal::at(__HERE__) + << "setKernelsResidual(integrator="< kernels(1); + switch (formulation) { + case pylith::problems::Physics::QUASISTATIC: + kernels[0] = ResidualKernels(sources.getSubfieldName(), pylith::feassemble::Integrator::LHS, r0, r1); + break; + case pylith::problems::Physics::DYNAMIC_IMEX: + case pylith::problems::Physics::DYNAMIC: + kernels[0] = ResidualKernels(sources.getSubfieldName(), pylith::feassemble::Integrator::RHS, r0, r1); + break; + default: { + PYLITH_JOURNAL_LOGICERROR("Unknown formulation for equations ("<setKernelsResidual(kernels, solution); + + PYLITH_METHOD_END; +} // setKernelsResidual + + +// --------------------------------------------------------------------------------------------------------------------- +// Set kernels for LHS Jacobian F(t,s,\dot{s}). +void +pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const topology::Field &solution) const { + PYLITH_METHOD_BEGIN; + PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); + + const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); + + std::vector kernels; + + switch (_formulation) { + case QUASISTATIC: + { + const PetscPointJac Jf0pp = NULL; + const PetscPointJac Jf1pp = NULL; + const PetscPointJac Jf2pp = NULL; + const PetscPointJac Jf3pp = NULL; + + kernels.resize(1); + const EquationPart equationPart = pylith::feassemble::Integrator::LHS; + kernels[0] = JacobianKernels(getSubfieldName(), getSubfieldName(), equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); + break; + } // QUASISTATIC + case DYNAMIC: + case DYNAMIC_IMEX: + { + break; + } // DYNAMIC_IMEX + default: + PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); + } // switch + + assert(integrator); + integrator->setKernelsJacobian(kernels, solution); + + PYLITH_METHOD_END; +} // _setKernelsJacobian + + +// End of file diff --git a/libsrc/pylith/sources/TimeHistorySource.hh b/libsrc/pylith/sources/TimeHistorySource.hh new file mode 100644 index 0000000000..14a8ce0919 --- /dev/null +++ b/libsrc/pylith/sources/TimeHistorySource.hh @@ -0,0 +1,156 @@ +// -*- C++ -*- +// +// ---------------------------------------------------------------------- +// +// Brad T. Aagaard, U.S. Geological Survey +// Charles A. Williams, GNS Science +// Matthew G. Knepley, University of Chicago +// +// This code was developed as part of the Computational Infrastructure +// for Geodynamics (http://geodynamics.org). +// +// Copyright (c) 2010-2015 University of California, Davis +// +// See COPYING for license information. +// +// ---------------------------------------------------------------------- +// + +/** @file libsrc/sources/SquarePulseSource.hh + * + * @brief C++ class for solving squarepulsesource equation. + */ + +#if !defined(pylith_sources_squarepulsesource_hh) +#define pylith_sources_squarepulsesource_hh + +#include "sourcesfwd.hh" // forward declarations + +#include "pylith/sources/Source.hh" // ISA Source + +class pylith::sources::SquarePulseSource : public pylith::sources::Source { + friend class TestSquarePulseSource; // unit testing + + // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// +public: + + /// Default constructor. + SquarePulseSource(void); + + /// Destructor. + ~SquarePulseSource(void); + + /// Deallocate PETSc and local data structures. + void deallocate(void); + + /** Set time history database. + * + * @param[in] db Time history database. + */ + void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); + + /** Get time history database. + * + * @preturns Time history database. + */ + const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); + + /** Use time history term in time history expression. + * + * @param[in] value True if using time history term in expression. + */ + void useTimeHistory(const bool value); + + /** Get flag associated with using time history term in time history expression. + * + * @returns True if using time history term in expression, false otherwise. + */ + bool useTimeHistory(void) const; + + /** Verify configuration is acceptable. + * + * @param[in] solution Solution field. + */ + void verifyConfiguration(const pylith::topology::Field &solution) const; + + /** Create integrator and set kernels. + * + * @param[in] solution Solution field. + * + * @returns Integrator if applicable, otherwise NULL. + */ + pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); + + /** Create auxiliary field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Auxiliary field if applicable, otherwise NULL. + */ + pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + /** Create derived field. + * + * @param[in] solution Solution field. + * @param[in\ domainMesh Finite-element mesh associated with integration domain. + * + * @returns Derived field if applicable, otherwise NULL. + */ + pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, + const pylith::topology::Mesh &domainMesh); + + // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// +protected: + + /** Get auxiliary factory associated with physics. + * + * @return Auxiliary factory for physics object. + */ + pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + /** Set kernels for residual. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + /** Set kernels for Jacobian. + * + * @param[out] integrator Integrator for source. + * @param[in] solution Solution field. + */ + void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, + const pylith::topology::Field &solution) const; + + // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + bool _useInertia; ///< Flag to include inertial term. + spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. + pylith::sources::AuxiliaryFactorySquarePulseSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. + std::string _scaleName; ///< Name of scale associated with Neumann boundary condition. + + bool _useInitial; ///< Use initial value term. + bool _useRate; ///< Use rate term. + bool _useTimeHistory; ///< Use time history term. + + // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// +private: + + SquarePulseSource(const SquarePulseSource &); ///< Not implemented. + const SquarePulseSource &operator=(const SquarePulseSource &); /// Not implemented. + +}; + +// class SquarePulseSource + +#endif // pylith_sources_squarepulsesource_hh + +// End of file diff --git a/pylith/sources/AuxSubfieldsMomentTensorForce.py b/pylith/sources/AuxSubfieldsMomentTensorForce.py index 5285fba760..ee37d37836 100644 --- a/pylith/sources/AuxSubfieldsMomentTensorForce.py +++ b/pylith/sources/AuxSubfieldsMomentTensorForce.py @@ -34,9 +34,9 @@ class AuxSubfieldsMomentTensorForce(PetscComponent): "moment_tensor", family="auxiliary_subfield", factory=Subfield) momentTensor.meta['tip'] = "Moment tensor subfield." - TimeDelay = pythia.pyre.inventory.facility( + timeDelay = pythia.pyre.inventory.facility( "time_delay", family="auxiliary_subfield", factory=Subfield) - TimeDelay.meta['tip'] = "time delay subfield." + timeDelay.meta['tip'] = "time delay subfield." # PUBLIC METHODS ///////////////////////////////////////////////////// diff --git a/pylith/sources/AuxSubfieldsPointForce.py b/pylith/sources/AuxSubfieldsPointForce.py index 91345d3898..cc8213b5e4 100644 --- a/pylith/sources/AuxSubfieldsPointForce.py +++ b/pylith/sources/AuxSubfieldsPointForce.py @@ -33,8 +33,8 @@ class AuxSubfieldsPointForce(PetscComponent): pointForce = pythia.pyre.inventory.facility("point_force", family="auxiliary_subfield", factory=Subfield) pointForce.meta['tip'] = "Point Force subfield." - TimeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) - TimeDelay.meta['tip'] = "time delay subfield." + timeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) + timeDelay.meta['tip'] = "time delay subfield." # PUBLIC METHODS ///////////////////////////////////////////////////// diff --git a/pylith/sources/AuxSubfieldsSquarePulseSource.py b/pylith/sources/AuxSubfieldsSquarePulseSource.py index e821b93b12..d6d462fcd1 100644 --- a/pylith/sources/AuxSubfieldsSquarePulseSource.py +++ b/pylith/sources/AuxSubfieldsSquarePulseSource.py @@ -33,6 +33,11 @@ class AuxSubfieldsSquarePulseSource(PetscComponent): volumeFlowRate = pythia.pyre.inventory.facility("volume_flow_rate", family="auxiliary_subfield", factory=Subfield) volumeFlowRate.meta['tip'] = "Volume Flow Rate subfield." + timeDelay = pythia.pyre.inventory.facility( + "time_delay", family="auxiliary_subfield", factory=Subfield) + timeDelay.meta['tip'] = "time delay subfield." + + # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="auxsubfieldssquarepulsesource"): diff --git a/pylith/sources/AuxSubfieldsWellboreSource.py b/pylith/sources/AuxSubfieldsWellboreSource.py index f464a6f9ba..83d65bed34 100644 --- a/pylith/sources/AuxSubfieldsWellboreSource.py +++ b/pylith/sources/AuxSubfieldsWellboreSource.py @@ -60,6 +60,9 @@ class AuxSubfieldsWellboreSource(PetscComponent): "element_dimensions", family="auxiliary_subfield", factory=Subfield) elementDimensions.meta['tip'] = "Element dimension subfield." + timeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) + timeDelay.meta['tip'] = "time delay subfield." + # PUBLIC METHODS ///////////////////////////////////////////////////// def __init__(self, name="auxsubfieldswellboresource"): diff --git a/pylith/sources/TimeHistorySource.py b/pylith/sources/TimeHistorySource.py new file mode 100644 index 0000000000..fb7bbb94ca --- /dev/null +++ b/pylith/sources/TimeHistorySource.py @@ -0,0 +1,113 @@ +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University of Chicago +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2016 University of California, Davis +# +# See COPYING for license information. +# +# ---------------------------------------------------------------------- +# +# @file pylith/sources/SquarePulseSource.py +# +# @brief Python object for solving the squarepulsesource equation. +# +# Factory: source + +from .Source import Source +from .sources import SquarePulseSource as ModuleSquarePulseSource + + +class SquarePulseSource(Source, ModuleSquarePulseSource): + """Python source property manager. + + FACTORY: source + """ + + import pythia.pyre.inventory + + useInitial = pythia.pyre.inventory.bool("use_initial", default=True) + useInitial.meta['tip'] = "Use initial term in time-dependent expression." + + useRate = pythia.pyre.inventory.bool("use_rate", default=False) + useRate.meta['tip'] = "Use rate term in time-dependent expression." + + useTimeHistory = pythia.pyre.inventory.bool("use_time_history", default=True) + useTimeHistory.meta['tip'] = "Use time history term in time-dependent expression." + + dbTimeHistory = pythia.pyre.inventory.facility( + "time_history", factory=NullComponent, family="temporal_database") + dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time." + + # PUBLIC METHODS ///////////////////////////////////////////////////// + + def __init__(self, name="squarepulsesource"): + """Constructor. + """ + Source.__init__(self, name) + return + + def _defaults(self): + from .AuxSubfieldsSquarePulseSource import AuxSubfieldsSquarePulseSource + self.auxiliarySubfields = AuxSubfieldsSquarePulseSource("auxiliary_subfields") + + def preinitialize(self, problem): + """Do pre-initialization setup. + """ + from pylith.mpi.Communicator import mpi_is_root + if mpi_is_root(): + self._info.log( + "Performing minimal initialization of time-dependent Neumann boundary condition '%s'." % self.aliases[-1]) + + + Source.preinitialize(self, problem) + ModuleSquarePulseSource.useTimeHistory(self, self.useTimeHistory) + if not isinstance(self.dbTimeHistory, NullComponent): + ModuleSquarePulseSource.setTimeHistoryDB( + self, self.dbTimeHistory) + return + + def _validate(self, context): + if isinstance(self.inventory.dbTimeHistory, NullComponent): + trait = self.inventory.getTrait("time_history") + self._validationError(context, trait, + f"Missing time history database for time history wavelet source '{self.aliases[-1]}'.") + + def _validationError(self, context, trait, msg): + from pythia.pyre.inventory.Item import Item + error = ValueError(msg) + descriptor = self.getTraitDescriptor(trait.name) + context.error(error, items=[Item(trait, descriptor)]) + + + + + def preinitialize(self, problem): + """Setup source. + """ + Source.preinitialize(self, problem) + + + return + + def _createModuleObj(self): + """Create handle to C++ SquarePulseSource. + """ + ModuleSquarePulseSource.__init__(self) + return + + +# Factories + +def source(): + """Factory associated with SquarePulseSource. + """ + return SquarePulseSource() + + +# End of file diff --git a/pylith/sources/TimeHistoryWavelet.py b/pylith/sources/TimeHistoryWavelet.py index 2b67f9b098..1ec08a410b 100644 --- a/pylith/sources/TimeHistoryWavelet.py +++ b/pylith/sources/TimeHistoryWavelet.py @@ -52,6 +52,14 @@ def _defaults(self): self.auxiliarySubfields = AuxSubfieldsSourceTime("auxiliary_subfields") def preinitialize(self, problem): + """Do pre-initialization setup. + """ + from pylith.mpi.Communicator import mpi_is_root + if mpi_is_root(): + self._info.log( + "Performing minimal initialization of time-dependent Neumann boundary condition '%s'." % self.aliases[-1]) + + SourceTimeFunctionMomentTensorForce.preinitialize(self, problem) ModuleTimeHistoryWavelet.useTimeHistory(self, self.useTimeHistory) if not isinstance(self.dbTimeHistory, NullComponent): From 3a2e759db5da47e0fb54c3a2059426aa46eae043 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 16 Jul 2024 15:16:20 -0700 Subject: [PATCH 40/65] Updated to ensure compilation --- libsrc/pylith/fekernels/SquarePulseSource.cc | 2 +- libsrc/pylith/sources/SquarePulseSource.hh | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libsrc/pylith/fekernels/SquarePulseSource.cc b/libsrc/pylith/fekernels/SquarePulseSource.cc index 7f22562282..df1c5ccc97 100644 --- a/libsrc/pylith/fekernels/SquarePulseSource.cc +++ b/libsrc/pylith/fekernels/SquarePulseSource.cc @@ -50,7 +50,7 @@ pylith::fekernels::SquarePulseSource::f0p(const PylithInt dim, assert(f0); // Incoming re-packed solution field. - const PylithInt i_pressure = 1; + // const PylithInt i_pressure = 1; // Incoming re-packed auxiliary field. const PylithInt i_volumeFlowRate = 0; diff --git a/libsrc/pylith/sources/SquarePulseSource.hh b/libsrc/pylith/sources/SquarePulseSource.hh index 14a8ce0919..4c287fa594 100644 --- a/libsrc/pylith/sources/SquarePulseSource.hh +++ b/libsrc/pylith/sources/SquarePulseSource.hh @@ -135,10 +135,7 @@ private: bool _useInertia; ///< Flag to include inertial term. spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. pylith::sources::AuxiliaryFactorySquarePulseSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. - std::string _scaleName; ///< Name of scale associated with Neumann boundary condition. - bool _useInitial; ///< Use initial value term. - bool _useRate; ///< Use rate term. bool _useTimeHistory; ///< Use time history term. // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// From 808a7c3834b06f24048aa041299a7a78aeb08d1e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 12 Sep 2024 16:39:21 -0700 Subject: [PATCH 41/65] Midway through timehistory source --- libsrc/pylith/fekernels/Makefile.am | 1 + libsrc/pylith/fekernels/TimeHistorySource.hh | 698 ++++-------------- libsrc/pylith/fekernels/TimeHistoryWavelet.hh | 2 +- libsrc/pylith/fekernels/fekernelsfwd.hh | 4 + libsrc/pylith/sources/Makefile.am | 2 + libsrc/pylith/sources/TimeHistorySource.cc | 131 ++-- libsrc/pylith/sources/TimeHistorySource.hh | 26 +- libsrc/pylith/sources/sourcesfwd.hh | 3 + pylith/sources/TimeHistorySource.py | 26 +- pylith/sources/__init__.py | 1 + 10 files changed, 248 insertions(+), 646 deletions(-) diff --git a/libsrc/pylith/fekernels/Makefile.am b/libsrc/pylith/fekernels/Makefile.am index 815273565f..db02849a5e 100644 --- a/libsrc/pylith/fekernels/Makefile.am +++ b/libsrc/pylith/fekernels/Makefile.am @@ -33,6 +33,7 @@ subpkginclude_HEADERS = \ FaultCohesiveKin.hh \ WellboreSource.hh \ SquarePulseSource.hh \ + TimeHistorySource.hh \ SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ diff --git a/libsrc/pylith/fekernels/TimeHistorySource.hh b/libsrc/pylith/fekernels/TimeHistorySource.hh index ce94532f3c..ba1cfa0bbb 100644 --- a/libsrc/pylith/fekernels/TimeHistorySource.hh +++ b/libsrc/pylith/fekernels/TimeHistorySource.hh @@ -1,34 +1,41 @@ -/* - * ================================================================================================ - * This code is part of PyLith, developed through the Computational Infrastructure - * for Geodynamics (https://github.com/geodynamics/pylith). +/* -*- C++ -*- * - * 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. - * ================================================================================================= + * Brad T. Aagaard, U.S. Geological Survey + * Charles A. Williams, GNS Science + * Matthew G. Knepley, University of Chicago + * + * This code was developed as part of the Computational Infrastructure + * for Geodynamics (http:*geodynamics.org). + * + * Copyright (c) 2010-2015 University of California, Davis + * + * See COPYING for license information. + * + * ---------------------------------------------------------------------- */ -#pragma once -/** @file libsrc/fekernels/SquarePulseSource.h - * - * Kernels for computing value from parameters for Neumann time dependent boundary conditions. +/** @file libsrc/fekernels/TimeHistorySource.hh * - * \int_{\Gamma_\tau} \trialvec[u] \vec{\tau}(\vec{x},t) d\Gamma */ -// Include directives --------------------------------------------------- -#include "pylith/fekernels/fekernelsfwd.hh" // forward declarations +#if !defined(pylith_fekernels_timehistorysource_hh) +#define pylith_fekernels_timehistorysource_hh -#include "pylith/fekernels/BoundaryDirections.hh" // USES tangential_directions() -#include "pylith/fekernels/TimeDependentFn.hh" // USES TimeDependentFn +// Include directives --------------------------------------------------- +#include "fekernelsfwd.hh" // forward declarations #include "pylith/utils/types.hh" #include // USES assert() -class pylith::fekernels::SquarePulseSource { +// ===================================================================================================================== +// Kernels for the TimeHistory Source Time Function in 2D. +// ===================================================================================================================== + +class pylith::fekernels::TimeHistorySourcePlaneStrain { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// public: /** Kernel interface. @@ -48,549 +55,140 @@ public: * @param[in] a_x Gradient of auxiliary field. * @param[in] t Time for residual evaluation. * @param[in] x Coordinates of point evaluation. - * @param[in] n Unit vector normal to boundary. * @param[in] numConstants Number of registered constants. * @param[in] constants Array of registered constants. * @param[out] f0 [dim]. */ - // -------------------------------------------------------------------------------------------- - /** Scalar initial value term for time-dependent boundary condition. - * - * f_0(x) - */ - static inline - void f0_initial_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::initial_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_initial_scalar - - // -------------------------------------------------------------------------------------------- - /** Vector initial value term for time-dependent boundary condition. - * - * f_0(x) - */ - static inline - void f0_initial_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::initial_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_initial_vector - - // -------------------------------------------------------------------------------------------- - /** Scalar rate term for time-dependent boundary condition. - * - * \dot{f}_1(x) * (t-t_1(x)) for t >= t_1(x). - */ - static inline - void f0_rate_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::rate_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_rate_scalar - - // -------------------------------------------------------------------------------------------- - /** Vector rate term for time-dependent boundary condition. - * - * \dot{f}_1(x) * (t-t_1(x)) for t >= t_1(x). - */ - static inline - void f0_rate_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::rate_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_rate_vector - - // -------------------------------------------------------------------------------------------- - /** Scalar time history term for time-dependent boundary condition. + /** g0 function for pressure equation * - * f_2(x) * a(t-t_2(x)) for t >= t_2(x). */ - static inline - void f0_timeHistory_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::timeHistory_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_timeHistory_scalar - - // -------------------------------------------------------------------------------------------- - /** Vector time history term for time-dependent boundary condition. - * - * f_2(x) * a(t-t_2(x)) for t >= t_2(x). - */ - static inline - void f0_timeHistory_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::timeHistory_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_timeHistory_vector - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition scalar value using initial and rate terms. - * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - */ - static inline - void f0_initialRate_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::initialRate_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_initialRate_scalar - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition vector value using initial and rate terms. - * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - */ - static inline - void f0_initialRate_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::initialRate_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_initialRate_vector - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition scalar value using initial and time history terms. - * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). - */ - static inline - void f0_initialTimeHistory_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::initialTimeHistory_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_initialTimeHistory_scalar - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition vector value using initial and time history terms. - * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). - */ - static inline - void f0_initialTimeHistory_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::initialTimeHistory_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_initialTimeHistory_vector - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition scalar value using rate and time history terms. - * - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). - */ - static inline - void f0_rateTimeHistory_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::rateTimeHistory_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_rateTimeHistory_scalar - - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition vector value using rate and time history terms. - * - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). - */ - static inline - void f0_rateTimeHistory_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::rateTimeHistory_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_rateTimeHistory_vector + static + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + const PylithInt _numA = 3; + assert(_numA == numA); + assert(aOff); + assert(a); + + // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_volume_flow_rate = aOff[0]; + const PylithInt i_start_time = aOff[numA - 2]; + const PylithInt i_value = aOff[numA - 1]; + + PylithInt _dim = 2; + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorysourceCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "timehistorySource %f\n", (double)timehistorysource); + + const PylithScalar volume_flow_rate = a[aOff[i_volume_flow_rate]]; + f0[0] += volumeFlowRate * a[i_value]; + + // for (PylithInt i = 0; i < dim*dim; ++i) { + // g1[i] -= momentTensor[i] * a[i_value]; + // // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); + // } // for + } // g1v + +}; // TimeHistorySourcePlaneStrain + +// ===================================================================================================================== +// Kernels for the TimeHistory Source Time Function in 3D. +// ===================================================================================================================== + +class pylith::fekernels::TimeHistorySource3D { + // PUBLIC MEMBERS /////////////////////////////////////////////////////// +public: - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition scalar value using initial, rate ,and time history terms. + /** Kernel interface. * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). + * @param[in] dim Spatial dimension. + * @param[in] numS Number of registered subfields in solution field. + * @param[in] numA Number of registered subfields in auxiliary field. + * @param[in] sOff Offset of registered subfields in solution field [numS]. + * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. + * @param[in] s Solution field with all subfields. + * @param[in] s_t Time derivative of solution field. + * @param[in] s_x Gradient of solution field. + * @param[in] aOff Offset of registered subfields in auxiliary field [numA] + * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] + * @param[in] a Auxiliary field with all subfields. + * @param[in] a_t Time derivative of auxiliary field. + * @param[in] a_x Gradient of auxiliary field. + * @param[in] t Time for residual evaluation. + * @param[in] x Coordinates of point evaluation. + * @param[in] numConstants Number of registered constants. + * @param[in] constants Array of registered constants. + * @param[out] f0 [dim]. */ - static inline - void f0_initialRateTimeHistory_scalar(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - pylith::fekernels::TimeDependentFn::initialRateTimeHistory_scalar_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, f0); - } // f0_initialRateTimeHistory_scalar - // -------------------------------------------------------------------------------------------- - /** Compute boundary condition vector value using initial, rate, and time history terms. + /** g1 function for velocity equation * - * f_0(x) + - * \dot{f}_1(x) * H(t-t_1(x)) + - * f_2(x) * a(t-t_2(x)) * H(t-t_2(s). */ static inline - void f0_initialRateTimeHistory_vector(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal x[], - const PylithReal n[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - PylithScalar values[3] = { 0.0, 0.0, 0.0 }; - pylith::fekernels::TimeDependentFn::initialRateTimeHistory_vector_boundary( - dim, numS, numA, sOff, sOff_x, s, s_t, s_x, aOff, aOff_x, a, a_t, a_x, - t, x, n, numConstants, constants, values); - - switch (dim) { - case 2: - pylith::fekernels::BoundaryDirections::toXY(f0, values, n); - break; - case 3: { - const PylithScalar* refDir1 = &constants[0]; - const PylithScalar* refDir2 = &constants[3]; - pylith::fekernels::BoundaryDirections::toXYZ(f0, values, refDir1, refDir2, n); - break; - } - default: - assert(0); - } // switch - } // f0_initialRateTimeHistory_vector - -}; // SquarePulseSource - -// End of file + void g1v(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar g1[]) { + const PylithInt _numA = 3; + assert(_numA == numA); + assert(aOff); + assert(a); + + // const PylithInt i_amplitude = aOff[numA - 3]; + const PylithInt i_moment_tensor = aOff[0]; + // const PylithInt i_start_time = aOff[numA - 2]; + const PylithInt i_value = aOff[numA - 1]; + + PylithInt _dim = 3; + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorysourceCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "timehistorySource %f\n", (double)timehistorysource); + + const PylithScalar* momentTensor = &a[aOff[i_moment_tensor]]; + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * a[i_value]; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); + } // for + } // g1v + +}; // g1v + +#endif /* pylith_fekernels_timehistorysource_hh */ + +/* End of file */ diff --git a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh index 00bd103982..a5cfa1cab1 100644 --- a/libsrc/pylith/fekernels/TimeHistoryWavelet.hh +++ b/libsrc/pylith/fekernels/TimeHistoryWavelet.hh @@ -168,7 +168,7 @@ public: // const PylithInt i_amplitude = aOff[numA - 3]; const PylithInt i_moment_tensor = aOff[0]; - const PylithInt i_start_time = aOff[numA - 2]; + // const PylithInt i_start_time = aOff[numA - 2]; const PylithInt i_value = aOff[numA - 1]; PylithInt _dim = 3; diff --git a/libsrc/pylith/fekernels/fekernelsfwd.hh b/libsrc/pylith/fekernels/fekernelsfwd.hh index 3260382aec..769733c36d 100644 --- a/libsrc/pylith/fekernels/fekernelsfwd.hh +++ b/libsrc/pylith/fekernels/fekernelsfwd.hh @@ -76,6 +76,10 @@ namespace pylith { class TimeHistoryWaveletPlaneStrain; class TimeHistoryWavelet3D; + class TimeHistorySource; + class TimeHistorySourcePlaneStrain; + class TimeHistorySource; + class PointForce; class BoundaryDirections; diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index f21b17b055..549c8a7b76 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -28,11 +28,13 @@ subpkginclude_HEADERS = \ AuxiliaryFactoryMomentTensorForce.hh \ AuxiliaryFactoryWellboreSource.hh \ AuxiliaryFactorySourceTime.hh \ + AuxiliaryFactoryTimeHistorySource.hh \ DerivedFactoryMomentTensorForce.hh \ SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ TimeHistoryWavelet.hh \ + TimeHistorySource.hh \ PointForce.hh \ AuxiliaryFactoryPointForce.hh \ SourceTimeFunctionMomentTensorForce.hh \ diff --git a/libsrc/pylith/sources/TimeHistorySource.cc b/libsrc/pylith/sources/TimeHistorySource.cc index a54eb8e831..3a818572c6 100644 --- a/libsrc/pylith/sources/TimeHistorySource.cc +++ b/libsrc/pylith/sources/TimeHistorySource.cc @@ -18,15 +18,15 @@ #include #include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "pylith/sources/SquarePulseSource.hh" // implementation of object methods +#include "pylith/sources/TimeHistorySource.hh" // implementation of object methods -#include "pylith/sources/AuxiliaryFactorySquarePulseSource.hh" // USES AuxiliaryFactorySquarePulseSource +#include "pylith/sources/AuxiliaryFactoryTimeHistorySource.hh" // USES AuxiliaryFactoryTimeHistorySource #include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain #include "pylith/topology/Mesh.hh" // USES Mesh #include "pylith/topology/Field.hh" // USES Field::SubfieldInfo #include "pylith/topology/FieldOps.hh" // USES FieldOps -#include "pylith/fekernels/SquarePulseSource.hh" // USES SquarePulseSource kernels +#include "pylith/fekernels/TimeHistorySource.hh" // USES TimeHistorySource kernels #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* @@ -45,7 +45,7 @@ typedef pylith::feassemble::Integrator::EquationPart EquationPart; // --------------------------------------------------------------------------------------------------------------------- namespace pylith { namespace sources { - class _SquarePulseSource { + class _TimeHistorySource { // PUBLIC MEMBERS ////////////////////////////////////////////////////////////////////////////////////////// public: @@ -58,35 +58,35 @@ namespace pylith { */ static void setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const pylith::sources::SquarePulseSource& sources, + const pylith::sources::TimeHistorySource& sources, const pylith::topology::Field& solution, const pylith::problems::Physics::FormulationEnum formulation); static const char* pyreComponent; - }; // _SquarePulseSource - const char* _SquarePulseSource::pyreComponent = "squarepulsesource"; + }; // _TimeHistorySource + const char* _TimeHistorySource::pyreComponent = "timehistorysource"; } // sources } // pylith // --------------------------------------------------------------------------------------------------------------------- // Default constructor. -pylith::sources::SquarePulseSource::SquarePulseSource(void) : +pylith::sources::TimeHistorySource::TimeHistorySource(void) : _dbTimeHistory(NULL), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource(pylith::sources::AuxiliaryFactorySquarePulseSource::XYZ)), + _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryTimeHistorySource(pylith::sources::AuxiliaryFactoryTimeHistorySource::XYZ)), _useInitial(true), _useRate(false), _useTimeHistory(false) { - PyreComponent::setName(_SquarePulseSource::pyreComponent); + PyreComponent::setName(_TimeHistorySource::pyreComponent); - pylith::utils::PyreComponent::setName("squarepulsesource"); + pylith::utils::PyreComponent::setName("timehistorysource"); } // constructor // --------------------------------------------------------------------------------------------------------------------- // Destructor. -pylith::sources::SquarePulseSource::~SquarePulseSource(void) { +pylith::sources::TimeHistorySource::~TimeHistorySource(void) { deallocate(); } // destructor @@ -94,7 +94,7 @@ pylith::sources::SquarePulseSource::~SquarePulseSource(void) { // --------------------------------------------------------------------------------------------------------------------- // Deallocate PETSc and local data structures. void -pylith::sources::SquarePulseSource::deallocate(void) { +pylith::sources::TimeHistorySource::deallocate(void) { Source::deallocate(); delete _auxiliaryFactory; @@ -105,7 +105,7 @@ pylith::sources::SquarePulseSource::deallocate(void) { // --------------------------------------------------------------------------------------------------------------------- // Set time history database. void -pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { +pylith::sources::TimeHistorySource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); _dbTimeHistory = th; @@ -115,7 +115,7 @@ pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::Tim // --------------------------------------------------------------------------------------------------------------------- // Get time history database. const spatialdata::spatialdb::TimeHistory * -pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { +pylith::sources::TimeHistorySource::getTimeHistoryDB(void) { return _dbTimeHistory; } // getTimeHistoryDB @@ -123,7 +123,7 @@ pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { // --------------------------------------------------------------------------------------------------------------------- // Use time history term in time history expression. void -pylith::sources::SquarePulseSource::useTimeHistory(const bool value) { +pylith::sources::TimeHistorySource::useTimeHistory(const bool value) { PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); _useTimeHistory = value; @@ -133,7 +133,7 @@ pylith::sources::SquarePulseSource::useTimeHistory(const bool value) { // --------------------------------------------------------------------------------------------------------------------- // Get flag associated with using time history term in time history expression. bool -pylith::sources::SquarePulseSource::useTimeHistory(void) const { +pylith::sources::TimeHistorySource::useTimeHistory(void) const { return _useTimeHistory; } // useTimeHistory @@ -141,13 +141,13 @@ pylith::sources::SquarePulseSource::useTimeHistory(void) const { // --------------------------------------------------------------------------------------------------------------------- // Verify configuration is acceptable. void -pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const { +pylith::sources::TimeHistorySource::verifyConfiguration(const pylith::topology::Field &solution) const { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); // Verify solution contains expected fields. if (!solution.hasSubfield("pressure")) { - throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'SquarePulseSource'."); + throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'TimeHistorySource'."); } // if PYLITH_METHOD_END; @@ -157,7 +157,7 @@ pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology:: // --------------------------------------------------------------------------------------------------------------------- // Create integrator and set kernels. pylith::feassemble::Integrator * -pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) { +pylith::sources::TimeHistorySource::createIntegrator(const pylith::topology::Field &solution) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); @@ -167,7 +167,7 @@ pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Fie assert(integrator); integrator->setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); - // printf("In SquarePulseSource end\n"); + // printf("In TimeHistorySource end\n"); // DMView(dmSoln, NULL); _setKernelsResidual(integrator, solution); @@ -180,14 +180,14 @@ pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Fie // --------------------------------------------------------------------------------------------------------------------- // Create auxiliary field. pylith::topology::Field * -pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology::Field &solution, +pylith::sources::TimeHistorySource::createAuxiliaryField(const pylith::topology::Field &solution, const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); assert(auxiliaryField); - auxiliaryField->setLabel("SquarePulseSource auxiliary field"); + auxiliaryField->setLabel("TimeHistorySource auxiliary field"); assert(_normalizer); _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); @@ -203,36 +203,29 @@ pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology: // add in aux specific to square pulse _auxiliaryFactory->addVolumeFlowRate(); // 0 - if (_useInitial) { - _auxiliaryFactory->addInitialAmplitude(); + _auxiliaryFactory->addTimeHistoryStartTime(); + _auxiliaryFactory->addTimeHistoryValue(); + + if (_dbTimeHistory) { + _dbTimeHistory->open(); } // if - if (_useRate) { - _auxiliaryFactory->addRateAmplitude(); - _auxiliaryFactory->addRateStartTime(); - } // _useRate - if (_useTimeHistory) { - _auxiliaryFactory->addTimeHistoryAmplitude(); - _auxiliaryFactory->addTimeHistoryStartTime(); - _auxiliaryFactory->addTimeHistoryValue(); - if (_dbTimeHistory) { - _dbTimeHistory->open(); - } // if - } // _useTimeHistory - - assert(_auxiliaryFactory); - _auxiliaryFactory->setValuesFromDB(); - - // Debug option - auxiliaryField->view("SquarePulse auxiliary field."); - - PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField +} // _useTimeHistory + + +assert(_auxiliaryFactory); +_auxiliaryFactory->setValuesFromDB(); + +// Debug option +auxiliaryField->view("SquarePulse auxiliary field."); + +PYLITH_METHOD_RETURN(auxiliaryField); +} // createAuxiliaryField // --------------------------------------------------------------------------------------------------------------------- // Create derived field. pylith::topology::Field * -pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::Field &solution, +pylith::sources::TimeHistorySource::createDerivedField(const pylith::topology::Field &solution, const pylith::topology::Mesh &domainMesh) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); @@ -244,7 +237,7 @@ pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::F // --------------------------------------------------------------------------------------------------------------------- // Get auxiliary factory associated with physics. pylith::feassemble::AuxiliaryFactory * -pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { +pylith::sources::TimeHistorySource::_getAuxiliaryFactory(void) { return _auxiliaryFactory; } // _getAuxiliaryFactory @@ -253,7 +246,7 @@ pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { // --------------------------------------------------------------------------------------------------------------------- // // Set kernels for LHS residual F(t,s,\dot{s}). // void -// pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, +// pylith::sources::TimeHistorySource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, // const topology::Field &solution) const { // PYLITH_METHOD_BEGIN; // PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << @@ -267,7 +260,7 @@ pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { // case QUASISTATIC: // { // // Pressure -// const PetscPointFunc f0p = pylith::fekernels::SquarePulseSource::f0p; +// const PetscPointFunc f0p = pylith::fekernels::TimeHistorySource::f0p; // const PetscPointFunc f1p = NULL; // kernels.resize(1); @@ -295,12 +288,12 @@ pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { // --------------------------------------------------------------------------------------------------------------------- // Set kernels for residual. void -pylith::sources::_SquarePulseSource::setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const pylith::sources::SquarePulseSource& sources, +pylith::sources::_TimeHistorySource::setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, + const pylith::sources::TimeHistorySource& sources, const topology::Field& solution, const pylith::problems::Physics::FormulationEnum formulation) { PYLITH_METHOD_BEGIN; - pythia::journal::debug_t debug(_SquarePulseSource::pyreComponent); + pythia::journal::debug_t debug(_TimeHistorySource::pyreComponent); debug << pythia::journal::at(__HERE__) << "setKernelsResidual(integrator="< Date: Tue, 3 Jun 2025 11:24:54 -0600 Subject: [PATCH 42/65] Mesh: Fix for empty labels --- libsrc/pylith/meshio/MeshBuilder.cc | 50 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/libsrc/pylith/meshio/MeshBuilder.cc b/libsrc/pylith/meshio/MeshBuilder.cc index 35867aeded..1b13d8a558 100644 --- a/libsrc/pylith/meshio/MeshBuilder.cc +++ b/libsrc/pylith/meshio/MeshBuilder.cc @@ -667,33 +667,33 @@ pylith::meshio::_MeshBuilder::getGroupNames(string_vector* names, const PetscInt* labelValues = PETSC_NULLPTR; err = DMLabelGetNumValues(dmLabel, &numLabelValues);PYLITH_CHECK_ERROR(err); // assert(1 == numLabelValues); err = DMLabelGetValueIS(dmLabel, &labelValuesIS);PYLITH_CHECK_ERROR(err);assert(labelValuesIS); - err = ISGetIndices(labelValuesIS, &labelValues);PYLITH_CHECK_ERROR(err);assert(labelValues); - const PetscInt labelValue = labelValues[0]; - + err = ISGetIndices(labelValuesIS, &labelValues);PYLITH_CHECK_ERROR(err); + if (labelValues) { + const PetscInt labelValue = labelValues[0]; + pylith::topology::StratumIS pointIS(dmMesh, labelStr, labelValue); + const PetscInt* points = pointIS.points(); + const PetscInt numPoints = pointIS.size(); + bool hasOtherPoints = false; + bool foundPoint = false; + for (PetscInt iPoint = 0; iPoint < numPoints; ++iPoint) { + if ((points[iPoint] >= pStart) && (points[iPoint] < pEnd) ) { + foundPoint = true; + if (!exclusive) { + break; + } // if + } else { + hasOtherPoints = true; + if (exclusive) { + break; + } // if + } // if/else + } // for + if ((foundPoint && !exclusive) || (foundPoint && exclusive && !hasOtherPoints)) { + (*names)[numNames++] = labelName; + } // if + } err = ISRestoreIndices(labelValuesIS, &labelValues);PYLITH_CHECK_ERROR(err); err = ISDestroy(&labelValuesIS);PYLITH_CHECK_ERROR(err); - - pylith::topology::StratumIS pointIS(dmMesh, labelStr, labelValue); - const PetscInt* points = pointIS.points(); - const PetscInt numPoints = pointIS.size(); - bool hasOtherPoints = false; - bool foundPoint = false; - for (PetscInt iPoint = 0; iPoint < numPoints; ++iPoint) { - if ((points[iPoint] >= pStart) && (points[iPoint] < pEnd) ) { - foundPoint = true; - if (!exclusive) { - break; - } // if - } else { - hasOtherPoints = true; - if (exclusive) { - break; - } // if - } // if/else - } // for - if ((foundPoint && !exclusive) || (foundPoint && exclusive && !hasOtherPoints)) { - (*names)[numNames++] = labelName; - } // if } // if } // for names->resize(numNames); From 58a722c76ce4b10850d72c8d8a2a0f3889d541c2 Mon Sep 17 00:00:00 2001 From: "Matthew G. Knepley" Date: Tue, 3 Jun 2025 13:04:04 -0600 Subject: [PATCH 43/65] Allow data that is not from timestepping in HDF5 --- pylith/meshio/Xdmf.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pylith/meshio/Xdmf.py b/pylith/meshio/Xdmf.py index 14703b2b98..d69b1941b1 100644 --- a/pylith/meshio/Xdmf.py +++ b/pylith/meshio/Xdmf.py @@ -5,7 +5,7 @@ # Copyright (c) 2010-2025, University of California, Davis and the PyLith Development Team. # All rights reserved. # -# See https://mit-license.org/ and LICENSE.md and for license information. +# See https://mit-license.org/ and LICENSE.md and for license information. # ================================================================================================= @@ -150,7 +150,7 @@ def _getXdmfVectorFieldType(self, vectorFieldString): """Get Xdmf vector field type. """ import numpy - + if type(vectorFieldString) == str: vectorFieldTypeName = vectorFieldString.lower() elif type(vectorFieldString) == bytes: @@ -449,8 +449,12 @@ def _writeGridField(self, field, iTime): raise ValueError( "Unexpected shape for dataset '%s'." % field.name) else: - assert(3 == len(field.data.shape)) - numTimeSteps, numPoints, numComponents = field.data.shape + if 2 == len(field.data.shape): + numPoints, numComponents = field.data.shape + numTimeSteps = 1 + else: + assert(3 == len(field.data.shape)) + numTimeSteps, numPoints, numComponents = field.data.shape if 2 == self._getSpaceDim() and field.vectorFieldType == "Vector": From b166df2c42d3c7694fb2ea72049fcf950466d83b Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Tue, 3 Jun 2025 14:12:57 -0600 Subject: [PATCH 44/65] added point source example --- examples/point-source/impulse_gen.py | 29 ++++ examples/point-source/mesh_quad.exo | Bin 0 -> 314212 bytes examples/point-source/mesh_quad.jou | 30 ++++ examples/point-source/pylithapp.cfg | 134 ++++++++++++++++++ examples/point-source/ramp.timedb | 110 ++++++++++++++ examples/point-source/source_sites.txt | 2 + examples/point-source/step01_ricker.cfg | 126 ++++++++++++++++ examples/point-source/step01_time_history.cfg | 127 +++++++++++++++++ examples/point-source/step02_time_history.cfg | 133 +++++++++++++++++ 9 files changed, 691 insertions(+) create mode 100644 examples/point-source/impulse_gen.py create mode 100644 examples/point-source/mesh_quad.exo create mode 100644 examples/point-source/mesh_quad.jou create mode 100644 examples/point-source/pylithapp.cfg create mode 100644 examples/point-source/ramp.timedb create mode 100644 examples/point-source/source_sites.txt create mode 100644 examples/point-source/step01_ricker.cfg create mode 100644 examples/point-source/step01_time_history.cfg create mode 100644 examples/point-source/step02_time_history.cfg diff --git a/examples/point-source/impulse_gen.py b/examples/point-source/impulse_gen.py new file mode 100644 index 0000000000..f83eba0719 --- /dev/null +++ b/examples/point-source/impulse_gen.py @@ -0,0 +1,29 @@ +import numpy as np + +def generate_ramp_stf(duration=0.5, dt=0.01, max_amplitude=1.0): + time = np.arange(0, duration + dt, dt) + amplitude = max_amplitude - (max_amplitude / duration) * time + return time, amplitude + +# Parameters +duration = 0.10 +dt = 0.001 +max_amp = 1.0 +time, amplitude = generate_ramp_stf(duration, dt, max_amp) + +# Write in the same format as impulse.timedb +with open("ramp.timedb", "w") as f: + f.write("// -*- C++ -*- (tell Emacs to use C++ mode for syntax highlighting)\n") + f.write("//\n") + f.write("// Ramp source time function with linear increase to max amplitude.\n") + f.write("#TIME HISTORY ascii\n") + f.write("TimeHistory {\n") + f.write(f" num-points = {len(time)+1} // number of points in time history\n") + f.write(" time-units = second // units for time\n") + f.write("}\n") + for t, a in zip(time, amplitude): + f.write(f"{t:10.4f} {a:10.4f}\n") + t_final = 999.000 + a_final = 0.000 + f.write(f"{t_final:10.4f} {a_final:10.4f}\n") + diff --git a/examples/point-source/mesh_quad.exo b/examples/point-source/mesh_quad.exo new file mode 100644 index 0000000000000000000000000000000000000000..81680a2cec54b08f5c52994876cb64771dc4eb36 GIT binary patch literal 314212 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 literal 0 HcmV?d00001 diff --git a/examples/point-source/mesh_quad.jou b/examples/point-source/mesh_quad.jou new file mode 100644 index 0000000000..ce8fc96b5c --- /dev/null +++ b/examples/point-source/mesh_quad.jou @@ -0,0 +1,30 @@ +# ---------------------------------------------------------------------- +# Generate geometry +# ---------------------------------------------------------------------- +playback 'geometry.jou' + +# ---------------------------------------------------------------------- +# Set discretization size +# ---------------------------------------------------------------------- +${dx=120.0*m} +surface all size {dx} + + +# ---------------------------------------------------------------------- +# Generate the mesh +# ---------------------------------------------------------------------- +surface all scheme submap +mesh surface all + +# ---------------------------------------------------------------------- +# Mark entities for boundary conditions, etc. +# ---------------------------------------------------------------------- +playback 'bc.jou' + +# ---------------------------------------------------------------------- +# Export exodus file +# ---------------------------------------------------------------------- +export mesh "mesh_quad.exo" dimension 2 overwrite + + + diff --git a/examples/point-source/pylithapp.cfg b/examples/point-source/pylithapp.cfg new file mode 100644 index 0000000000..ffd19a62f8 --- /dev/null +++ b/examples/point-source/pylithapp.cfg @@ -0,0 +1,134 @@ +[pylithapp.metadata] +# This is not a self-contained simulation configuration file. This +# file only specifies the general parameters common to the simulations +# in this directory. +keywords = [example, 2D] +features = [ + Dynamic simulation, + Implicit-explicit formulation, + Quadrilateral cells, + Runge-Kutta time stepping, + pylith.meshio.MeshIOCubit, + pylith.problems.TimeDependent, + pylith.materials.Elasticity, + pylith.materials.IsotropicLinearElasticity, + spatialdata.spatialdb.UniformDB, + pylith.meshio.DataWriterHDF5, + spatialdata.units.NondimElasticDynamic + ] + +# ---------------------------------------------------------------------- +# journal +# ---------------------------------------------------------------------- +# Turn on some journals to show progress. +[pylithapp.journal] +#device = color-console + +[pylithapp.journal.info] +timedependent = 1 +solution = 1 +meshiocubit = 1 +pylithapp = 1 + +[pylithapp.journal.debug] +timedependent = 0 + +# ---------------------------------------------------------------------- +# mesh_generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator] +# Set the reader to match the type of mesh file. +reader = pylith.meshio.MeshIOCubit +reader.filename = mesh_quad.exo + +# Set the Cartesian coordinate system. +reader.coordsys.space_dim = 2 + + +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Use the nonlinear solver to verify residual and Jacobian are consistent. +solver = linear +formulation = dynamic + +# # Nondimensionalize problem using wave propagation parameters. +# normalizer = spatialdata.units.NondimElasticDynamic +# normalizer.mass_density = 2500.0*kg/m**3 +# normalizer.shear_wave_speed = 1.0*km/s +# normalizer.wave_period = 0.5*s + +defaults.quadrature_order = 1 + + +# Set the discretization for each of the solution subfields. +# +# For a quastistatic simulation with a fault, we have two solution fields: +# (1) displacement and (2) Lagrange multiplier. We use a predefined containter +# to create a solution field with these two subfields. +solution = pylith.problems.SolnDispVel + +solution.subfields.displacement.basis_order = 1 +solution.subfields.velocity.basis_order = 1 + +#solution_observers = [domain] +#solution_observers = [] +#solution_observers.domain.trigger.num_skip = 10 + + +start_time = 0.0*s +end_time = 0.025*s +initial_dt = 0.001*s + +# ---------------------------------------------------------------------- +# materials +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Create an array of one material +materials = [elastic] + +# We use the default material (elasticity) and rheology +# (isotropic, linearly elastic). + +[pylithapp.problem.materials.elastic] +# id must match the values in the mesh material-ids. +description = Elastic material +label_value = 1 +observers = [] +#observers.observer.trigger.num_skip = 10 +# We will use uniform material properties, so we use the UniformDB +# spatial database. +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Elastic properties +db_auxiliary_field.values = [density, vs, vp] +db_auxiliary_field.data = [1800*kg/m**3, 1.3*km/s, 3.0*km/s] + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.density.basis_order = 0 +bulk_rheology.auxiliary_subfields.bulk_modulus.basis_order = 0 +bulk_rheology.auxiliary_subfields.shear_modulus.basis_order = 0 + +# ---------------------------------------------------------------------- +# PETSc +# ---------------------------------------------------------------------- +[pylithapp.petsc] +ts_type = rk +ts_rk_type = 3bs +ts_adapt_dt_max = 0.1 + +ksp_rtol = 1.0e-8 +ksp_atol = 1.0e-12 +ksp_max_it = 30 +ksp_gmres_restart = 50 +ksp_error_if_not_converged = true + +snes_rtol = 1.0e-10 +snes_atol = 1.0e-10 +snes_error_if_not_converged = true + +# Monitors for debugging +ts_monitor = true + +# End of file diff --git a/examples/point-source/ramp.timedb b/examples/point-source/ramp.timedb new file mode 100644 index 0000000000..d78a94fa91 --- /dev/null +++ b/examples/point-source/ramp.timedb @@ -0,0 +1,110 @@ +// -*- C++ -*- (tell Emacs to use C++ mode for syntax highlighting) +// +// Ramp source time function with linear increase to max amplitude. +#TIME HISTORY ascii +TimeHistory { + num-points = 102 // number of points in time history + time-units = second // units for time +} + 0.0000 1.0000 + 0.0010 0.9900 + 0.0020 0.9800 + 0.0030 0.9700 + 0.0040 0.9600 + 0.0050 0.9500 + 0.0060 0.9400 + 0.0070 0.9300 + 0.0080 0.9200 + 0.0090 0.9100 + 0.0100 0.9000 + 0.0110 0.8900 + 0.0120 0.8800 + 0.0130 0.8700 + 0.0140 0.8600 + 0.0150 0.8500 + 0.0160 0.8400 + 0.0170 0.8300 + 0.0180 0.8200 + 0.0190 0.8100 + 0.0200 0.8000 + 0.0210 0.7900 + 0.0220 0.7800 + 0.0230 0.7700 + 0.0240 0.7600 + 0.0250 0.7500 + 0.0260 0.7400 + 0.0270 0.7300 + 0.0280 0.7200 + 0.0290 0.7100 + 0.0300 0.7000 + 0.0310 0.6900 + 0.0320 0.6800 + 0.0330 0.6700 + 0.0340 0.6600 + 0.0350 0.6500 + 0.0360 0.6400 + 0.0370 0.6300 + 0.0380 0.6200 + 0.0390 0.6100 + 0.0400 0.6000 + 0.0410 0.5900 + 0.0420 0.5800 + 0.0430 0.5700 + 0.0440 0.5600 + 0.0450 0.5500 + 0.0460 0.5400 + 0.0470 0.5300 + 0.0480 0.5200 + 0.0490 0.5100 + 0.0500 0.5000 + 0.0510 0.4900 + 0.0520 0.4800 + 0.0530 0.4700 + 0.0540 0.4600 + 0.0550 0.4500 + 0.0560 0.4400 + 0.0570 0.4300 + 0.0580 0.4200 + 0.0590 0.4100 + 0.0600 0.4000 + 0.0610 0.3900 + 0.0620 0.3800 + 0.0630 0.3700 + 0.0640 0.3600 + 0.0650 0.3500 + 0.0660 0.3400 + 0.0670 0.3300 + 0.0680 0.3200 + 0.0690 0.3100 + 0.0700 0.3000 + 0.0710 0.2900 + 0.0720 0.2800 + 0.0730 0.2700 + 0.0740 0.2600 + 0.0750 0.2500 + 0.0760 0.2400 + 0.0770 0.2300 + 0.0780 0.2200 + 0.0790 0.2100 + 0.0800 0.2000 + 0.0810 0.1900 + 0.0820 0.1800 + 0.0830 0.1700 + 0.0840 0.1600 + 0.0850 0.1500 + 0.0860 0.1400 + 0.0870 0.1300 + 0.0880 0.1200 + 0.0890 0.1100 + 0.0900 0.1000 + 0.0910 0.0900 + 0.0920 0.0800 + 0.0930 0.0700 + 0.0940 0.0600 + 0.0950 0.0500 + 0.0960 0.0400 + 0.0970 0.0300 + 0.0980 0.0200 + 0.0990 0.0100 + 0.1000 0.0000 + 999.0000 0.0000 diff --git a/examples/point-source/source_sites.txt b/examples/point-source/source_sites.txt new file mode 100644 index 0000000000..6c0b234328 --- /dev/null +++ b/examples/point-source/source_sites.txt @@ -0,0 +1,2 @@ +#Site X Y +s000 5000.00 5000.00 \ No newline at end of file diff --git a/examples/point-source/step01_ricker.cfg b/examples/point-source/step01_ricker.cfg new file mode 100644 index 0000000000..399d23fee7 --- /dev/null +++ b/examples/point-source/step01_ricker.cfg @@ -0,0 +1,126 @@ +[pylithapp.metadata] +# y +# ^ +# | +# --> x + +base = [pylithapp.cfg] +description = Ricker source test. +authors = [Robert Walker] +keywords = [Ricker source, time-dependent Dirichlet boundary condition] +arguments = [step01_ricker.cfg] +version = 1.0.0 +pylith_version = [>=3.0, <7.0] + +features = [ + pylith.problems.SolnDispVel, + pylith.bc.DirichletTimeDependent, + spatialdata.spatialdb.ZeroDB + ] + +[pylithapp] +# File with version information and parameters (including defaults). +# +# You can view this file using the pylith_parameters application or +# online at https://geodynamics.github.io/pylith_parameters/. +dump_parameters.filename = output/step01_ricker-parameters.json +problem.progress_monitor.filename = output/step01_ricker-progress.txt + +# Set the name of the problem that will be used to construct the +# output filenames. The default directory for output is 'output'. +problem.defaults.name = step01_ricker + +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Use the nonlinear solver to verify residual and Jacobian are consistent. +solver = nonlinear +formulation = dynamic + +# Nondimensionalize problem using wave propagation parameters. +normalizer = spatialdata.units.NondimElasticDynamic +normalizer.mass_density = 2500.0*kg/m**3 +normalizer.shear_wave_speed = 1000.0*m/s +normalizer.wave_period = 1.0*s + +defaults.quadrature_order = 1 + + +# Set the discretization for each of the solution subfields. +# +solution = pylith.problems.SolnDispVel + +solution.subfields.displacement.basis_order = 1 +solution.subfields.velocity.basis_order = 1 + +solution_observers = [domain] + +start_time = 0.0*s +end_time = 1.0*s +initial_dt = 0.01*s +# ---------------------------------------------------------------------- +# sources +# ---------------------------------------------------------------------- + +[pylithapp.problem] +sources = [source] + +sources.source = pylith.sources.MomentTensorForce +[pylithapp.problem.sources] +source.source_time_function = pylith.sources.RickerWavelet + +[pylithapp.problem.sources.source] +description = Ricker Source +label_value = 2 +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 + +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [100*Pa*s, 100*Pa*s, 0.0*Pa*s, 100.0*Pa*s, 0.0*s, 1] + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.moment_tensor.basis_order = 0 +auxiliary_subfields.time_delay.basis_order = 0 +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 + + + +# ---------------------------------------------------------------------- +# initial conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] +ic = [domain] +ic.domain = pylith.problems.InitialConditionDomain + +[pylithapp.problem.ic.domain] +db = spatialdata.spatialdb.UniformDB +db.description = Initial conditions over domain +db.values = [displacement_x, displacement_y] +db.data = [0.0*m, 0.0*m] + +# ---------------------------------------------------------------------- +# boundary conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] + + +# ---------------------------------------------------------------------- +# PETSc +# ---------------------------------------------------------------------- +[pylithapp.petsc] +ts_type = rk +ts_rk_type = 3bs +ts_adapt_dt_max = 0.001 +dm_partition_view = True + +# ---------------------------------------------------------------------- +# Mesh Generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator] +refiner = pylith.topology.RefineUniform +# End of file diff --git a/examples/point-source/step01_time_history.cfg b/examples/point-source/step01_time_history.cfg new file mode 100644 index 0000000000..bc1b188d8f --- /dev/null +++ b/examples/point-source/step01_time_history.cfg @@ -0,0 +1,127 @@ +[pylithapp.metadata] +# y +# ^ +# | +# --> x + +base = [pylithapp.cfg] +description = Time History MT test. +authors = [Robert Walker] +keywords = [Time History Wavelet, time-dependent Dirichlet boundary condition] +arguments = [step01_time_history.cfg] +version = 1.0.0 +pylith_version = [>=3.0, <7.0] + +features = [ + pylith.problems.SolnDispVel, + pylith.bc.DirichletTimeDependent, + spatialdata.spatialdb.ZeroDB + ] + +[pylithapp] +# File with version information and parameters (including defaults). +# +# You can view this file using the pylith_parameters application or +# online at https://geodynamics.github.io/pylith_parameters/. +dump_parameters.filename = output/step01_ricker-parameters.json +problem.progress_monitor.filename = output/step01_ricker-progress.txt + +# Set the name of the problem that will be used to construct the +# output filenames. The default directory for output is 'output'. +problem.defaults.name = step01_time_history + +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Use the nonlinear solver to verify residual and Jacobian are consistent. +solver = nonlinear +formulation = dynamic + +# Nondimensionalize problem using wave propagation parameters. +normalizer = spatialdata.units.NondimElasticDynamic +normalizer.mass_density = 2500.0*kg/m**3 +normalizer.shear_wave_speed = 1000.0*m/s +normalizer.wave_period = 1.0*s + +defaults.quadrature_order = 1 + + +# Set the discretization for each of the solution subfields. +# +solution = pylith.problems.SolnDispVel + +solution.subfields.displacement.basis_order = 1 +solution.subfields.velocity.basis_order = 1 + +solution_observers = [domain] + +start_time = 0.0*s +end_time = 0.1*s +initial_dt = 0.01*s +# ---------------------------------------------------------------------- +# sources +# ---------------------------------------------------------------------- + +[pylithapp.problem] +sources = [source] + +sources.source = pylith.sources.MomentTensorForce + +[pylithapp.problem.sources.source] +description = Time History Source +label_value = 2 +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 +source_time_function = pylith.sources.TimeHistoryWavelet + + +#useTimeHistory = True + +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_history_start_time] +db_auxiliary_field.data = [100*Pa*s, 100*Pa*s, 0.0*Pa*s, 100.0*Pa*s, 0.0*s] +source_time_function.time_history = spatialdata.spatialdb.TimeHistory +source_time_function.time_history.description = Ramp time history +source_time_function.time_history.filename = ramp.timedb + + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.moment_tensor.basis_order = 0 +#source_time_function.auxiliary_subfields.time_history_amplitude.basis_order = 0 +#source_time_function.auxiliary_subfields.time_history_start_time.basis_order = 0 + + + +# ---------------------------------------------------------------------- +# initial conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] +ic = [domain] +ic.domain = pylith.problems.InitialConditionDomain + +[pylithapp.problem.ic.domain] +db = spatialdata.spatialdb.UniformDB +db.description = Initial conditions over domain +db.values = [displacement_x, displacement_y] +db.data = [0.0*m, 0.0*m] + +# ---------------------------------------------------------------------- +# boundary conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] + + +# ---------------------------------------------------------------------- +# PETSc +# ---------------------------------------------------------------------- +[pylithapp.petsc] +ts_type = rk +ts_rk_type = 3bs +ts_adapt_dt_max = 0.001 + + +# End of file diff --git a/examples/point-source/step02_time_history.cfg b/examples/point-source/step02_time_history.cfg new file mode 100644 index 0000000000..22043befed --- /dev/null +++ b/examples/point-source/step02_time_history.cfg @@ -0,0 +1,133 @@ +[pylithapp.metadata] +# y +# ^ +# | +# --> x + +base = [pylithapp.cfg] +description = Time History MT test. +authors = [Robert Walker] +keywords = [Time History Wavelet, time-dependent Dirichlet boundary condition] +arguments = [step02_time_history.cfg] +version = 1.0.0 +pylith_version = [>=3.0, <7.0] + +features = [ + pylith.problems.SolnDispVel, + pylith.bc.DirichletTimeDependent, + spatialdata.spatialdb.ZeroDB + ] + +[pylithapp] +# File with version information and parameters (including defaults). +# +# You can view this file using the pylith_parameters application or +# online at https://geodynamics.github.io/pylith_parameters/. +dump_parameters.filename = output/step02_time_history-parameters.json +problem.progress_monitor.filename = output/step02_time_history-progress.txt + +# Set the name of the problem that will be used to construct the +# output filenames. The default directory for output is 'output'. +problem.defaults.name = step02_time_history + +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Use the nonlinear solver to verify residual and Jacobian are consistent. +solver = nonlinear +formulation = dynamic + +# Nondimensionalize problem using wave propagation parameters. +normalizer = spatialdata.units.NondimElasticDynamic +normalizer.mass_density = 2500.0*kg/m**3 +normalizer.shear_wave_speed = 1000.0*m/s +normalizer.wave_period = 1.0*s + +defaults.quadrature_order = 1 + + +# Set the discretization for each of the solution subfields. +# +solution = pylith.problems.SolnDispVel + +solution.subfields.displacement.basis_order = 1 +solution.subfields.velocity.basis_order = 1 + +solution_observers = [domain] +#solution_observers.domain.trigger.num_skip = 10 + +start_time = 0.0*s +end_time = 1.0*s +initial_dt = 0.01*s +# ---------------------------------------------------------------------- +# sources +# ---------------------------------------------------------------------- + +[pylithapp.problem] +sources = [source] + +sources.source = pylith.sources.MomentTensorForce + +[pylithapp.problem.sources.source] +description = Time History Source +label_value = 2 +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 +source_time_function = pylith.sources.TimeHistoryWavelet +#observer.trigger.num_skip = 10 +observers = [] +#useTimeHistory = True + +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_history_start_time] +db_auxiliary_field.data = [100*Pa*s, 100*Pa*s, 0.0*Pa*s, 100.0*Pa*s, 0.0*s] +source_time_function.time_history = spatialdata.spatialdb.TimeHistory +source_time_function.time_history.description = ramp time history +source_time_function.time_history.filename = ramp.timedb + + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.moment_tensor.basis_order = 0 +#source_time_function.auxiliary_subfields.time_history_amplitude.basis_order = 0 +#source_time_function.auxiliary_subfields.time_history_start_time.basis_order = 0 + + + +# ---------------------------------------------------------------------- +# initial conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] +ic = [domain] +ic.domain = pylith.problems.InitialConditionDomain + +[pylithapp.problem.ic.domain] +db = spatialdata.spatialdb.UniformDB +db.description = Initial conditions over domain +db.values = [displacement_x, displacement_y] +db.data = [0.0*m, 0.0*m] + +# ---------------------------------------------------------------------- +# boundary conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] + + +# ---------------------------------------------------------------------- +# PETSc +# ---------------------------------------------------------------------- +[pylithapp.petsc] +ts_type = rk +ts_rk_type = 3bs +ts_adapt_dt_max = 0.001 + +# ---------------------------------------------------------------------- +# Mesh Generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator] +refiner = pylith.topology.RefineUniform + +# End of file From 54454f2f50086c8c5c4dd95125d89e26b19d69c1 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 4 Jun 2025 15:54:34 -0600 Subject: [PATCH 45/65] Updated to fix input units --- .../infinitesimal-strain-dynamic.md | 2 +- libsrc/pylith/sources/MomentTensorForce.cc | 15 +++++++++++ libsrc/pylith/sources/Source.cc | 27 +++++++++++++++++-- libsrc/pylith/sources/Source.hh | 2 ++ .../TestAuxiliaryFactoryMomentTensorForce.cc | 2 +- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/docs/user/governingeqns/elasticity/infinitesimal-strain-dynamic.md b/docs/user/governingeqns/elasticity/infinitesimal-strain-dynamic.md index 419e81b5b9..f5caffd656 100644 --- a/docs/user/governingeqns/elasticity/infinitesimal-strain-dynamic.md +++ b/docs/user/governingeqns/elasticity/infinitesimal-strain-dynamic.md @@ -9,7 +9,7 @@ We introduce the velocity as a unknown, $\vec{v}=\frac{\partial u}{\partial t}$, % Displacement-velocity \frac{\partial \vec{u}}{\partial t} &= \vec{v} \text{ in } \Omega, \\ % Elasticity -\rho(\vec{x}) \frac{\partial\vec{v}}{\partial t} &= \vec{f}(\vec{x},t) + \boldsymbol{\nabla} \cdot \boldsymbol{\sigma}(\vec{u}) \text{ in } \Omega, \\ +\rho(\vec{x}) \frac{\partial\vec{v}}{\partial t} &= \vec{f}(\vec{x},t) + \boldsymbol{\nabla} \cdot \boldsymbol{\sigma}(\vec{u}) + \boldsymbol{\nabla} \cdot {\bf M} \text{ in } \Omega, \\ % Neumann \boldsymbol{\sigma} \cdot \vec{n} &= \vec{\tau}(\vec{x},t) \text{ on } \Gamma_\tau, \\ % Dirichlet diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index dcf1664060..5fd7639151 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -158,6 +158,21 @@ pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology: assert(auxiliaryFactory); auxiliaryFactory->setValuesFromDB(); + // Scale Moment Tensor Values + PetscDM dm = auxiliaryField->getDM(); + PetscVec v = auxiliaryField->getLocalVector(); + PylithScalar* array; + PylithScalar* ptr; + PetscErrorCode err; + err = VecGetArray(v, &array);PYLITH_CHECK_ERROR(err); + PetscInt dim; + err = DMGetDimension(dm, &dim);PYLITH_CHECK_ERROR(err); + for (int p = 0; p < _pointCoords.size() / dim; ++p) { + err = DMPlexPointLocalRef(dm, _cellNumber[p], array, (void*) &ptr);PYLITH_CHECK_ERROR(err); + ptr[0] /= _cellVolume[p]; + } + err = VecRestoreArray(v, &array);PYLITH_CHECK_ERROR(err); + // Debug option auxiliaryField->view("MomentTensor auxiliary field."); diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index db946143b8..32a7806871 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -190,13 +190,36 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, // pylith::sources::Source numLeaves); // PetscMPIInt rank; err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); - for (PetscInt p = 0; p < _pointCoords.size() / dim; ++p) { + + PetscInt pcs = _pointCoords.size() / dim; + _cellNumber.resize(pcs); + _cellVolume.resize(pcs); + + for (PetscInt p = 0; p < pcs; ++p) { PetscPrintf(PETSC_COMM_SELF, "[%i] OUTPUT rank: %i, index: %i, label: %s, labelValue: %i \n", (int)rank, (PetscInt)remotePoints[p].rank, (PetscInt)remotePoints[p].index, labelName, (int) labelValue); if ((remotePoints[p].index >= 0)) { + PetscReal cV; err = DMLabelSetValue(label, remotePoints[p].index, labelValue);PYLITH_CHECK_ERROR(err); + err = DMPlexComputeCellGeometryFVM(dmSoln,remotePoints[p].index, &cV, NULL, NULL);PYLITH_CHECK_ERROR(err); + _cellVolume[p] = cV; + _cellNumber[p] = remotePoints[p].index; } } // for - DMLabelView(label, NULL); + PetscIS cellIS; + err = DMLabelGetStratumIS(label, labelValue, &cellIS);PYLITH_CHECK_ERROR(err); + if (cellIS) { + const PetscInt* cells; + err = ISGetIndices(cellIS, &cells);PYLITH_CHECK_ERROR(err); + for (PetscInt p = 0; p < pcs; ++p) { + PetscInt loc; + err = PetscFindInt(_cellNumber[p], pcs, cells, &loc);PYLITH_CHECK_ERROR(err); + assert(loc >= 0); + _cellNumber[p] = loc; + } + err = ISRestoreIndices(cellIS, &cells);PYLITH_CHECK_ERROR(err); + } + err = DMLabelView(label, NULL);PYLITH_CHECK_ERROR(err); + err = PetscSFDestroy(&sfPoints);PYLITH_CHECK_ERROR(err); // printf("In MomentTensorForce end\n"); // // DMView(dmSoln, NULL); diff --git a/libsrc/pylith/sources/Source.hh b/libsrc/pylith/sources/Source.hh index 7bae44c5a9..5674748a2a 100644 --- a/libsrc/pylith/sources/Source.hh +++ b/libsrc/pylith/sources/Source.hh @@ -118,6 +118,8 @@ protected: std::string _labelName; ///< Name of label to identify source points in mesh. int _labelValue; ///< Value of label to identify source points in mesh. std::string _subfieldName; ///< Name of solution subfield for boundary condition. + pylith::int_array _cellNumber; ///< Numbers of cells used for source + pylith::scalar_array _cellVolume; ///< Volumes of cell used for source // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc index dc233c1c0b..35f948f970 100644 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc +++ b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc @@ -66,7 +66,7 @@ pylith::sources::TestAuxiliaryFactoryMomentTensorForce::TestAuxiliaryFactoryMome componentNames, componentNames.size(), pylith::topology::Field::TENSOR, - _data->normalizer->getPressureScale() + _data->normalizer->getPressureScale() * normalizer->getLengthScale() * normalizer->getLengthScale() * normalizer->getLengthScale(); ); info.fe = pylith::topology::Field::Discretization( 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false From 40967928048917feb74a27c9db48e29c067f1287 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 4 Jun 2025 16:12:19 -0600 Subject: [PATCH 46/65] Added ability to time shift wavelet to zero phase --- libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc index 34948e3371..f3b67adcef 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -100,7 +100,9 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { // time description.componentNames.resize(1); description.componentNames[0] = subfieldName; description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; + // description.validator = pylith::topology::FieldQuery::validatorNonnegative; + description.validator = NULL; + _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); this->setSubfieldQuery(subfieldName); From 5766b29edf720558b815c655ac8dd915ffb57e41 Mon Sep 17 00:00:00 2001 From: "Matthew G. Knepley" Date: Thu, 5 Jun 2025 09:53:40 -0600 Subject: [PATCH 47/65] Parallel fix --- libsrc/pylith/sources/MomentTensorForce.cc | 1 + libsrc/pylith/sources/Source.cc | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 5fd7639151..9c87ee9288 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -168,6 +168,7 @@ pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology: PetscInt dim; err = DMGetDimension(dm, &dim);PYLITH_CHECK_ERROR(err); for (int p = 0; p < _pointCoords.size() / dim; ++p) { + if (_cellNumber[p] < 0) continue; err = DMPlexPointLocalRef(dm, _cellNumber[p], array, (void*) &ptr);PYLITH_CHECK_ERROR(err); ptr[0] /= _cellVolume[p]; } diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 32a7806871..483d0438ad 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -190,7 +190,7 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, // pylith::sources::Source numLeaves); // PetscMPIInt rank; err = MPI_Comm_rank(PetscObjectComm((PetscObject)dmSoln), &rank); - + PetscInt pcs = _pointCoords.size() / dim; _cellNumber.resize(pcs); _cellVolume.resize(pcs); @@ -203,6 +203,9 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, err = DMPlexComputeCellGeometryFVM(dmSoln,remotePoints[p].index, &cV, NULL, NULL);PYLITH_CHECK_ERROR(err); _cellVolume[p] = cV; _cellNumber[p] = remotePoints[p].index; + } else { + _cellVolume[p] = -1.; + _cellNumber[p] = -1; } } // for PetscIS cellIS; @@ -212,6 +215,7 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, err = ISGetIndices(cellIS, &cells);PYLITH_CHECK_ERROR(err); for (PetscInt p = 0; p < pcs; ++p) { PetscInt loc; + if (_cellNumber[p] < 0) continue; err = PetscFindInt(_cellNumber[p], pcs, cells, &loc);PYLITH_CHECK_ERROR(err); assert(loc >= 0); _cellNumber[p] = loc; @@ -219,7 +223,7 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, err = ISRestoreIndices(cellIS, &cells);PYLITH_CHECK_ERROR(err); } err = DMLabelView(label, NULL);PYLITH_CHECK_ERROR(err); - + err = PetscSFDestroy(&sfPoints);PYLITH_CHECK_ERROR(err); // printf("In MomentTensorForce end\n"); // // DMView(dmSoln, NULL); From e4944ba8c1a239d7687a9676227be810efafe83c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 5 Jun 2025 12:35:43 -0600 Subject: [PATCH 48/65] Added cfg for petsc test --- examples/point-source/pylithapp.cfg | 10 -- examples/point-source/step03_ricker.cfg | 171 ++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 examples/point-source/step03_ricker.cfg diff --git a/examples/point-source/pylithapp.cfg b/examples/point-source/pylithapp.cfg index ffd19a62f8..16a1b792da 100644 --- a/examples/point-source/pylithapp.cfg +++ b/examples/point-source/pylithapp.cfg @@ -33,16 +33,6 @@ pylithapp = 1 [pylithapp.journal.debug] timedependent = 0 -# ---------------------------------------------------------------------- -# mesh_generator -# ---------------------------------------------------------------------- -[pylithapp.mesh_generator] -# Set the reader to match the type of mesh file. -reader = pylith.meshio.MeshIOCubit -reader.filename = mesh_quad.exo - -# Set the Cartesian coordinate system. -reader.coordsys.space_dim = 2 # ---------------------------------------------------------------------- diff --git a/examples/point-source/step03_ricker.cfg b/examples/point-source/step03_ricker.cfg new file mode 100644 index 0000000000..8e81b8c2fd --- /dev/null +++ b/examples/point-source/step03_ricker.cfg @@ -0,0 +1,171 @@ +[pylithapp.metadata] +# y +# ^ +# | +# --> x + +base = [pylithapp.cfg] +description = Ricker source test. +authors = [Robert Walker] +keywords = [Ricker source, time-dependent Dirichlet boundary condition] +arguments = [step03_ricker.cfg] +version = 1.0.0 +pylith_version = [>=3.0, <7.0] + +features = [ + pylith.problems.SolnDispVel, + pylith.bc.DirichletTimeDependent, + spatialdata.spatialdb.ZeroDB + ] + +[pylithapp] +# File with version information and parameters (including defaults). +# +# You can view this file using the pylith_parameters application or +# online at https://geodynamics.github.io/pylith_parameters/. +dump_parameters.filename = output/step03_ricker-parameters.json +problem.progress_monitor.filename = output/step03_ricker-progress.txt + +# Set the name of the problem that will be used to construct the +# output filenames. The default directory for output is 'output'. +problem.defaults.name = step03_ricker + +# ---------------------------------------------------------------------- +# problem +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Use the nonlinear solver to verify residual and Jacobian are consistent. +solver = nonlinear +formulation = dynamic + +# Nondimensionalize problem using wave propagation parameters. +normalizer = spatialdata.units.NondimElasticDynamic +normalizer.mass_density = 2500.0*kg/m**3 +normalizer.shear_wave_speed = 1000.0*m/s +normalizer.wave_period = 1.0*s + +defaults.quadrature_order = 1 + + +# Set the discretization for each of the solution subfields. +# +solution = pylith.problems.SolnDispVel + +solution.subfields.displacement.basis_order = 1 +solution.subfields.velocity.basis_order = 1 + +solution_observers = [domain] + +start_time = 0.0*s +end_time = 3.0*s +initial_dt = 0.01*s + +# ---------------------------------------------------------------------- +# mesh_generator +# ---------------------------------------------------------------------- +[pylithapp.mesh_generator] +# Set the reader to match the type of mesh file. +reader = pylith.meshio.MeshIOPetsc +#reader = pylith.meshio.MeshIOCubit +#reader.filename = mesh_quad.exo + +# Set the Cartesian coordinate system. +#reader.coordsys.space_dim = 2 + +#refiner = pylith.topology.RefineUniform +# ---------------------------------------------------------------------- +# materials +# ---------------------------------------------------------------------- +[pylithapp.problem] +# Create an array of one material +materials = [elastic] + +# We use the default material (elasticity) and rheology +# (isotropic, linearly elastic). + +[pylithapp.problem.materials.elastic] +# id must match the values in the mesh material-ids. +description = Elastic material +label_value = 1 +observers = [] +#observers.observer.trigger.num_skip = 10 +# We will use uniform material properties, so we use the UniformDB +# spatial database. +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Elastic properties +db_auxiliary_field.values = [density, vs, vp] +db_auxiliary_field.data = [1800*kg/m**3, 1.3*km/s, 3.0*km/s] + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.density.basis_order = 0 +bulk_rheology.auxiliary_subfields.bulk_modulus.basis_order = 0 +bulk_rheology.auxiliary_subfields.shear_modulus.basis_order = 0 + +# ---------------------------------------------------------------------- +# sources +# ---------------------------------------------------------------------- + +[pylithapp.problem] +sources = [source] + +sources.source = pylith.sources.MomentTensorForce +[pylithapp.problem.sources] +source.source_time_function = pylith.sources.RickerWavelet + +[pylithapp.problem.sources.source] +description = Ricker Source +label_value = 2 +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 + +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +#db_auxiliary_field.data = [0*newton*m, 0*newton*m, 1000.0*newton*m, 0.0*newton*m, -1.0*s, 0.5] +db_auxiliary_field.data = [1e14*newton*m, 1e14*newton*m, 0.0*newton*m, 1e14*newton*m, 0.0*s, 0.5] + + +# Set the discretization of the material auxiliary fields (properties). +# We have uniform material properties, so we can use a basis order of 0. +auxiliary_subfields.moment_tensor.basis_order = 0 +auxiliary_subfields.time_delay.basis_order = 0 +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 + + + +# ---------------------------------------------------------------------- +# initial conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] +ic = [domain] +ic.domain = pylith.problems.InitialConditionDomain + +[pylithapp.problem.ic.domain] +db = spatialdata.spatialdb.UniformDB +db.description = Initial conditions over domain +db.values = [displacement_x, displacement_y] +db.data = [0.0*m, 0.0*m] + +# ---------------------------------------------------------------------- +# boundary conditions +# ---------------------------------------------------------------------- +[pylithapp.problem] + + +# ---------------------------------------------------------------------- +# PETSc +# ---------------------------------------------------------------------- +[pylithapp.petsc] +ts_type = rk +ts_rk_type = 3bs +ts_adapt_dt_max = 0.01 +dm_partition_view = True + +dm_plex_box_faces = 100,100 +dm_plex_box_lower = 0,0 +dm_plex_box_upper = 10000,10000 + + +# End of file From f015c2c35df4f9041803db5ac548ef3b11f8857b Mon Sep 17 00:00:00 2001 From: "Matthew G. Knepley" Date: Thu, 5 Jun 2025 13:15:42 -0600 Subject: [PATCH 49/65] MeshIOPetsc: Allow creation from command line --- libsrc/pylith/meshio/MeshIOPetsc.cc | 7 +++++++ pylith/meshio/MeshIOPetsc.py | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libsrc/pylith/meshio/MeshIOPetsc.cc b/libsrc/pylith/meshio/MeshIOPetsc.cc index e2e67c217a..923262c915 100644 --- a/libsrc/pylith/meshio/MeshIOPetsc.cc +++ b/libsrc/pylith/meshio/MeshIOPetsc.cc @@ -299,6 +299,13 @@ pylith::meshio::_MeshIOPetsc::fixMaterialLabel(PetscDM* dmMesh) { PetscDMLabel dmLabel = NULL; PetscInt pStart = -1, pEnd = -1; err = DMGetLabel(*dmMesh, labelName, &dmLabel);PYLITH_CHECK_ERROR(err); + if (!dmLabel) { + err = DMCreateLabel(*dmMesh, labelName);PYLITH_CHECK_ERROR(err); + err = DMGetLabel(*dmMesh, labelName, &dmLabel);PYLITH_CHECK_ERROR(err); + for (PetscInt point = cStart; point < cEnd; ++point) { + err = DMLabelSetValue(dmLabel, point, 1);PYLITH_CHECK_ERROR(err); + } + } err = DMLabelGetBounds(dmLabel, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); if (pStart == cStart) { pStart = cEnd; } if (pEnd == cEnd) { pEnd = cStart; } diff --git a/pylith/meshio/MeshIOPetsc.py b/pylith/meshio/MeshIOPetsc.py index 02b70239e6..674c50a533 100644 --- a/pylith/meshio/MeshIOPetsc.py +++ b/pylith/meshio/MeshIOPetsc.py @@ -5,7 +5,7 @@ # Copyright (c) 2010-2025, University of California, Davis and the PyLith Development Team. # All rights reserved. # -# See https://mit-license.org/ and LICENSE.md and for license information. +# See https://mit-license.org/ and LICENSE.md and for license information. # ================================================================================================= import pathlib @@ -57,7 +57,7 @@ def __init__(self, mode=MeshIOObj.READ, name="meshiopetsc"): def preinitialize(self): """Do minimal initialization.""" MeshIOObj.preinitialize(self) - ModuleMeshIOPetsc.setFilename(self, self.filename) + if len(self.filename) > 0: ModuleMeshIOPetsc.setFilename(self, self.filename) ModuleMeshIOPetsc.setPrefix(self, self.prefix) ModuleMeshIOPetsc.setGmshMarkRecursive(self, self.gmshMarkRecursive) @@ -72,7 +72,7 @@ def _createModuleObj(self): ModuleMeshIOPetsc.__init__(self) def _validate(self, context): - if 0 == len(self.filename) and self.mode == self.READ and not pathlib.Path(self.filename).is_file(): + if 0 < len(self.filename) and self.mode == self.READ and not pathlib.Path(self.filename).is_file(): context.error(IOError(f"Input mesh '{self.filename}' not found.")) # FACTORIES //////////////////////////////////////////////////////////// From 3b8d922a35db99be46b23ef4da427cc6a2d24a97 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 5 Jun 2025 16:43:24 -0600 Subject: [PATCH 50/65] Added break to switch statement --- libsrc/pylith/materials/Poroelasticity.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc/pylith/materials/Poroelasticity.cc b/libsrc/pylith/materials/Poroelasticity.cc index 66510d1de3..1be241b734 100644 --- a/libsrc/pylith/materials/Poroelasticity.cc +++ b/libsrc/pylith/materials/Poroelasticity.cc @@ -499,6 +499,7 @@ pylith::materials::Poroelasticity::_setKernelsResidual(pylith::feassemble::Integ kernels[3] = ResidualKernels("pressure", pylith::feassemble::Integrator::RHS, g0p, g1p); kernels[4] = ResidualKernels("velocity", pylith::feassemble::Integrator::LHS, f0v, f1v); kernels[5] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); + break; } // DYNAMIC default: PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); From 2a10bbe2c1c0407efef6a2a21cf32f33a70cf415 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 10:58:42 -0600 Subject: [PATCH 51/65] Restricted branch to point source only. --- libsrc/pylith/Makefile.am | 12 - libsrc/pylith/fekernels/GaussianWavelet.cc | 134 ------ libsrc/pylith/fekernels/GaussianWavelet.hh | 57 ++- libsrc/pylith/fekernels/Makefile.am | 5 +- libsrc/pylith/fekernels/PointForce.cc | 66 --- libsrc/pylith/fekernels/PointForce.hh | 83 ---- libsrc/pylith/fekernels/Poroelasticity.hh | 35 +- libsrc/pylith/fekernels/RickerWavelet.cc | 140 ------ libsrc/pylith/fekernels/SquarePulseSource.cc | 69 --- libsrc/pylith/fekernels/SquarePulseSource.hh | 83 ---- libsrc/pylith/fekernels/SquareWavelet.cc | 138 ------ libsrc/pylith/fekernels/SquareWavelet.hh | 60 ++- libsrc/pylith/fekernels/TimeHistorySource.hh | 194 -------- libsrc/pylith/fekernels/WellboreSource.cc | 148 ------ libsrc/pylith/fekernels/WellboreSource.hh | 104 ----- libsrc/pylith/fekernels/fekernelsfwd.hh | 9 - libsrc/pylith/materials/Poroelasticity.cc | 1 + .../sources/AuxiliaryFactoryPointForce.cc | 106 ----- .../sources/AuxiliaryFactoryPointForce.hh | 60 --- .../AuxiliaryFactorySquarePulseSource.cc | 100 ----- .../AuxiliaryFactorySquarePulseSource.hh | 60 --- .../AuxiliaryFactoryTimeHistorySource.cc | 421 ------------------ .../AuxiliaryFactoryTimeHistorySource.hh | 114 ----- .../sources/AuxiliaryFactoryWellboreSource.cc | 337 -------------- .../sources/AuxiliaryFactoryWellboreSource.hh | 84 ---- libsrc/pylith/sources/Makefile.am | 7 - .../sources/MomentTensorForceTimeHistory.cc | 298 ------------- libsrc/pylith/sources/PointForce.cc | 283 ------------ libsrc/pylith/sources/PointForce.hh | 152 ------- libsrc/pylith/sources/TimeHistorySource.cc | 417 ----------------- libsrc/pylith/sources/TimeHistorySource.hh | 156 ------- libsrc/pylith/sources/WellboreSource.cc | 300 ------------- libsrc/pylith/sources/WellboreSource.hh | 148 ------ libsrc/pylith/sources/sourcesfwd.hh | 12 - modulesrc/sources/Makefile.am | 3 - modulesrc/sources/PointForce.i | 117 ----- .../sources/SourceTimeFunctionPointForce.i | 84 ---- modulesrc/sources/SquarePulseSource.i | 117 ----- modulesrc/sources/WellboreSource.i | 117 ----- modulesrc/sources/sources.i | 3 - pylith/Makefile.am | 5 +- pylith/sources/AuxSubfieldsPointForce.py | 63 --- .../sources/AuxSubfieldsSquarePulseSource.py | 64 --- pylith/sources/AuxSubfieldsWellboreSource.py | 89 ---- pylith/sources/PointForce.py | 68 --- pylith/sources/SquarePulseSource.py | 71 --- pylith/sources/TimeHistorySource.py | 113 ----- pylith/sources/WellboreSource.py | 71 --- pylith/sources/__init__.py | 6 - 49 files changed, 149 insertions(+), 5235 deletions(-) delete mode 100644 libsrc/pylith/fekernels/GaussianWavelet.cc delete mode 100644 libsrc/pylith/fekernels/PointForce.cc delete mode 100644 libsrc/pylith/fekernels/PointForce.hh delete mode 100644 libsrc/pylith/fekernels/RickerWavelet.cc delete mode 100644 libsrc/pylith/fekernels/SquarePulseSource.cc delete mode 100644 libsrc/pylith/fekernels/SquarePulseSource.hh delete mode 100644 libsrc/pylith/fekernels/SquareWavelet.cc delete mode 100644 libsrc/pylith/fekernels/TimeHistorySource.hh delete mode 100644 libsrc/pylith/fekernels/WellboreSource.cc delete mode 100644 libsrc/pylith/fekernels/WellboreSource.hh delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh delete mode 100644 libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc delete mode 100644 libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc delete mode 100644 libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh delete mode 100644 libsrc/pylith/sources/MomentTensorForceTimeHistory.cc delete mode 100644 libsrc/pylith/sources/PointForce.cc delete mode 100644 libsrc/pylith/sources/PointForce.hh delete mode 100644 libsrc/pylith/sources/TimeHistorySource.cc delete mode 100644 libsrc/pylith/sources/TimeHistorySource.hh delete mode 100644 libsrc/pylith/sources/WellboreSource.cc delete mode 100644 libsrc/pylith/sources/WellboreSource.hh delete mode 100644 modulesrc/sources/PointForce.i delete mode 100644 modulesrc/sources/SourceTimeFunctionPointForce.i delete mode 100644 modulesrc/sources/SquarePulseSource.i delete mode 100644 modulesrc/sources/WellboreSource.i delete mode 100644 pylith/sources/AuxSubfieldsPointForce.py delete mode 100644 pylith/sources/AuxSubfieldsSquarePulseSource.py delete mode 100644 pylith/sources/AuxSubfieldsWellboreSource.py delete mode 100644 pylith/sources/PointForce.py delete mode 100644 pylith/sources/SquarePulseSource.py delete mode 100644 pylith/sources/TimeHistorySource.py delete mode 100644 pylith/sources/WellboreSource.py diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index a457f6c93d..498aaa4b90 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -70,11 +70,6 @@ libpylith_la_SOURCES = \ fekernels/Tensor.cc \ fekernels/IsotropicLinearGenMaxwell.cc \ fekernels/IsotropicPowerLaw.cc \ - fekernels/SquareWavelet.cc \ - fekernels/GaussianWavelet.cc \ - fekernels/PointForce.cc \ - fekernels/SquarePulseSource.cc \ - fekernels/WellboreSource.cc \ materials/Material.cc \ materials/Elasticity.cc \ materials/RheologyElasticity.cc \ @@ -135,21 +130,14 @@ libpylith_la_SOURCES = \ problems/ProgressMonitorTime.cc \ problems/ProgressMonitorStep.cc \ sources/AuxiliaryFactoryMomentTensorForce.cc \ - sources/AuxiliaryFactoryPointForce.cc \ sources/AuxiliaryFactorySourceTime.cc \ - sources/AuxiliaryFactorySquarePulseSource.cc \ - sources/AuxiliaryFactoryWellboreSource.cc \ sources/DerivedFactoryMomentTensorForce.cc \ sources/GaussianWavelet.cc \ - sources/MomentTensorForce.cc \ - sources/PointForce.cc \ sources/SquareWavelet.cc \ sources/RickerWavelet.cc \ sources/TimeHistoryWavelet.cc \ sources/Source.cc \ sources/SourceTimeFunctionMomentTensorForce.cc \ - sources/SquarePulseSource.cc \ - sources/WellboreSource.cc \ topology/Mesh.cc \ topology/MeshOps.cc \ topology/FieldBase.cc \ diff --git a/libsrc/pylith/fekernels/GaussianWavelet.cc b/libsrc/pylith/fekernels/GaussianWavelet.cc deleted file mode 100644 index 5193f0cdcf..0000000000 --- a/libsrc/pylith/fekernels/GaussianWavelet.cc +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/GaussianWavelet.hh" - -#include // USES assert() -#include // debugging. - -// ===================================================================================================================== -// Kernels for the Gaussian Source Time Function in 2D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::GaussianWaveletPlaneStrain::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 2; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; - - // GaussianWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); - // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %d\n", (double)timeDelay); - // PetscPrintf(PETSC_COMM_WORLD, "t %d\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "gaussianWavelet %d\n", (double)gaussianwavelet); - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * gaussianwavelet; - } // for -} // g1v - - -// ===================================================================================================================== -// Kernels for the Gaussian Source Time Function in 3D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::GaussianWavelet3D::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 3; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; - - // GaussianWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * gaussianwavelet; - } // for -} // g1v - - -// End of file diff --git a/libsrc/pylith/fekernels/GaussianWavelet.hh b/libsrc/pylith/fekernels/GaussianWavelet.hh index 7c854f1ed9..065e6698b7 100644 --- a/libsrc/pylith/fekernels/GaussianWavelet.hh +++ b/libsrc/pylith/fekernels/GaussianWavelet.hh @@ -79,8 +79,34 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); - + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 2; + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; + + // GaussianWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %d\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %d\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "gaussianWavelet %d\n", (double)gaussianwavelet); + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * gaussianwavelet; + } // for + } // g1v }; // GaussianWaveletPlaneStrain // ===================================================================================================================== @@ -134,8 +160,33 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_gaussianwaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar f0 = a[aOff[i_gaussianwaveletCenterFrequency]]; + + // GaussianWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar gaussianwavelet = PetscExpReal( (PETSC_PI*PETSC_PI * f0*f0) * rt*rt) / (2.0 * (PETSC_PI*PETSC_PI * f0*f0) ); + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * gaussianwavelet; + } // for + } // g1v }; // GaussianWaveletPlaneStrain #endif /* pylith_fekernels_gaussianwavelet_hh */ diff --git a/libsrc/pylith/fekernels/Makefile.am b/libsrc/pylith/fekernels/Makefile.am index db02849a5e..0bef115461 100644 --- a/libsrc/pylith/fekernels/Makefile.am +++ b/libsrc/pylith/fekernels/Makefile.am @@ -31,13 +31,10 @@ subpkginclude_HEADERS = \ NeumannTimeDependent.hh \ AbsorbingDampers.hh \ FaultCohesiveKin.hh \ - WellboreSource.hh \ - SquarePulseSource.hh \ - TimeHistorySource.hh \ SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ - PointForce.hh + TimeHistoryWavelet.hh dist_noinst_HEADERS = diff --git a/libsrc/pylith/fekernels/PointForce.cc b/libsrc/pylith/fekernels/PointForce.cc deleted file mode 100644 index 1eabc0fadc..0000000000 --- a/libsrc/pylith/fekernels/PointForce.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/PointForce.hh" - -#include // USES assert() -#include // debugging. - -// ---------------------------------------------------------------------- -// f0 entry function for displacement equation: f0u = \dot{u}. -void -pylith::fekernels::PointForce::f0u(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - assert(sOff); - assert(s); - assert(s_t); - assert(f0); - - // Incoming re-packed solution field. - const PylithInt i_displacement = 0; - - // Incoming re-packed auxiliary field. - const PylithInt i_pointForce = 0; - - const PylithScalar *pointForce = &a[aOff[i_pointForce]]; - - for (PylithInt i = 0; i < dim; ++i) { - f0[i] += pointForce[i]; - } // for -} - - -// End of file diff --git a/libsrc/pylith/fekernels/PointForce.hh b/libsrc/pylith/fekernels/PointForce.hh deleted file mode 100644 index 0167d28404..0000000000 --- a/libsrc/pylith/fekernels/PointForce.hh +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -/** @file libsrc/fekernels/PointForce.hh - * - */ - -#if !defined(pylith_fekernels_PointForce_hh) -#define pylith_fekernels_PointForce_hh - -// Include directives --------------------------------------------------- -#include "fekernelsfwd.hh" // forward declarations - -#include "pylith/utils/types.hh" - -class pylith::fekernels::PointForce { - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - - /** Kernel interface. - * - * @param[in] dim Spatial dimension. - * @param[in] numS Number of registered subfields in solution field. - * @param[in] numA Number of registered subfields in auxiliary field. - * @param[in] sOff Offset of registered subfields in solution field [numS]. - * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. - * @param[in] s Solution field with all subfields. - * @param[in] s_t Time derivative of solution field. - * @param[in] s_x Gradient of solution field. - * @param[in] aOff Offset of registered subfields in auxiliary field [numA] - * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] - * @param[in] a Auxiliary field with all subfields. - * @param[in] a_t Time derivative of auxiliary field. - * @param[in] a_x Gradient of auxiliary field. - * @param[in] t Time for residual evaluation. - * @param[in] x Coordinates of point evaluation. - * @param[in] numConstants Number of registered constants. - * @param[in] constants Array of registered constants. - * @param[out] f0 [dim]. - */ - - /** f0 function for displacement equation - * - */ - static void f0u(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]); - -}; // PointForce - -#endif /* pylith_fekernels_PointForce_hh */ - -/* End of file */ diff --git a/libsrc/pylith/fekernels/Poroelasticity.hh b/libsrc/pylith/fekernels/Poroelasticity.hh index db3978cb54..1acd62a571 100644 --- a/libsrc/pylith/fekernels/Poroelasticity.hh +++ b/libsrc/pylith/fekernels/Poroelasticity.hh @@ -280,7 +280,7 @@ public: context->displacement_t = &s_t[sOff[i_displacement]]; context->displacement_x = &s_x[sOff_x[i_displacement]]; context->pressure = s[sOff[i_pressure]]; - context->pressure_t = s_t[sOff[i_pressure]]; + // context->pressure_t = s_t[sOff[i_pressure]]; context->pressure_x = &s_x[sOff_x[i_pressure]]; context->velocity = &s[sOff[i_velocity]]; context->velocity_t = &s_t[sOff[i_velocity]]; @@ -1126,6 +1126,39 @@ public: } // for } // Jf0vv_explicit + /** Jf0 function for displacement equation: Jf0uu = s_tshift. + * + * Solution fields: [disp(dim), vel(dim)] + */ + static inline + void Jf0uu_stshift(const PylithInt dim, + const PylithInt numS, + const PylithInt numA, + const PylithInt sOff[], + const PylithInt sOff_x[], + const PylithScalar s[], + const PylithScalar s_t[], + const PylithScalar s_x[], + const PylithInt aOff[], + const PylithInt aOff_x[], + const PylithScalar a[], + const PylithScalar a_t[], + const PylithScalar a_x[], + const PylithReal t, + const PylithReal s_tshift, + const PylithScalar x[], + const PylithInt numConstants, + const PylithScalar constants[], + PylithScalar Jf0[]) { + const PylithInt _numS = 3; + assert(_numS == numS); + assert(s_tshift > 0); + + for (PylithInt i = 0; i < dim; ++i) { + Jf0[i*dim+i] += s_tshift; + } // for + } // Jf0uu_stshift + // --------------------------------------------------------------------------------------------------------------------- /* * Jf0pdotp function for poroelasticity equation, quasistatic. diff --git a/libsrc/pylith/fekernels/RickerWavelet.cc b/libsrc/pylith/fekernels/RickerWavelet.cc deleted file mode 100644 index 5921f106d4..0000000000 --- a/libsrc/pylith/fekernels/RickerWavelet.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/RickerWavelet.hh" - -#include // USES assert() -#include // debugging. - -// ===================================================================================================================== -// Kernels for the Ricker Source Time Function in 2D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::RickerWaveletPlaneStrain::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 2; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_rickerwaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; - - // RickerWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * - PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); - - // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); - // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)rickerwaveletCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "rickerWavelet %f\n", (double)rickerwavelet); - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * rickerwavelet; - // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - ricker\n", (int)i, (double)g1[i]); - } // for -} // g1v - - -// ===================================================================================================================== -// Kernels for the Ricker Source Time Function in 3D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::RickerWavelet3D::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 3; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_rickerwaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar rickerwaveletCenterFrequency = a[aOff[i_rickerwaveletCenterFrequency]]; - - // RickerWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar rickerwavelet = (1.0 - 2.0*PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt) * - PetscExpReal(-PETSC_PI*PETSC_PI*rickerwaveletCenterFrequency*rickerwaveletCenterFrequency*rt*rt); - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * rickerwavelet; - } // for -} // g1v - - -// End of file diff --git a/libsrc/pylith/fekernels/SquarePulseSource.cc b/libsrc/pylith/fekernels/SquarePulseSource.cc deleted file mode 100644 index df1c5ccc97..0000000000 --- a/libsrc/pylith/fekernels/SquarePulseSource.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/SquarePulseSource.hh" - -#include // USES assert() -#include // debugging. - -// ---------------------------------------------------------------------- -// f0 entry function for displacement equation: f0u = \dot{u}. -void -pylith::fekernels::SquarePulseSource::f0p(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - assert(sOff); - assert(s); - assert(s_t); - assert(f0); - - // Incoming re-packed solution field. - // const PylithInt i_pressure = 1; - - // Incoming re-packed auxiliary field. - const PylithInt i_volumeFlowRate = 0; - const PylithInt i_timeDelay = 1; - - const PylithScalar volumeFlowRate = a[aOff[i_volumeFlowRate]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - - PylithScalar rt = t - timeDelay; - PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; - - f0[0] += volumeFlowRate * squarewavelet; -} // f0p - - -// End of file diff --git a/libsrc/pylith/fekernels/SquarePulseSource.hh b/libsrc/pylith/fekernels/SquarePulseSource.hh deleted file mode 100644 index 5bdf419c2b..0000000000 --- a/libsrc/pylith/fekernels/SquarePulseSource.hh +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -/** @file libsrc/fekernels/SquarePulseSource.hh - * - */ - -#if !defined(pylith_fekernels_SquarePulseSource_hh) -#define pylith_fekernels_SquarePulseSource_hh - -// Include directives --------------------------------------------------- -#include "fekernelsfwd.hh" // forward declarations - -#include "pylith/utils/types.hh" - -class pylith::fekernels::SquarePulseSource -{ - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - /** Kernel interface. - * - * @param[in] dim Spatial dimension. - * @param[in] numS Number of registered subfields in solution field. - * @param[in] numA Number of registered subfields in auxiliary field. - * @param[in] sOff Offset of registered subfields in solution field [numS]. - * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. - * @param[in] s Solution field with all subfields. - * @param[in] s_t Time derivative of solution field. - * @param[in] s_x Gradient of solution field. - * @param[in] aOff Offset of registered subfields in auxiliary field [numA] - * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] - * @param[in] a Auxiliary field with all subfields. - * @param[in] a_t Time derivative of auxiliary field. - * @param[in] a_x Gradient of auxiliary field. - * @param[in] t Time for residual evaluation. - * @param[in] x Coordinates of point evaluation. - * @param[in] numConstants Number of registered constants. - * @param[in] constants Array of registered constants. - * @param[out] f0 [dim]. - */ - - /** f0 function for pressure equation - * - */ - static void f0p(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]); - -}; // SquarePulseSource - -#endif /* pylith_fekernels_SquarePulseSource_hh */ - -/* End of file */ diff --git a/libsrc/pylith/fekernels/SquareWavelet.cc b/libsrc/pylith/fekernels/SquareWavelet.cc deleted file mode 100644 index 3296517025..0000000000 --- a/libsrc/pylith/fekernels/SquareWavelet.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/SquareWavelet.hh" - -#include // USES assert() -#include // debugging. - -// ===================================================================================================================== -// Kernels for the Square Source Time Function in 2D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::SquareWaveletPlaneStrain::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 2; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_squarewaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; - - // SquareWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; - - // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); - // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)squarewaveletCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "squareWavelet %f\n", (double)squarewavelet); - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * squarewavelet; - // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - square\n", (int)i, (double)g1[i]); - } // for -} // g1v - - -// ===================================================================================================================== -// Kernels for the Square Source Time Function in 3D. -// ===================================================================================================================== - -// ---------------------------------------------------------------------- -// g1 entry function for velocity equation -void -pylith::fekernels::SquareWavelet3D::g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - assert(sOff); - assert(s); - assert(g1); - - PylithInt _dim = 3; - - // Incoming re-packed solution field. - - // Incoming re-packed auxiliary field. - const PylithInt i_momentTensor = 0; - const PylithInt i_timeDelay = 1; - const PylithInt i_squarewaveletCenterFrequency = numA - 1; - - const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; - - // SquareWavelet source time function (time domain) - - PylithScalar rt = t - timeDelay; - PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * squarewavelet; - } // for -} // g1v - - -// End of file diff --git a/libsrc/pylith/fekernels/SquareWavelet.hh b/libsrc/pylith/fekernels/SquareWavelet.hh index 842c5997c6..76a5813958 100644 --- a/libsrc/pylith/fekernels/SquareWavelet.hh +++ b/libsrc/pylith/fekernels/SquareWavelet.hh @@ -79,8 +79,39 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + PylithInt _dim = 2; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_squarewaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; + + // SquareWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; + + // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); + // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); + // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)squarewaveletCenterFrequency); + // PetscPrintf(PETSC_COMM_WORLD, "squareWavelet %f\n", (double)squarewavelet); + + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * squarewavelet; + // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - square\n", (int)i, (double)g1[i]); + } // for + } // g1v }; // SquareWaveletPlaneStrain // ===================================================================================================================== @@ -134,8 +165,33 @@ public: const PylithScalar x[], const PylithInt numConstants, const PylithScalar constants[], - PylithScalar g1[]); + PylithScalar g1[]) { + assert(sOff); + assert(s); + assert(g1); + + PylithInt _dim = 3; + + // Incoming re-packed solution field. + + // Incoming re-packed auxiliary field. + const PylithInt i_momentTensor = 0; + const PylithInt i_timeDelay = 1; + const PylithInt i_squarewaveletCenterFrequency = numA - 1; + + const PylithScalar* momentTensor = &a[aOff[i_momentTensor]]; + const PylithScalar timeDelay = a[aOff[i_timeDelay]]; + const PylithScalar squarewaveletCenterFrequency = a[aOff[i_squarewaveletCenterFrequency]]; + + // SquareWavelet source time function (time domain) + + PylithScalar rt = t - timeDelay; + PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; + for (PylithInt i = 0; i < dim*dim; ++i) { + g1[i] -= momentTensor[i] * squarewavelet; + } // for + } // g1v }; // SquareWaveletPlaneStrain #endif /* pylith_fekernels_squarewavelet_hh */ diff --git a/libsrc/pylith/fekernels/TimeHistorySource.hh b/libsrc/pylith/fekernels/TimeHistorySource.hh deleted file mode 100644 index ba1cfa0bbb..0000000000 --- a/libsrc/pylith/fekernels/TimeHistorySource.hh +++ /dev/null @@ -1,194 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -/** @file libsrc/fekernels/TimeHistorySource.hh - * - */ - -#if !defined(pylith_fekernels_timehistorysource_hh) -#define pylith_fekernels_timehistorysource_hh - -// Include directives --------------------------------------------------- -#include "fekernelsfwd.hh" // forward declarations - -#include "pylith/utils/types.hh" - -#include // USES assert() - -// ===================================================================================================================== -// Kernels for the TimeHistory Source Time Function in 2D. -// ===================================================================================================================== - -class pylith::fekernels::TimeHistorySourcePlaneStrain { - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - - /** Kernel interface. - * - * @param[in] dim Spatial dimension. - * @param[in] numS Number of registered subfields in solution field. - * @param[in] numA Number of registered subfields in auxiliary field. - * @param[in] sOff Offset of registered subfields in solution field [numS]. - * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. - * @param[in] s Solution field with all subfields. - * @param[in] s_t Time derivative of solution field. - * @param[in] s_x Gradient of solution field. - * @param[in] aOff Offset of registered subfields in auxiliary field [numA] - * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] - * @param[in] a Auxiliary field with all subfields. - * @param[in] a_t Time derivative of auxiliary field. - * @param[in] a_x Gradient of auxiliary field. - * @param[in] t Time for residual evaluation. - * @param[in] x Coordinates of point evaluation. - * @param[in] numConstants Number of registered constants. - * @param[in] constants Array of registered constants. - * @param[out] f0 [dim]. - */ - - /** g0 function for pressure equation - * - */ - static - void g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - const PylithInt _numA = 3; - assert(_numA == numA); - assert(aOff); - assert(a); - - // const PylithInt i_amplitude = aOff[numA - 3]; - const PylithInt i_volume_flow_rate = aOff[0]; - const PylithInt i_start_time = aOff[numA - 2]; - const PylithInt i_value = aOff[numA - 1]; - - PylithInt _dim = 2; - - // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); - // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorysourceCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "timehistorySource %f\n", (double)timehistorysource); - - const PylithScalar volume_flow_rate = a[aOff[i_volume_flow_rate]]; - f0[0] += volumeFlowRate * a[i_value]; - - // for (PylithInt i = 0; i < dim*dim; ++i) { - // g1[i] -= momentTensor[i] * a[i_value]; - // // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); - // } // for - } // g1v - -}; // TimeHistorySourcePlaneStrain - -// ===================================================================================================================== -// Kernels for the TimeHistory Source Time Function in 3D. -// ===================================================================================================================== - -class pylith::fekernels::TimeHistorySource3D { - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - - /** Kernel interface. - * - * @param[in] dim Spatial dimension. - * @param[in] numS Number of registered subfields in solution field. - * @param[in] numA Number of registered subfields in auxiliary field. - * @param[in] sOff Offset of registered subfields in solution field [numS]. - * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. - * @param[in] s Solution field with all subfields. - * @param[in] s_t Time derivative of solution field. - * @param[in] s_x Gradient of solution field. - * @param[in] aOff Offset of registered subfields in auxiliary field [numA] - * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] - * @param[in] a Auxiliary field with all subfields. - * @param[in] a_t Time derivative of auxiliary field. - * @param[in] a_x Gradient of auxiliary field. - * @param[in] t Time for residual evaluation. - * @param[in] x Coordinates of point evaluation. - * @param[in] numConstants Number of registered constants. - * @param[in] constants Array of registered constants. - * @param[out] f0 [dim]. - */ - - /** g1 function for velocity equation - * - */ - static inline - void g1v(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar g1[]) { - const PylithInt _numA = 3; - assert(_numA == numA); - assert(aOff); - assert(a); - - // const PylithInt i_amplitude = aOff[numA - 3]; - const PylithInt i_moment_tensor = aOff[0]; - // const PylithInt i_start_time = aOff[numA - 2]; - const PylithInt i_value = aOff[numA - 1]; - - PylithInt _dim = 3; - - // PetscPrintf(PETSC_COMM_WORLD, "timeDelay %f\n", (double)timeDelay); - // PetscPrintf(PETSC_COMM_WORLD, "t %f\n", (double)t); - // PetscPrintf(PETSC_COMM_WORLD, "Center Freq %f\n", (double)timehistorysourceCenterFrequency); - // PetscPrintf(PETSC_COMM_WORLD, "timehistorySource %f\n", (double)timehistorysource); - - const PylithScalar* momentTensor = &a[aOff[i_moment_tensor]]; - - for (PylithInt i = 0; i < dim*dim; ++i) { - g1[i] -= momentTensor[i] * a[i_value]; - // PetscPrintf(PETSC_COMM_WORLD, "g1[%i]: %f - timehistory\n", (int)i, (double)g1[i]); - } // for - } // g1v - -}; // g1v - -#endif /* pylith_fekernels_timehistorysource_hh */ - -/* End of file */ diff --git a/libsrc/pylith/fekernels/WellboreSource.cc b/libsrc/pylith/fekernels/WellboreSource.cc deleted file mode 100644 index d0f742a508..0000000000 --- a/libsrc/pylith/fekernels/WellboreSource.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -#include - -#include "pylith/fekernels/WellboreSource.hh" - -#include // USES assert() -#include // debugging. - -// ---------------------------------------------------------------------- -// f0 entry function for displacement equation: f0u = \dot{u}. -void -pylith::fekernels::WellboreSource::f0p(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]) { - assert(sOff); - assert(s); - assert(s_t); - assert(f0); - - // Incoming re-packed solution field. - const PylithInt i_pressure = 1; - - // Incoming re-packed auxiliary field. - const PylithInt i_fluidDensity = 0; - const PylithInt i_fluidViscosity = 1; - const PylithInt i_isotropicPermeability = 2; - const PylithInt i_wellboreRadius = 3; - const PylithInt i_wellboreLength = 4; - const PylithInt i_wellborePressure = 5; - const PylithInt i_wellboreCharacter = 6; - const PylithInt i_elementDimensions = 7; - const PylithInt i_r_e_constant = 8; - const PylithInt i_timeDelay = 9; - - const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - - PylithScalar rt = t - timeDelay; - PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; - - const PylithScalar pressure = s[sOff[i_pressure]]; - - const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; - const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; - const PylithScalar isotropicPermeability = a[aOff[i_isotropicPermeability]]; - const PylithScalar wellboreRadius = a[aOff[i_wellboreRadius]]; - const PylithScalar wellboreLength = a[aOff[i_wellboreLength]]; - const PylithScalar wellborePressure = a[aOff[i_wellborePressure]]; - const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; - const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; - - PylithScalar r_e = r_e_constant * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / - ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); - // Well Index, L**3 - PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); - - f0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity) * (pressure - wellborePressure) * squarewavelet; -} // f0p - - -// ---------------------------------------------------------------------- -// Jf0 function for pressure equation -void -pylith::fekernels::WellboreSource::Jf0pp(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal s_tshift, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar Jf0[]) { - // Incoming re-packed auxiliary field. - const PylithInt i_fluidDensity = 0; - const PylithInt i_fluidViscosity = 1; - const PylithInt i_isotropicPermeability = 2; - const PylithInt i_wellboreRadius = 3; - const PylithInt i_wellboreLength = 4; - const PylithInt i_wellboreCharacter = 6; - const PylithInt i_elementDimensions = 7; - const PylithInt i_r_e_constant = 8; - const PylithInt i_timeDelay = 9; - - const PylithScalar fluidDensity = a[aOff[i_fluidDensity]]; - const PylithScalar fluidViscosity = a[aOff[i_fluidViscosity]]; - const PylithScalar isotropicPermeability = a[aOff[i_isotropicPermeability]]; - const PylithScalar wellboreRadius = a[aOff[i_wellboreRadius]]; - const PylithScalar wellboreLength = a[aOff[i_wellboreLength]]; - const PylithScalar wellboreCharacter = a[aOff[i_wellboreCharacter]]; - const PylithScalar* elementDimensions = &a[aOff[i_elementDimensions]]; - const PylithScalar r_e_constant = a[aOff[i_r_e_constant]]; - const PylithScalar timeDelay = a[aOff[i_timeDelay]]; - - PylithScalar rt = t - timeDelay; - PylithScalar squarewavelet = (rt >= 0.0) ? 1.0 : 0.0; - - PylithScalar r_e = r_e_constant * ( PetscSqrtReal(PetscSqrtReal(isotropicPermeability / isotropicPermeability) * PetscSqr(elementDimensions[0]) + PetscSqrtReal(isotropicPermeability/isotropicPermeability) * PetscSqr(elementDimensions[1]) ) / - ( PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) + PetscPowReal(isotropicPermeability/isotropicPermeability, 0.25) ) ); - PylithScalar WI = 2.0*PETSC_PI * ( PetscSqrtReal(isotropicPermeability*isotropicPermeability)*wellboreLength / PetscLogReal(r_e / wellboreRadius) ); - - Jf0[0] += WI * wellboreCharacter * (1.0 / fluidViscosity)* squarewavelet; - -} // Jf0pp - - -// End of file diff --git a/libsrc/pylith/fekernels/WellboreSource.hh b/libsrc/pylith/fekernels/WellboreSource.hh deleted file mode 100644 index 197558342c..0000000000 --- a/libsrc/pylith/fekernels/WellboreSource.hh +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- C++ -*- - * - * ---------------------------------------------------------------------- - * - * Brad T. Aagaard, U.S. Geological Survey - * Charles A. Williams, GNS Science - * Matthew G. Knepley, University of Chicago - * - * This code was developed as part of the Computational Infrastructure - * for Geodynamics (http:*geodynamics.org). - * - * Copyright (c) 2010-2015 University of California, Davis - * - * See COPYING for license information. - * - * ---------------------------------------------------------------------- - */ - -/** @file libsrc/fekernels/WellboreSource.hh - * - */ - -#if !defined(pylith_fekernels_WellboreSource_hh) -#define pylith_fekernels_WellboreSource_hh - -// Include directives --------------------------------------------------- -#include "fekernelsfwd.hh" // forward declarations - -#include "pylith/utils/types.hh" - -class pylith::fekernels::WellboreSource { - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - - /** Kernel interface. - * - * @param[in] dim Spatial dimension. - * @param[in] numS Number of registered subfields in solution field. - * @param[in] numA Number of registered subfields in auxiliary field. - * @param[in] sOff Offset of registered subfields in solution field [numS]. - * @param[in] sOff_x Offset of registered subfields in gradient of the solution field [numS]. - * @param[in] s Solution field with all subfields. - * @param[in] s_t Time derivative of solution field. - * @param[in] s_x Gradient of solution field. - * @param[in] aOff Offset of registered subfields in auxiliary field [numA] - * @param[in] aOff_x Offset of registered subfields in gradient of auxiliary field [numA] - * @param[in] a Auxiliary field with all subfields. - * @param[in] a_t Time derivative of auxiliary field. - * @param[in] a_x Gradient of auxiliary field. - * @param[in] t Time for residual evaluation. - * @param[in] x Coordinates of point evaluation. - * @param[in] numConstants Number of registered constants. - * @param[in] constants Array of registered constants. - * @param[out] f0 [dim]. - */ - - /** f0 function for pressure equation **/ - static - void f0p(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar f0[]); - - /** Jf0 function for pressure **/ - static - void Jf0pp(const PylithInt dim, - const PylithInt numS, - const PylithInt numA, - const PylithInt sOff[], - const PylithInt sOff_x[], - const PylithScalar s[], - const PylithScalar s_t[], - const PylithScalar s_x[], - const PylithInt aOff[], - const PylithInt aOff_x[], - const PylithScalar a[], - const PylithScalar a_t[], - const PylithScalar a_x[], - const PylithReal t, - const PylithReal s_tshift, - const PylithScalar x[], - const PylithInt numConstants, - const PylithScalar constants[], - PylithScalar Jf0[]); - -}; // WellboreSource - -#endif /* pylith_fekernels_WellboreSource_hh */ - -/* End of file */ diff --git a/libsrc/pylith/fekernels/fekernelsfwd.hh b/libsrc/pylith/fekernels/fekernelsfwd.hh index 769733c36d..a9bb918e26 100644 --- a/libsrc/pylith/fekernels/fekernelsfwd.hh +++ b/libsrc/pylith/fekernels/fekernelsfwd.hh @@ -57,9 +57,6 @@ namespace pylith { class FaultCohesive; class FaultCohesiveKin; - class SquarePulseSource; - class WellboreSource; - class SquareWavelet; class SquareWaveletPlaneStrain; class SquareWavelet3D; @@ -76,12 +73,6 @@ namespace pylith { class TimeHistoryWaveletPlaneStrain; class TimeHistoryWavelet3D; - class TimeHistorySource; - class TimeHistorySourcePlaneStrain; - class TimeHistorySource; - - class PointForce; - class BoundaryDirections; } // fekernels } // pylith diff --git a/libsrc/pylith/materials/Poroelasticity.cc b/libsrc/pylith/materials/Poroelasticity.cc index 1be241b734..6277a0357b 100644 --- a/libsrc/pylith/materials/Poroelasticity.cc +++ b/libsrc/pylith/materials/Poroelasticity.cc @@ -704,6 +704,7 @@ pylith::materials::Poroelasticity::_setKernelsJacobian(pylith::feassemble::Integ PetscPointJacFn* Jf3vv = NULL; const EquationPart equationPart = pylith::feassemble::Integrator::LHS_LUMPED_INV; + kernels.resize(9); kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); kernels[1] = JacobianKernels("displacement", "pressure", equationPart, Jf0up, Jf1up, Jf2up, Jf3up); kernels[2] = JacobianKernels("displacement", "velocity", equationPart, Jf0uv, Jf1uv, Jf2uv, Jf3uv); diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc deleted file mode 100644 index 3979f010d7..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.cc +++ /dev/null @@ -1,106 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "AuxiliaryFactoryPointForce.hh" // implementation of object methods - -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery - -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* - -#include - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::AuxiliaryFactoryPointForce::AuxiliaryFactoryPointForce(void) { - GenericComponent::setName("auxiliaryfactorypointforce"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::AuxiliaryFactoryPointForce::~AuxiliaryFactoryPointForce(void) {} - - -// ---------------------------------------------------------------------- -// Add fluid density subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryPointForce::addPointForce(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addPointForce(void)"); - - const char *subfieldName = "point_force"; - const char* componentNames[3] = { - "point_force_x", - "point_force_y", - "point_force_z", - }; - const PylithReal pressureScale = _normalizer->getPressureScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = (3 == _spaceDim) ? pylith::topology::Field::VECTOR : pylith::topology::Field::OTHER; - description.numComponents = _spaceDim; - description.componentNames.resize(_spaceDim); - for (int i = 0; i < _spaceDim; ++i) { - description.componentNames[i] = componentNames[i]; - } // for - description.scale = pressureScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addPointForce - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time delay of source time function to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryPointForce::addTimeDelay(void) { // timeDelay - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); - - const char* subfieldName = "time_delay"; - - pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeDelay - - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh b/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh deleted file mode 100644 index 93b3a446f1..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryPointForce.hh +++ /dev/null @@ -1,60 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2017 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/AuxiliaryFactoryPointForce.hh - * - * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. - */ - -#if !defined(pylith_sources_auxiliaryfactorypointforce_hh) -#define pylith_sources_auxiliaryfactorypointforce_hh - -#include "sourcesfwd.hh" // forward declarations -#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField - -class pylith::sources::AuxiliaryFactoryPointForce : public pylith::feassemble::AuxiliaryFactory { - friend class TestAuxiliaryFactoryPointForce; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - AuxiliaryFactoryPointForce(void); - - /// Destructor. - virtual ~AuxiliaryFactoryPointForce(void); - - /// Add point force subfield to auxiliary subfields. - void addPointForce(void); - - /// Add time delay subfield to auxiliary subfields. - void addTimeDelay(void); - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - AuxiliaryFactoryPointForce(const AuxiliaryFactoryPointForce &); ///< Not implemented. - const AuxiliaryFactoryPointForce &operator=(const AuxiliaryFactoryPointForce &); ///< Not implemented - -}; // class AuxiliaryFactoryPointForce - -#endif // pylith_sources_auxiliaryfactorypointforce_hh - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc deleted file mode 100644 index 43f7b78ee0..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.cc +++ /dev/null @@ -1,100 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "AuxiliaryFactorySquarePulseSource.hh" // implementation of object methods - -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery - -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* - -#include - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(void) { - GenericComponent::setName("auxiliaryfactorysquarepulsesource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::AuxiliaryFactorySquarePulseSource::~AuxiliaryFactorySquarePulseSource(void) {} - - -// ---------------------------------------------------------------------- -// Add fluid density subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) { // fluidDensity - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addVolumeFlowRate(void)"); - - const char *subfieldName = "volume_flow_rate"; - const PylithReal lengthScale = _normalizer->getLengthScale(); - const PylithReal timeScale = _normalizer->getTimeScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = lengthScale * lengthScale * lengthScale / timeScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addVolumeFlowRate - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time delay of source time function to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeDelay(void) { // timeDelay - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); - - const char* subfieldName = "time_delay"; - - pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeDelay - - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh b/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh deleted file mode 100644 index 2caa0c7f9d..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactorySquarePulseSource.hh +++ /dev/null @@ -1,60 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2017 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/AuxiliaryFactorySquarePulseSource.hh - * - * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. - */ - -#if !defined(pylith_sources_auxiliaryfactorysquarepulsesource_hh) -#define pylith_sources_auxiliaryfactorysquarepulsesource_hh - -#include "sourcesfwd.hh" // forward declarations -#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField - -class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory { - friend class TestAuxiliaryFactorySquarePulseSource; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - AuxiliaryFactorySquarePulseSource(void); - - /// Destructor. - virtual ~AuxiliaryFactorySquarePulseSource(void); - - /// Add fluid density subfield to auxiliary subfields. - void addVolumeFlowRate(void); - - /// Add time delay subfield to auxiliary subfields. - void addTimeDelay(void); - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - AuxiliaryFactorySquarePulseSource(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented. - const AuxiliaryFactorySquarePulseSource &operator=(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented - -}; // class AuxiliaryFactorySquarePulseSource - -#endif // pylith_sources_auxiliaryfactorysquarepulsesource_hh - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc deleted file mode 100644 index f9ef22974a..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.cc +++ /dev/null @@ -1,421 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "AuxiliaryFactorySquarePulseSource.hh" // implementation of object methods - -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery -#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh - -#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* - -#include - -// --------------------------------------------------------------------------------------------------------------------- -namespace pylith { - namespace sources { - class _AuxiliaryFactorySquarePulseSource { -public: - - ///< Names of field components in XYZ coordinate system. - static const char* componentsXYZ[3]; - - ///< Names of field components in 2-D tangential/normal coordinate system. - static const char* componentsTN[2]; - - ///< Names of field components in 3-D tangential/normal coordinate system. - static const char* componentsTTN[3]; - - static const char* genericComponent; - }; // _AuxiliaryFactorySquarePulseSource - - const char* _AuxiliaryFactorySquarePulseSource::componentsXYZ[3] = { "_x", "_y", "_z" }; - const char* _AuxiliaryFactorySquarePulseSource::componentsTN[2] = { "_tangential", "_normal" }; - const char* _AuxiliaryFactorySquarePulseSource::componentsTTN[3] = { "_tangential_1", "_tangential_2", "_normal" }; - - const char* _AuxiliaryFactorySquarePulseSource::genericComponent = "auxiliaryfactorysquarepulsesource"; - } // sources -} // pylith - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::AuxiliaryFactorySquarePulseSource::AuxiliaryFactorySquarePulseSource(const ReferenceEnum reference) : - _auxComponents(reference) { - GenericComponent::setName("auxiliaryfactorysquarepulsesource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::AuxiliaryFactorySquarePulseSource::~AuxiliaryFactorySquarePulseSource(void) {} - - -// --------------------------------------------------------------------------------------------------------------------- -// Set names of vector components in auxiliary subfield. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::_setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("_setVectorFieldComponentNames(description)"); - - assert(description); - - const char** componentNames = NULL; - if (XYZ == _auxComponents) { - componentNames = _AuxiliaryFactorySquarePulseSource::componentsXYZ; - } else if (TANGENTIAL_NORMAL == _auxComponents) { - if (2 == _spaceDim) { - componentNames = _AuxiliaryFactorySquarePulseSource::componentsTN; - } else if (3 == _spaceDim) { - componentNames = _AuxiliaryFactorySquarePulseSource::componentsTTN; - } // if/else - } // if/else - if (!componentNames) { - PYLITH_JOURNAL_ERROR("Unknown case for auxiliary component reference ("<<_auxComponents<<") and spatial dimension ("<<_spaceDim<<")."); - throw std::logic_error("Unknown case for auxiliary component reference and spatial dimension."); - } // if - - assert(size_t(_spaceDim) == description->numComponents); - for (int i = 0; i < _spaceDim; ++i) { - description->componentNames[i] = description->label + std::string(componentNames[i]); - } // for - - PYLITH_METHOD_END; -} // _setVectorFieldComponentNames - - -// ---------------------------------------------------------------------- -// Add fluid density subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addVolumeFlowRate(void) { // fluidDensity - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addVolumeFlowRate(void)"); - - const char *subfieldName = "volume_flow_rate"; - const PylithReal lengthScale = _normalizer->getLengthScale(); - const PylithReal timeScale = _normalizer->getTimeScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = lengthScale * lengthScale * lengthScale / timeScale; - description.validator = pylith::topology::FieldQuery::validatorPositive; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addVolumeFlowRate - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time delay of source time function to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeDelay(void) { // timeDelay - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); - - const char* subfieldName = "time_delay"; - - pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeDelay - - -// --------------------------------------------------------------------------------------------------------------------- -// Add initial amplitude field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addInitialAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addInitialAmplitude(void)"); - - const char* subfieldName = "initial_amplitude"; - - assert(_defaultDescription); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.validator = NULL; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::initialAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addInitialAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add rate amplitude field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addRateAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addRateAmplitude(void)"); - - const char* subfieldName = "rate_amplitude"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.scale = _defaultDescription->scale / _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::addRateAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addRateAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add rate start time field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addRateStartTime(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addRateStartTime(void)"); - - const char* subfieldName = "rate_start_time"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addRateStartTime - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history amplitude field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryAmplitude(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryAmplitude(void)"); - - const char* subfieldName = "time_history_amplitude"; - - assert(_defaultDescription); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - switch (subfieldDescription.vectorFieldType) { - case pylith::topology::FieldBase::SCALAR: { - const size_t numComponents = 1; - assert(numComponents == subfieldDescription.numComponents); - assert(numComponents == subfieldDescription.componentNames.size()); - subfieldDescription.componentNames[0] = subfieldName; - break; - } // SCALAR - case pylith::topology::FieldBase::VECTOR: { - _setVectorFieldComponentNames(&subfieldDescription); - break; - } // VECTOR - default: - PYLITH_JOURNAL_ERROR("Unknown vector field case."); - throw std::logic_error("Unknown vector field case in AuxiliaryFactorySquarePulseSource::addTimeHistoryAmplitude()."); - } // switch - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeHistoryAmplitude - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history start time field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryStartTime(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryStartTime(void)"); - - const char* subfieldName = "time_history_start_time"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeHistoryStartTime - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time history value field to auxiliary fields. -void -pylith::sources::AuxiliaryFactorySquarePulseSource::addTimeHistoryValue(void) { - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeHistoryValue(void)"); - - const char* subfieldName = "time_history_value"; - - assert(_defaultDescription); - assert(_normalizer); - pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); - subfieldDescription.label = subfieldName; - subfieldDescription.alias = subfieldName; - subfieldDescription.vectorFieldType = pylith::topology::FieldBase::SCALAR; - subfieldDescription.numComponents = 1; - subfieldDescription.componentNames.resize(1); - subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.validator = NULL; - - _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization("time_history_amplitude")); - // No subfield query; populated by integrator or constraint at beginning of time step. - - PYLITH_METHOD_END; -} // addTimeHistoryValue - - -// --------------------------------------------------------------------------------------------------------------------- -void -pylith::sources::AuxiliaryFactorySquarePulseSource::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const PylithReal t, - const PylithReal timeScale, - spatialdata::spatialdb::TimeHistory* const dbTimeHistory) { - PYLITH_METHOD_BEGIN; - pythia::journal::debug_t debug(_AuxiliaryFactorySquarePulseSource::genericComponent); - debug << pythia::journal::at(__HERE__) - << "AuxiliaryFactorySquarePulseSource::updateAuxiliaryField(auxiliaryField="<getLocalSection();assert(auxiliaryFieldSection); - PetscInt pStart = 0, pEnd = 0; - err = PetscSectionGetChart(auxiliaryFieldSection, &pStart, &pEnd);PYLITH_CHECK_ERROR(err); - pylith::topology::VecVisitorMesh auxiliaryFieldVisitor(*auxiliaryField); - PetscScalar* auxiliaryFieldArray = auxiliaryFieldVisitor.localArray();assert(auxiliaryFieldArray); - - // Compute offset of time history subfields in auxiliary field. - const PetscInt i_startTime = auxiliaryField->getSubfieldInfo("time_history_start_time").index; - const PetscInt i_value = auxiliaryField->getSubfieldInfo("time_history_value").index; - - // Loop over all points in section. - for (PetscInt p = pStart; p < pEnd; ++p) { - // Skip points without values in section. - if (!auxiliaryFieldVisitor.sectionDof(p)) {continue;} - - // Get starting time and compute relative time for point. - const PetscInt offStartTime = auxiliaryFieldVisitor.sectionSubfieldOffset(i_startTime, p); - const PylithScalar tStart = auxiliaryFieldArray[offStartTime]; - const PylithScalar tRel = t - tStart; - - // Query time history for value (normalized amplitude). - PylithScalar value = 0.0; - if (tRel >= 0.0) { - PylithScalar tDim = tRel * timeScale; - const int err = dbTimeHistory->query(&value, tDim); - if (err) { - std::ostringstream msg; - msg << "Error querying for time '" << tDim << "' in time history database '" << dbTimeHistory->getDescription() << "'."; - throw std::runtime_error(msg.str()); - } // if - } // if - - // Update value (normalized amplitude) in auxiliary field. - const PetscInt offValue = auxiliaryFieldVisitor.sectionSubfieldOffset(i_value, p); - auxiliaryFieldArray[offValue] = value; - } // for - - PYLITH_METHOD_END; -} // updateAuxiliaryField - - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh b/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh deleted file mode 100644 index 33488295c6..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryTimeHistorySource.hh +++ /dev/null @@ -1,114 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2017 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// -#pragma once - -/** @file libsrc/sources/AuxiliaryFactorySquarePulseSource.hh - * - * @brief C++ helper class for setting up auxiliary subfields for the squarepulse source equation. - */ - -#if !defined(pylith_sources_auxiliaryfactorysquarepulsesource_hh) -#define pylith_sources_auxiliaryfactorysquarepulsesource_hh - -#include "pylith/sources/sourcesfwd.hh" // forward declarations -#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField - -class pylith::sources::AuxiliaryFactorySquarePulseSource : public pylith::feassemble::AuxiliaryFactory { - friend class TestAuxiliaryFactorySquarePulseSource; // unit testing - - // PUBLIC ENUMS //////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - enum ReferenceEnum { - XYZ=0, ///< Coordinate directions (x, y, z). - TANGENTIAL_NORMAL=1, ///< Directions tangential and normal to the boundary (tangential_1, tangential_2, normal). - }; - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - AuxiliaryFactorySquarePulseSource(const ReferenceEnum reference=XYZ); - - /// Destructor. - virtual ~AuxiliaryFactorySquarePulseSource(void); - - /// Add fluid density subfield to auxiliary subfields. - void addVolumeFlowRate(void); - - /// Add time delay subfield to auxiliary subfields. - void addTimeDelay(void); - - /// Add initial amplitude field to auxiliary fields. - void addInitialAmplitude(void); - - /// Add rate amplitude field to auxiliary fields. - void addRateAmplitude(void); - - /// Add rate start time amplitude field to auxiliary fields. - void addRateStartTime(void); - - /// Add time history amplitude field to auxiliary fields. - void addTimeHistoryAmplitude(void); - - /// Add time history start time field to auxiliary fields. - void addTimeHistoryStartTime(void); - - /// Add time history value field to auxiliary fields. - void addTimeHistoryValue(void); - - /** Update auxiliary field for current time. - * - * @param[inout] auxiliaryField Auxiliary field to update. - * @param[in] t Current time. - * @param[in] timeScale Time scale for nondimensionalization. - * @param[in] dbTimeHistory Time history database. - */ - static - void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const PylithReal t, - const PylithReal timeScale, - spatialdata::spatialdb::TimeHistory* const dbTimeHistory); - - // PRIVATE METHODS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - /** Set names of vector field components in auxiliary subfield. - * - * @param[in] description Subfield description. - */ - void _setVectorFieldComponentNames(pylith::topology::FieldBase::Description* description); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - ReferenceEnum _auxComponents; ///< Coordinate system reference for field components. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - AuxiliaryFactorySquarePulseSource(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented. - const AuxiliaryFactorySquarePulseSource &operator=(const AuxiliaryFactorySquarePulseSource &); ///< Not implemented - -}; // class AuxiliaryFactorySquarePulseSource - -#endif // pylith_sources_auxiliaryfactorysquarepulsesource_hh - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc deleted file mode 100644 index e7435278ce..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.cc +++ /dev/null @@ -1,337 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "AuxiliaryFactoryWellboreSource.hh" // implementation of object methods - -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery - -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* - -#include - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::AuxiliaryFactoryWellboreSource::AuxiliaryFactoryWellboreSource(void) { - GenericComponent::setName("auxiliaryfactorywellboresource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::AuxiliaryFactoryWellboreSource::~AuxiliaryFactoryWellboreSource(void) {} - - -// ---------------------------------------------------------------------- -// Add fluid density subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addFluidDensity(void) { // fluidDensity - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addFluidDensity(void)"); - - const char* subfieldName = "fluid_density"; - const PylithReal densityScale = _normalizer->getDensityScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = densityScale; - description.validator = pylith::topology::FieldQuery::validatorPositive; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addFluidDensity - - -// ---------------------------------------------------------------------- -// Add fluid viscosity subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addFluidViscosity(void) { // fluidViscosity - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addFluidViscosity(void)"); - - const char* subfieldName = "fluid_viscosity"; - const PylithReal pressureScale = _normalizer->getPressureScale(); - const PylithReal timeScale = _normalizer->getTimeScale(); - const PylithReal viscosityScale = pressureScale*timeScale; - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = viscosityScale; - description.validator = pylith::topology::FieldQuery::validatorPositive; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; - -} // addFluidViscosity - - -// ---------------------------------------------------------------------------- -// Add isotropic permeability subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addIsotropicPermeability(void) { // isotropicPermeablity - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addIsotropicPermeability(void)"); - - const char* subfieldName = "isotropic_permeability"; - - const PylithReal lengthScale = _normalizer->getLengthScale(); - const PylithReal permeabilityScale = lengthScale*lengthScale; - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = permeabilityScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addIsotropicPermeability - - -// ---------------------------------------------------------------------------- -// Add wellbore radius subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreRadius(void) { // wellboreRadius - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addWellboreRadius(void)"); - - const char* subfieldName = "wellbore_radius"; - - const PylithReal lengthScale = _normalizer->getLengthScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = _normalizer->getLengthScale(); - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addWellboreRadius - - -// ---------------------------------------------------------------------------- -// Add wellbore length subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreLength(void) { // wellboreLength - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addWellboreLength(void)"); - - const char* subfieldName = "wellbore_length"; - - const PylithReal lengthScale = _normalizer->getLengthScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = _normalizer->getLengthScale(); - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addWellboreLength - - -// -------------------------------------------------------------------- -// Add wellbore pressure subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addWellborePressure(void) { // wellborePressure - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addWellborePressure(void)"); - - const char* subfieldName = "wellbore_pressure"; - const PylithReal pressureScale = _normalizer->getPressureScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = pressureScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addWellborePressure - - -// ---------------------------------------------------------------------- -// Add wellbore character subfield to auxiliary fields. -// If zero then borehole does nothing. -// If positive the borehole acts as a sink (production well) for porepressure > borehole pressure, and does nothing -// otherwise. -// If negative the borehole acts as a source (injection well) for porepressure < borehole pressure, and does nothing -// otherwise. -// The flow rate to/from the borehole is multiplied by |character|, so usually character = +/- 1, -// but you can specify other quantities to provide an overall scaling to the flow if you like. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addWellboreCharacter(void) { // wellboreCharacter - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addWellboreCharacter(void)"); - - const char* subfieldName = "wellbore_character"; - const PylithReal noScale = 1; - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = noScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addWellboreCharacter - - -// ---------------------------------------------------------------------- -// Add r_e constant subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addr_e_constant(void) { // r_e constant - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addr_e_constant(void)"); - - const char* subfieldName = "r_e_constant"; - const PylithReal noScale = 1; - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = noScale; - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addWellboreCharacter - - -// ---------------------------------------------------------------------------- -// Add isotropic permeability subfield to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addElementDimensions(void) { // elementLength - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addElementDimensions(void)"); - - const char* subfieldName = "element_dimensions"; - const char* componentNames[3] = { - "element_x", - "element_y", - "element_z" - }; - const int tensorSize = (3 == _spaceDim) ? 3 : (2 == _spaceDim) ? 2 : 1; - const PylithReal lengthScale = _normalizer->getLengthScale(); - - pylith::topology::Field::Description description; - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::OTHER; - description.numComponents = tensorSize; - description.componentNames.resize(tensorSize); - for (int i = 0; i < _spaceDim; ++i) { - description.componentNames[i] = componentNames[i]; - } // for - description.scale = _normalizer->getLengthScale(); - description.validator = NULL; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addElementLength - - -// --------------------------------------------------------------------------------------------------------------------- -// Add time delay of source time function to auxiliary fields. -void -pylith::sources::AuxiliaryFactoryWellboreSource::addTimeDelay(void) { // timeDelay - PYLITH_METHOD_BEGIN; - PYLITH_JOURNAL_DEBUG("addTimeDelay(void)"); - - const char* subfieldName = "time_delay"; - - pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); - description.label = subfieldName; - description.alias = subfieldName; - description.vectorFieldType = pylith::topology::Field::SCALAR; - description.numComponents = 1; - description.componentNames.resize(1); - description.componentNames[0] = subfieldName; - description.scale = timeScale; - description.validator = pylith::topology::FieldQuery::validatorNonnegative; - - _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); - this->setSubfieldQuery(subfieldName); - - PYLITH_METHOD_END; -} // addTimeDelay - - -// End of file diff --git a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh b/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh deleted file mode 100644 index 2250a291e6..0000000000 --- a/libsrc/pylith/sources/AuxiliaryFactoryWellboreSource.hh +++ /dev/null @@ -1,84 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2017 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/AuxiliaryFactoryWellboreSource.hh - * - * @brief C++ helper class for setting up auxiliary subfields for the wellbore source equation. - */ - -#if !defined(pylith_sources_auxiliaryfactorywellboresource_hh) -#define pylith_sources_auxiliaryfactorywellboresource_hh - -#include "sourcesfwd.hh" // forward declarations -#include "pylith/feassemble/AuxiliaryFactory.hh" // ISA AuxiliaryFactory - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // USES GravityField - -class pylith::sources::AuxiliaryFactoryWellboreSource : public pylith::feassemble::AuxiliaryFactory { - friend class TestAuxiliaryFactoryWellboreSource; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - AuxiliaryFactoryWellboreSource(void); - - /// Destructor. - virtual ~AuxiliaryFactoryWellboreSource(void); - - /// Add fluid density subfield to auxiliary subfields. - void addFluidDensity(void); - - /// Add fluid viscosity subfield to auxiliary subfields. - void addFluidViscosity(void); - - /// Add isotropic permeability subfield to auxiliary subfields. - void addIsotropicPermeability(void); - - /// Add wellbore radius subfield to auxiliary subfields. - void addWellboreRadius(void); - - /// Add wellbore length subfield to auxiliary subfields. - void addWellboreLength(void); - - /// Add wellbore pressure subfield to auxiliary subfields. - void addWellborePressure(void); - - /// Add wellbore character subfield to auxiliary subfields. - void addWellboreCharacter(void); - - /// Add r_e constant character subfield to auxiliary subfields. - void addr_e_constant(void); - - /// Add element dimensions subfield to auxiliary subfields. - void addElementDimensions(void); - - /// Add time delay subfield to auxiliary subfields. - void addTimeDelay(void); - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - AuxiliaryFactoryWellboreSource(const AuxiliaryFactoryWellboreSource &); ///< Not implemented. - const AuxiliaryFactoryWellboreSource& operator=(const AuxiliaryFactoryWellboreSource&); ///< Not implemented - -}; // class AuxiliaryFactoryWellboreSource - -#endif // pylith_sources_auxiliaryfactorywellboresource_hh - -// End of file diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index 549c8a7b76..b8f87e7059 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -22,21 +22,14 @@ include $(top_srcdir)/subpackage.am subpkginclude_HEADERS = \ Source.hh \ MomentTensorForce.hh \ - WellboreSource.hh \ - SquarePulseSource.hh \ AuxiliaryFactorySquarePulseSource.hh \ AuxiliaryFactoryMomentTensorForce.hh \ - AuxiliaryFactoryWellboreSource.hh \ AuxiliaryFactorySourceTime.hh \ - AuxiliaryFactoryTimeHistorySource.hh \ DerivedFactoryMomentTensorForce.hh \ SquareWavelet.hh \ RickerWavelet.hh \ GaussianWavelet.hh \ TimeHistoryWavelet.hh \ - TimeHistorySource.hh \ - PointForce.hh \ - AuxiliaryFactoryPointForce.hh \ SourceTimeFunctionMomentTensorForce.hh \ sourcesfwd.hh diff --git a/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc b/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc deleted file mode 100644 index 96b301beda..0000000000 --- a/libsrc/pylith/sources/MomentTensorForceTimeHistory.cc +++ /dev/null @@ -1,298 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "pylith/sources/MomentTensorForce.hh" // implementation of object methods - -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime -#include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" // HASA SourceTimeFunctionMomentTensorSource -#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce -#include "pylith/sources/DerivedFactoryMomentTensorForce.hh" // USES DerivedFactoryMomentTensorForce -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps -#include "pylith/fekernels/DispVel.hh" // USES DispVel kernels -#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; -typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; -typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; -typedef pylith::feassemble::Integrator::EquationPart EquationPart; - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::MomentTensorForce::MomentTensorForce(void) : - _sourceTimeFunction(NULL), - _derivedFactory(new pylith::sources::DerivedFactoryMomentTensorForce) { - pylith::utils::PyreComponent::setName("momenttensorforce"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::MomentTensorForce::~MomentTensorForce(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::MomentTensorForce::deallocate(void) { - Source::deallocate(); - - delete _derivedFactory;_derivedFactory = NULL; - _sourceTimeFunction = NULL; -} // deallocate - - -// --------------------------------------------------------------------------------------------------------------------- -// Set source time function. -void -pylith::sources::MomentTensorForce::setSourceTimeFunction(pylith::sources::SourceTimeFunctionMomentTensorForce* const sourceTimeFunction) { - _sourceTimeFunction = sourceTimeFunction; -} // setSourceTimeFunction - - -// --------------------------------------------------------------------------------------------------------------------- -// Get bulk source time function. -pylith::sources::SourceTimeFunctionMomentTensorForce* -pylith::sources::MomentTensorForce::getSourceTimeFunction(void) const { - return _sourceTimeFunction; -} // getSourceTimeFunction - - -// --------------------------------------------------------------------------------------------------------------------- -// Verify configuration is acceptable. -void -pylith::sources::MomentTensorForce::verifyConfiguration(const pylith::topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution="<setLabelName(getLabelName()); - integrator->setLabelValue(getLabelValue()); - - _setKernelsResidual(integrator, solution); - - _setKernelsUpdateStateVars(integrator, solution); - _setKernelsDerivedField(integrator, solution); - - PYLITH_METHOD_RETURN(integrator); -} // createIntegrator - - -// --------------------------------------------------------------------------------------------------------------------- -// Create auxiliary field. -pylith::topology::Field* -pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution="<setLabel("MomentTensorForce auxiliary field"); - - assert(_sourceTimeFunction); - pylith::sources::AuxiliaryFactoryMomentTensorForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); - - assert(_normalizer); - auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); - - // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - - auxiliaryFactory->addMomentTensor(); // 0 - - _sourceTimeFunction->addAuxiliarySubfields(); - - auxiliaryField->subfieldsSetup(); - auxiliaryField->createDiscretization(); - pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); - auxiliaryField->allocate(); - auxiliaryField->createOutputVector(); - - assert(auxiliaryFactory); - auxiliaryFactory->setValuesFromDB(); - - // Debug option - auxiliaryField->view("MomentTensor auxiliary field."); - - PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField - - -// --------------------------------------------------------------------------------------------------------------------- -// Update auxiliary subfields at beginning of time step. -void -pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, - const double t) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField="<getTimeScale(); - - _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale); - - // if (_useTimeHistory) { - // assert(_normalizer); - // const PylithScalar timeScale = _normalizer->getTimeScale(); - // AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); - // } // if - - PYLITH_METHOD_END; -} // updateAuxiliaryField - - -// --------------------------------------------------------------------------------------------------------------------- -// Create derived field. -pylith::topology::Field* -pylith::sources::MomentTensorForce::createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution="<getAuxiliaryFactory(); -} // _getAuxiliaryFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Update kernel constants. -void -pylith::sources::MomentTensorForce::_updateKernelConstants(const PylithReal dt) { - assert(_sourceTimeFunction); - _sourceTimeFunction->updateKernelConstants(&_kernelConstants, dt); -} // _updateKernelConstants - - -// --------------------------------------------------------------------------------------------------------------------- -// Get derived factory associated with physics. -pylith::topology::FieldFactory* -pylith::sources::MomentTensorForce::_getDerivedFactory(void) { - return _derivedFactory; -} // _getDerivedFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for RHS residual G(t,s). -void -pylith::sources::MomentTensorForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator="< kernels(1); - switch (_formulation) { - case QUASISTATIC: { - break; - } // QUASISTATIC - case DYNAMIC_IMEX: - case DYNAMIC: { - // Velocity - const PetscPointFunc g0v = NULL; - const PetscPointFunc g1v = _sourceTimeFunction->getKernelg1v_explicit(coordsys); - kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::RHS, g0v, g1v); - // kernels[0] = ResidualKernels("velocity", pylith::feassemble::Integrator::RHS, g0v, g1v); - break; - } // DYNAMIC - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsResidual(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsResidual - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for computing updated state variables in auxiliary field. -void -pylith::sources::MomentTensorForce::_setKernelsUpdateStateVars(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsUpdateStateVars(integrator="< kernels; - _sourceTimeFunction->addKernelsUpdateStateVars(&kernels, coordsys); - - integrator->setKernelsUpdateStateVars(kernels); - - PYLITH_METHOD_END; -} // _setKernelsUpdateStateVars - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for computing derived field. -void -pylith::sources::MomentTensorForce::_setKernelsDerivedField(pylith::feassemble::IntegratorDomain* integrator, - const topology::Field& solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsDerivedField(integrator="< - -#include "pylith/sources/PointForce.hh" // implementation of object methods - -#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // USES AuxiliaryFactoryPointForce -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps - -#include "pylith/fekernels/PointForce.hh" // USES PointForce kernels - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; -typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; -typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; -typedef pylith::feassemble::Integrator::EquationPart EquationPart; - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::PointForce::PointForce(void) : - _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryPointForce) { - pylith::utils::PyreComponent::setName("pointforce"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::PointForce::~PointForce(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::PointForce::deallocate(void) { - Source::deallocate(); - - delete _auxiliaryFactory; - _auxiliaryFactory = NULL; -} // deallocate - - -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::PointForce::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); - - _dbTimeHistory = th; -} // setTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Get time history database. -const spatialdata::spatialdb::TimeHistory * -pylith::sources::PointForce::getTimeHistoryDB(void) { - return _dbTimeHistory; -} // getTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Use time history term in time history expression. -void -pylith::sources::PointForce::useTimeHistory(const bool value) { - PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); - - _useTimeHistory = value; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Get flag associated with using time history term in time history expression. -bool -pylith::sources::PointForce::useTimeHistory(void) const { - return _useTimeHistory; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Verify configuration is acceptable. -void -pylith::sources::PointForce::verifyConfiguration(const pylith::topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); - - // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) { - throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'PointForce'."); - } // if - - PYLITH_METHOD_END; -} // verifyConfiguration - - -// --------------------------------------------------------------------------------------------------------------------- -// Create integrator and set kernels. -pylith::feassemble::Integrator * -pylith::sources::PointForce::createIntegrator(const pylith::topology::Field &solution) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - - pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); - - pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); - assert(integrator); - integrator->setLabelName(getLabelName()); - integrator->setLabelValue(getLabelValue()); - - _setKernelsResidual(integrator, solution); - _setKernelsJacobian(integrator, solution); - - PYLITH_METHOD_RETURN(integrator); -} // createIntegrator - - -// --------------------------------------------------------------------------------------------------------------------- -// Create auxiliary field. -pylith::topology::Field* -pylith::sources::PointForce::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); - - pylith::topology::Field* auxiliaryField = new pylith::topology::Field(domainMesh); - assert(auxiliaryField); - auxiliaryField->setLabel("PointForce auxiliary field"); - - assert(_normalizer); - _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); - - // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - - // :ATTENTION: In quasi-static problems, the time scale is usually quite large - // (order of tens to hundreds of years), which means that the density scale is very large, - // and the acceleration scale is very small. Nevertheless, density times gravitational - // acceleration will have a scale of pressure divided by length and should be within a few orders - // of magnitude of 1. - - _auxiliaryFactory->addPointForce(); // 0 - _auxiliaryFactory->addTimeDelay(); // 1 - - assert(_auxiliaryFactory); - _auxiliaryFactory->setValuesFromDB(); - - // Debug option - auxiliaryField->view("PointForce auxiliary field."); - - PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField - - -// --------------------------------------------------------------------------------------------------------------------- -// Create derived field. -pylith::topology::Field * -pylith::sources::PointForce::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); - - PYLITH_METHOD_RETURN(NULL); -} // createDerivedField - - -// --------------------------------------------------------------------------------------------------------------------- -// Get auxiliary factory associated with physics. -pylith::feassemble::AuxiliaryFactory * -pylith::sources::PointForce::_getAuxiliaryFactory(void) { - return _auxiliaryFactory; -} // _getAuxiliaryFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS residual F(t,s,\dot{s}). -void -pylith::sources::PointForce::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - // Displacement - const PetscPointFunc f0u = pylith::fekernels::PointForce::f0u; - const PetscPointFunc f1u = NULL; - - kernels.resize(1); - kernels[0] = ResidualKernels("displacement", pylith::feassemble::Integrator::LHS, f0u, f1u); - break; - } // QUASISTATIC - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC - case DYNAMIC: - { - break; - } // DYNAMIC - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsResidual(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsResidual - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS Jacobian F(t,s,\dot{s}). -void -pylith::sources::PointForce::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - const PetscPointJac Jf0uu = NULL; - const PetscPointJac Jf1uu = NULL; - const PetscPointJac Jf2uu = NULL; - const PetscPointJac Jf3uu = NULL; - - kernels.resize(1); - const EquationPart equationPart = pylith::feassemble::Integrator::LHS; - kernels[0] = JacobianKernels("displacement", "displacement", equationPart, Jf0uu, Jf1uu, Jf2uu, Jf3uu); - break; - } // QUASISTATIC - case DYNAMIC: - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC_IMEX - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsJacobian(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsJacobian - - -// End of file diff --git a/libsrc/pylith/sources/PointForce.hh b/libsrc/pylith/sources/PointForce.hh deleted file mode 100644 index c9eaa614e7..0000000000 --- a/libsrc/pylith/sources/PointForce.hh +++ /dev/null @@ -1,152 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/PointForce.hh - * - * @brief C++ class for solving pointforce equation. - */ - -#if !defined(pylith_sources_pointforce_hh) -#define pylith_sources_pointforce_hh - -#include "sourcesfwd.hh" // forward declarations - -#include "pylith/sources/Source.hh" // ISA Source - -class pylith::sources::PointForce : public pylith::sources::Source { - friend class TestPointForce; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - PointForce(void); - - /// Destructor. - ~PointForce(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field &solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - /** Set kernels for residual. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - /** Set kernels for Jacobian. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. - pylith::sources::AuxiliaryFactoryPointForce *_auxiliaryFactory; ///< Factory for auxiliary subfields. - - bool _useTimeHistory; ///< Use time history term. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - PointForce(const PointForce &); ///< Not implemented. - const PointForce &operator=(const PointForce &); /// Not implemented. - -}; - -// class PointForce - -#endif // pylith_sources_pointforce_hh - -// End of file diff --git a/libsrc/pylith/sources/TimeHistorySource.cc b/libsrc/pylith/sources/TimeHistorySource.cc deleted file mode 100644 index 3a818572c6..0000000000 --- a/libsrc/pylith/sources/TimeHistorySource.cc +++ /dev/null @@ -1,417 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include -#include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "pylith/sources/TimeHistorySource.hh" // implementation of object methods - -#include "pylith/sources/AuxiliaryFactoryTimeHistorySource.hh" // USES AuxiliaryFactoryTimeHistorySource -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps - -#include "pylith/fekernels/TimeHistorySource.hh" // USES TimeHistorySource kernels - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; -typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; -typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; -typedef pylith::feassemble::Integrator::EquationPart EquationPart; - -// --------------------------------------------------------------------------------------------------------------------- -namespace pylith { - namespace sources { - class _TimeHistorySource { - // PUBLIC MEMBERS ////////////////////////////////////////////////////////////////////////////////////////// -public: - - /** Set kernels for RHS residual. - * - * @param[out] integrator Integrator for source condition. - * @param[in] sources Square Pulse time-dependent source condition. - * @param[in] solution Solution field. - * @param[in] formulation Formulation for equations. - */ - static - void setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const pylith::sources::TimeHistorySource& sources, - const pylith::topology::Field& solution, - const pylith::problems::Physics::FormulationEnum formulation); - - static const char* pyreComponent; - - }; // _TimeHistorySource - const char* _TimeHistorySource::pyreComponent = "timehistorysource"; - - } // sources -} // pylith - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::TimeHistorySource::TimeHistorySource(void) : - _dbTimeHistory(NULL), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryTimeHistorySource(pylith::sources::AuxiliaryFactoryTimeHistorySource::XYZ)), - _useInitial(true), - _useRate(false), - _useTimeHistory(false) { - PyreComponent::setName(_TimeHistorySource::pyreComponent); - - pylith::utils::PyreComponent::setName("timehistorysource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::TimeHistorySource::~TimeHistorySource(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::TimeHistorySource::deallocate(void) { - Source::deallocate(); - - delete _auxiliaryFactory; - _auxiliaryFactory = NULL; -} // deallocate - - -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::TimeHistorySource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); - - _dbTimeHistory = th; -} // setTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Get time history database. -const spatialdata::spatialdb::TimeHistory * -pylith::sources::TimeHistorySource::getTimeHistoryDB(void) { - return _dbTimeHistory; -} // getTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Use time history term in time history expression. -void -pylith::sources::TimeHistorySource::useTimeHistory(const bool value) { - PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); - - _useTimeHistory = value; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Get flag associated with using time history term in time history expression. -bool -pylith::sources::TimeHistorySource::useTimeHistory(void) const { - return _useTimeHistory; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Verify configuration is acceptable. -void -pylith::sources::TimeHistorySource::verifyConfiguration(const pylith::topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); - - // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) { - throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'TimeHistorySource'."); - } // if - - PYLITH_METHOD_END; -} // verifyConfiguration - - -// --------------------------------------------------------------------------------------------------------------------- -// Create integrator and set kernels. -pylith::feassemble::Integrator * -pylith::sources::TimeHistorySource::createIntegrator(const pylith::topology::Field &solution) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - - pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); - - pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); - assert(integrator); - integrator->setLabelName(getLabelName()); - integrator->setLabelValue(getLabelValue()); - // printf("In TimeHistorySource end\n"); - // DMView(dmSoln, NULL); - - _setKernelsResidual(integrator, solution); - _setKernelsJacobian(integrator, solution); - - PYLITH_METHOD_RETURN(integrator); -} // createIntegrator - - -// --------------------------------------------------------------------------------------------------------------------- -// Create auxiliary field. -pylith::topology::Field * -pylith::sources::TimeHistorySource::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); - - pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); - assert(auxiliaryField); - auxiliaryField->setLabel("TimeHistorySource auxiliary field"); - - assert(_normalizer); - _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); - - // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - - // :ATTENTION: In quasi-static problems, the time scale is usually quite large - // (order of tens to hundreds of years), which means that the density scale is very large, - // and the acceleration scale is very small. Nevertheless, density times gravitational - // acceleration will have a scale of pressure divided by length and should be within a few orders - // of magnitude of 1. - - // add in aux specific to square pulse - _auxiliaryFactory->addVolumeFlowRate(); // 0 - - _auxiliaryFactory->addTimeHistoryStartTime(); - _auxiliaryFactory->addTimeHistoryValue(); - - if (_dbTimeHistory) { - _dbTimeHistory->open(); - } // if - -} // _useTimeHistory - - -assert(_auxiliaryFactory); -_auxiliaryFactory->setValuesFromDB(); - -// Debug option -auxiliaryField->view("SquarePulse auxiliary field."); - -PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField - -// --------------------------------------------------------------------------------------------------------------------- -// Create derived field. -pylith::topology::Field * -pylith::sources::TimeHistorySource::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); - - PYLITH_METHOD_RETURN(NULL); -} // createDerivedField - - -// --------------------------------------------------------------------------------------------------------------------- -// Get auxiliary factory associated with physics. -pylith::feassemble::AuxiliaryFactory * -pylith::sources::TimeHistorySource::_getAuxiliaryFactory(void) { - return _auxiliaryFactory; -} // _getAuxiliaryFactory - - -// // -// --------------------------------------------------------------------------------------------------------------------- -// // Set kernels for LHS residual F(t,s,\dot{s}). -// void -// pylith::sources::TimeHistorySource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, -// const topology::Field &solution) const { -// PYLITH_METHOD_BEGIN; -// PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << -// ")"); - -// const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - -// std::vector kernels; - -// switch (_formulation) { -// case QUASISTATIC: -// { -// // Pressure -// const PetscPointFunc f0p = pylith::fekernels::TimeHistorySource::f0p; -// const PetscPointFunc f1p = NULL; - -// kernels.resize(1); -// kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::LHS, f0p, f1p); -// break; -// } // QUASISTATIC -// case DYNAMIC_IMEX: -// { -// break; -// } // DYNAMIC -// case DYNAMIC: -// { -// break; -// } // DYNAMIC -// default: -// PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); -// } // switch - -// assert(integrator); -// integrator->setKernelsResidual(kernels, solution); - -// PYLITH_METHOD_END; -// } // _setKernelsResidual - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for residual. -void -pylith::sources::_TimeHistorySource::setKernelsResidual(pylith::feassemble::IntegratorDomain* integrator, - const pylith::sources::TimeHistorySource& sources, - const topology::Field& solution, - const pylith::problems::Physics::FormulationEnum formulation) { - PYLITH_METHOD_BEGIN; - pythia::journal::debug_t debug(_TimeHistorySource::pyreComponent); - debug << pythia::journal::at(__HERE__) - << "setKernelsResidual(integrator="< kernels(1); - switch (formulation) { - case pylith::problems::Physics::QUASISTATIC: - kernels[0] = ResidualKernels(sources.getSubfieldName(), pylith::feassemble::Integrator::LHS, r0, r1); - break; - case pylith::problems::Physics::DYNAMIC_IMEX: - case pylith::problems::Physics::DYNAMIC: - kernels[0] = ResidualKernels(sources.getSubfieldName(), pylith::feassemble::Integrator::RHS, r0, r1); - break; - default: { - PYLITH_JOURNAL_LOGICERROR("Unknown formulation for equations ("<setKernelsResidual(kernels, solution); - - PYLITH_METHOD_END; -} // setKernelsResidual - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS Jacobian F(t,s,\dot{s}). -void -pylith::sources::TimeHistorySource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - const PetscPointJac Jf0pp = NULL; - const PetscPointJac Jf1pp = NULL; - const PetscPointJac Jf2pp = NULL; - const PetscPointJac Jf3pp = NULL; - - kernels.resize(1); - const EquationPart equationPart = pylith::feassemble::Integrator::LHS; - kernels[0] = JacobianKernels(getSubfieldName(), getSubfieldName(), equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); - break; - } // QUASISTATIC - case DYNAMIC: - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC_IMEX - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsJacobian(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsJacobian - - -// End of file diff --git a/libsrc/pylith/sources/TimeHistorySource.hh b/libsrc/pylith/sources/TimeHistorySource.hh deleted file mode 100644 index 8e7e0487d5..0000000000 --- a/libsrc/pylith/sources/TimeHistorySource.hh +++ /dev/null @@ -1,156 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/TimeHistorySource.hh - * - * @brief C++ class for solving timehistorysource equation. - */ - -#if !defined(pylith_sources_timehistorysource_hh) -#define pylith_sources_timehistorysource_hh - -#include "sourcesfwd.hh" // forward declarations - -#include "pylith/sources/Source.hh" // ISA Source - -class pylith::sources::TimeHistorySource : public pylith::sources::Source { - friend class TestTimeHistorySource; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - TimeHistorySource(void); - - /// Destructor. - ~TimeHistorySource(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field &solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - /** Set kernels for residual. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - /** Set kernels for Jacobian. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - bool _useInertia; ///< Flag to include inertial term. - spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. - pylith::sources::AuxiliaryFactoryTimeHistorySource *_auxiliaryFactory; ///< Factory for auxiliary subfields. - std::string _scaleName; ///< Name of scale associated with Neumann boundary condition. - - bool _useInitial; ///< Use initial value term. - bool _useRate; ///< Use rate term. - bool _useTimeHistory; ///< Use time history term. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - TimeHistorySource(const TimeHistorySource &); ///< Not implemented. - const TimeHistorySource &operator=(const TimeHistorySource &); /// Not implemented. - -}; - -// class TimeHistorySource - -#endif // pylith_sources_timehistorysource_hh - -// End of file diff --git a/libsrc/pylith/sources/WellboreSource.cc b/libsrc/pylith/sources/WellboreSource.cc deleted file mode 100644 index d73e2da317..0000000000 --- a/libsrc/pylith/sources/WellboreSource.cc +++ /dev/null @@ -1,300 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "pylith/sources/WellboreSource.hh" // implementation of object methods - -#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // USES AuxiliaryFactoryWellboreSource -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps - -#include "pylith/fekernels/WellboreSource.hh" // USES WellboreSource kernels - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; -typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; -typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; -typedef pylith::feassemble::Integrator::EquationPart EquationPart; - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::WellboreSource::WellboreSource(void) : _useInertia(false), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactoryWellboreSource) { - pylith::utils::PyreComponent::setName("wellboresource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::WellboreSource::~WellboreSource(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::WellboreSource::deallocate(void) { - Source::deallocate(); - - delete _auxiliaryFactory; - _auxiliaryFactory = NULL; -} // deallocate - - -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::WellboreSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); - - _dbTimeHistory = th; -} // setTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Get time history database. -const spatialdata::spatialdb::TimeHistory * -pylith::sources::WellboreSource::getTimeHistoryDB(void) { - return _dbTimeHistory; -} // getTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Use time history term in time history expression. -void -pylith::sources::WellboreSource::useTimeHistory(const bool value) { - PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); - - _useTimeHistory = value; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Get flag associated with using time history term in time history expression. -bool -pylith::sources::WellboreSource::useTimeHistory(void) const { - return _useTimeHistory; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Verify configuration is acceptable. -void -pylith::sources::WellboreSource::verifyConfiguration(const pylith::topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); - - // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) { - throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'WellboreSource'."); - } // if - - PYLITH_METHOD_END; -} // verifyConfiguration - - -// --------------------------------------------------------------------------------------------------------------------- -// Create integrator and set kernels. -pylith::feassemble::Integrator * -pylith::sources::WellboreSource::createIntegrator(const pylith::topology::Field &solution) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - - pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); - - pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); - assert(integrator); - integrator->setLabelName(getLabelName()); - integrator->setLabelValue(getLabelValue()); - // printf("In WellboreSource end\n"); - // DMView(dmSoln, NULL); - - _setKernelsResidual(integrator, solution); - _setKernelsJacobian(integrator, solution); - - PYLITH_METHOD_RETURN(integrator); -} // createIntegrator - - -// --------------------------------------------------------------------------------------------------------------------- -// Create auxiliary field. -pylith::topology::Field * -pylith::sources::WellboreSource::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); - - pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); - assert(auxiliaryField); - auxiliaryField->setLabel("WellboreSource auxiliary field"); - - assert(_normalizer); - _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); - - // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - - // :ATTENTION: In quasi-static problems, the time scale is usually quite large - // (order of tens to hundreds of years), which means that the density scale is very large, - // and the acceleration scale is very small. Nevertheless, density times gravitational - // acceleration will have a scale of pressure divided by length and should be within a few orders - // of magnitude of 1. - - // add in aux specific to peaceman - _auxiliaryFactory->addFluidDensity(); // 0 - _auxiliaryFactory->addFluidViscosity(); // 1 - _auxiliaryFactory->addIsotropicPermeability(); // 2 - _auxiliaryFactory->addWellboreRadius(); // 3 - _auxiliaryFactory->addWellboreLength(); // 4 - _auxiliaryFactory->addWellborePressure(); // 5 - _auxiliaryFactory->addWellboreCharacter(); // 6 - _auxiliaryFactory->addElementDimensions(); // 7 - _auxiliaryFactory->addr_e_constant(); // 8 - _auxiliaryFactory->addTimeDelay(); // 9 - - auxiliaryField->subfieldsSetup(); - auxiliaryField->createDiscretization(); - pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); - auxiliaryField->allocate(); - auxiliaryField->createOutputVector(); - - assert(_auxiliaryFactory); - _auxiliaryFactory->setValuesFromDB(); - - // Debug option - auxiliaryField->view("Wellbore auxiliary field."); - - PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField - - -// --------------------------------------------------------------------------------------------------------------------- -// Create derived field. -pylith::topology::Field * -pylith::sources::WellboreSource::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); - - PYLITH_METHOD_RETURN(NULL); -} // createDerivedField - - -// --------------------------------------------------------------------------------------------------------------------- -// Get auxiliary factory associated with physics. -pylith::feassemble::AuxiliaryFactory * -pylith::sources::WellboreSource::_getAuxiliaryFactory(void) { - return _auxiliaryFactory; -} // _getAuxiliaryFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS residual F(t,s,\dot{s}). -void -pylith::sources::WellboreSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - // Pressure - const PetscPointFunc f0p = pylith::fekernels::WellboreSource::f0p; - const PetscPointFunc f1p = NULL; - - kernels.resize(1); - kernels[0] = ResidualKernels("pressure", pylith::feassemble::Integrator::LHS, f0p, f1p); - break; - } // QUASISTATIC - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC - case DYNAMIC: - { - break; - } // DYNAMIC - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsResidual(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsResidual - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS Jacobian F(t,s,\dot{s}). -void -pylith::sources::WellboreSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - const PetscPointJac Jf0pp = pylith::fekernels::WellboreSource::Jf0pp; - const PetscPointJac Jf1pp = NULL; - const PetscPointJac Jf2pp = NULL; - const PetscPointJac Jf3pp = NULL; - - kernels.resize(1); - const EquationPart equationPart = pylith::feassemble::Integrator::LHS; - kernels[0] = JacobianKernels("pressure", "pressure", equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); - break; - } // QUASISTATIC - case DYNAMIC: - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC_IMEX - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsJacobian(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsJacobian - - -// End of file diff --git a/libsrc/pylith/sources/WellboreSource.hh b/libsrc/pylith/sources/WellboreSource.hh deleted file mode 100644 index 5fcbc5a96f..0000000000 --- a/libsrc/pylith/sources/WellboreSource.hh +++ /dev/null @@ -1,148 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/WellboreSource.hh - * - * @brief C++ class for solving wellboresource equation. - */ - -#if !defined(pylith_sources_wellboresource_hh) -#define pylith_sources_wellboresource_hh - -#include "sourcesfwd.hh" // forward declarations - -#include "pylith/sources/Source.hh" // ISA Source - -class pylith::sources::WellboreSource : public pylith::sources::Source -{ - friend class TestWellboreSource; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - /// Default constructor. - WellboreSource(void); - - /// Destructor. - ~WellboreSource(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field &solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// -protected: - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - /** Set kernels for residual. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - /** Set kernels for Jacobian. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - bool _useInertia; ///< Flag to include inertial term. - spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. - pylith::sources::AuxiliaryFactoryWellboreSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. - - bool _useTimeHistory; ///< Use time history term. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - WellboreSource(const WellboreSource &); ///< Not implemented. - const WellboreSource &operator=(const WellboreSource &); /// Not implemented. -}; - -// class WellboreSource - -#endif // pylith_sources_wellboresource_hh - -// End of file diff --git a/libsrc/pylith/sources/sourcesfwd.hh b/libsrc/pylith/sources/sourcesfwd.hh index 6eccf38347..dacb8814c1 100644 --- a/libsrc/pylith/sources/sourcesfwd.hh +++ b/libsrc/pylith/sources/sourcesfwd.hh @@ -43,18 +43,6 @@ namespace pylith { class GaussianWavelet; class TimeHistoryWavelet; - class PointForce; - class AuxiliaryFactoryPointForce; - - class SquarePulseSource; - class AuxiliaryFactorySquarePulseSource; - - class TimeHistorySource; - class AuxiliaryFactoryTimeHistorySource; - - class WellboreSource; - class AuxiliaryFactoryWellboreSource; - } // sources } // pylith diff --git a/modulesrc/sources/Makefile.am b/modulesrc/sources/Makefile.am index bdfbddea20..aed37dcc8f 100644 --- a/modulesrc/sources/Makefile.am +++ b/modulesrc/sources/Makefile.am @@ -28,9 +28,6 @@ swig_sources = \ sources.i \ ../problems/Physics.i \ Source.i \ - WellboreSource.i \ - SquarePulseSource.i \ - PointForce.i \ MomentTensorForce.i \ SourceTimeFunctionMomentTensorForce.i \ RickerWavelet.i \ diff --git a/modulesrc/sources/PointForce.i b/modulesrc/sources/PointForce.i deleted file mode 100644 index 19bb15fe16..0000000000 --- a/modulesrc/sources/PointForce.i +++ /dev/null @@ -1,117 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2016 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file modulesrc/sources/PointForce.i - * - * Python interface to C++ PointForce. - */ - -namespace pylith { - namespace sources { - class PointForce : public pylith::sources::Source { - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - PointForce(void); - - /// Destructor. - ~PointForce(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field& solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); - - /** Update kernel constants. - * - * @param[in] dt Current time step. - */ - void _updateKernelConstants(const PylithReal dt); - - }; // class PointForce - - } // sources -} // pylith - -// End of file \ No newline at end of file diff --git a/modulesrc/sources/SourceTimeFunctionPointForce.i b/modulesrc/sources/SourceTimeFunctionPointForce.i deleted file mode 100644 index 6fe8e1f56e..0000000000 --- a/modulesrc/sources/SourceTimeFunctionPointForce.i +++ /dev/null @@ -1,84 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2021 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file modulesrc/sources/SourceTimeFunctionPointForce.i - * - * Python interface to C++ abstract base class SourceTimeFunctionPointForce. - */ - -namespace pylith { - namespace sources { - class SourceTimeFunctionPointForce : public pylith::utils::PyreComponent { - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - SourceTimeFunctionPointForce(void); - - /// Destructor. - virtual ~SourceTimeFunctionPointForce(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - virtual - pylith::sources::AuxiliaryFactoryPointForce* getAuxiliaryFactory(void) = 0; - - /// Add sourcetimefunction subfields to auxiliary field. - virtual - void addAuxiliarySubfields(void) = 0; - - /** Get g1v kernel for residual, G(t,s). - * - * @param[in] coordsys Coordinate system. - * - * @return RHS residual kernel for stress. - */ - virtual - PetscPointFunc getKernelg1v_explicit(const spatialdata::geocoords::CoordSys* coordsys) const = 0; - - /** Add kernels for updating state variables. - * - * @param[inout] kernels Array of kernels for updating state variables. - * @param[in] coordsys Coordinate system. - */ - virtual - void addKernelsUpdateStateVars(std::vector* kernels, - const spatialdata::geocoords::CoordSys* coordsys) const; - - /** Update kernel constants. - * - * @param[inout] kernelConstants Array of constants used in integration kernels. - * @param[in] dt Current time step. - */ - virtual - void updateKernelConstants(pylith::real_array* kernelConstants, - const PylithReal dt) const; - - }; - - // class SourceTimeFunctionPointForce - - } // sources -} // pylith - -// End of file \ No newline at end of file diff --git a/modulesrc/sources/SquarePulseSource.i b/modulesrc/sources/SquarePulseSource.i deleted file mode 100644 index 15d0239390..0000000000 --- a/modulesrc/sources/SquarePulseSource.i +++ /dev/null @@ -1,117 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2016 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file modulesrc/sources/SquarePulseSource.i - * - * Python interface to C++ SquarePulseSource. - */ - -namespace pylith { - namespace sources { - class SquarePulseSource : public pylith::sources::Source { - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - SquarePulseSource(void); - - /// Destructor. - ~SquarePulseSource(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field& solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); - - /** Update kernel constants. - * - * @param[in] dt Current time step. - */ - void _updateKernelConstants(const PylithReal dt); - - }; // class SquarePulseSource - - } // sources -} // pylith - -// End of file \ No newline at end of file diff --git a/modulesrc/sources/WellboreSource.i b/modulesrc/sources/WellboreSource.i deleted file mode 100644 index 7de30528d3..0000000000 --- a/modulesrc/sources/WellboreSource.i +++ /dev/null @@ -1,117 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2016 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file modulesrc/sources/WellboreSource.i - * - * Python interface to C++ WellboreSource. - */ - -namespace pylith { - namespace sources { - class WellboreSource : public pylith::sources::Source { - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - WellboreSource(void); - - /// Destructor. - ~WellboreSource(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory* th); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory* getTimeHistoryDB(void); - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field& solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator* createIntegrator(const pylith::topology::Field& solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field* createAuxiliaryField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field* createDerivedField(const pylith::topology::Field& solution, - const pylith::topology::Mesh& domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory* _getAuxiliaryFactory(void); - - /** Update kernel constants. - * - * @param[in] dt Current time step. - */ - void _updateKernelConstants(const PylithReal dt); - - }; // class WellboreSource - - } // sources -} // pylith - -// End of file \ No newline at end of file diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i index 5bc04cca9b..cc4b933a06 100644 --- a/modulesrc/sources/sources.i +++ b/modulesrc/sources/sources.i @@ -19,9 +19,6 @@ // Header files for module C++ code %{ #include "pylith/sources/Source.hh" -#include "pylith/sources/WellboreSource.hh" -#include "pylith/sources/SquarePulseSource.hh" -#include "pylith/sources/PointForce.hh" #include "pylith/sources/MomentTensorForce.hh" #include "pylith/sources/SquareWavelet.hh" #include "pylith/sources/RickerWavelet.hh" diff --git a/pylith/Makefile.am b/pylith/Makefile.am index 97ae30f110..1eebf9ad1a 100644 --- a/pylith/Makefile.am +++ b/pylith/Makefile.am @@ -145,14 +145,11 @@ EXTRA_DIST = \ sources/Source.py \ sources/SquareWavelet.py \ sources/RickerWavelet.py \ - sources/PointForce.py \ sources/MomentTensorForce.py \ sources/GaussianWavelet.py \ - sources/AuxSubfieldsWellboreSource.py \ - sources/AuxSubfieldsSquarePulseSource.py \ sources/AuxSubfieldsSourceTime.py \ - sources/AuxSubfieldsPointForce.py \ sources/AuxSubfieldsMomentTensorForce.py \ + sources/TimeHistoryWavelet.py \ sources/__init__.py \ testing/FullTestApp.py \ testing/SolutionPoints.py \ diff --git a/pylith/sources/AuxSubfieldsPointForce.py b/pylith/sources/AuxSubfieldsPointForce.py deleted file mode 100644 index cc8213b5e4..0000000000 --- a/pylith/sources/AuxSubfieldsPointForce.py +++ /dev/null @@ -1,63 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Vuffalo - -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/AuxSubfieldsPointForce.py -# -# @brief Python container for pointforce equation subfields. - -from pylith.utils.PetscComponent import PetscComponent - - -class AuxSubfieldsPointForce(PetscComponent): - """Python container for pointforce equation subfields. - - FACTORY: auxiliary_subfields - """ - - import pythia.pyre.inventory - - from pylith.topology.Subfield import Subfield - - pointForce = pythia.pyre.inventory.facility("point_force", family="auxiliary_subfield", factory=Subfield) - pointForce.meta['tip'] = "Point Force subfield." - - timeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) - timeDelay.meta['tip'] = "time delay subfield." - - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="auxsubfieldspointforce"): - """Constructor. - """ - PetscComponent.__init__(self, name, facility="auxiliary_subfields") - return - - # PRIVATE METHODS //////////////////////////////////////////////////// - - def _configure(self): - PetscComponent._configure(self) - return - - -# FACTORIES //////////////////////////////////////////////////////////// - -def auxiliary_subfields(): - """Factory associated with AuxSubfieldsPointForce. - """ - return AuxSubfieldsPointForce() - - -# End of file diff --git a/pylith/sources/AuxSubfieldsSquarePulseSource.py b/pylith/sources/AuxSubfieldsSquarePulseSource.py deleted file mode 100644 index d6d462fcd1..0000000000 --- a/pylith/sources/AuxSubfieldsSquarePulseSource.py +++ /dev/null @@ -1,64 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/AuxSubfieldsSquarePulseSource.py -# -# @brief Python container for squarepulsesource equation subfields. - -from pylith.utils.PetscComponent import PetscComponent - - -class AuxSubfieldsSquarePulseSource(PetscComponent): - """Python container for squarepulsesource equation subfields. - - FACTORY: auxiliary_subfields - """ - - import pythia.pyre.inventory - - from pylith.topology.Subfield import Subfield - - volumeFlowRate = pythia.pyre.inventory.facility("volume_flow_rate", family="auxiliary_subfield", factory=Subfield) - volumeFlowRate.meta['tip'] = "Volume Flow Rate subfield." - - timeDelay = pythia.pyre.inventory.facility( - "time_delay", family="auxiliary_subfield", factory=Subfield) - timeDelay.meta['tip'] = "time delay subfield." - - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="auxsubfieldssquarepulsesource"): - """Constructor. - """ - PetscComponent.__init__(self, name, facility="auxiliary_subfields") - return - - # PRIVATE METHODS //////////////////////////////////////////////////// - - def _configure(self): - PetscComponent._configure(self) - return - - -# FACTORIES //////////////////////////////////////////////////////////// - -def auxiliary_subfields(): - """Factory associated with AuxSubfieldsSquarePulseSource. - """ - return AuxSubfieldsSquarePulseSource() - - -# End of file diff --git a/pylith/sources/AuxSubfieldsWellboreSource.py b/pylith/sources/AuxSubfieldsWellboreSource.py deleted file mode 100644 index 83d65bed34..0000000000 --- a/pylith/sources/AuxSubfieldsWellboreSource.py +++ /dev/null @@ -1,89 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/AuxSubfieldsWellboreSource.py -# -# @brief Python container for wellboresource equation subfields. - -from pylith.utils.PetscComponent import PetscComponent - - -class AuxSubfieldsWellboreSource(PetscComponent): - """Python container for wellboresource equation subfields. - - FACTORY: auxiliary_subfields - """ - - import pythia.pyre.inventory - - from pylith.topology.Subfield import Subfield - - fluidDensity = pythia.pyre.inventory.facility("fluid_density", family="auxiliary_subfield", factory=Subfield) - fluidDensity.meta['tip'] = "Fluid density subfield." - - fluidViscosity = pythia.pyre.inventory.facility("fluid_viscosity", family="auxiliary_subfield", factory=Subfield) - fluidViscosity.meta['tip'] = "Fluid viscosity subfield." - - isotropicPermeability = pythia.pyre.inventory.facility( - "isotropic_permeability", family="auxiliary_subfield", factory=Subfield) - isotropicPermeability.meta['tip'] = "Isotropic permeability subfield." - - wellboreRadius = pythia.pyre.inventory.facility( - "wellbore_radius", family="auxiliary_subfield", factory=Subfield) - wellboreRadius.meta['tip'] = "Wellbore radius subfield." - - wellboreLength = pythia.pyre.inventory.facility( - "wellbore_length", family="auxiliary_subfield", factory=Subfield) - wellboreLength.meta['tip'] = "Wellbore length subfield." - - wellboreCharacter = pythia.pyre.inventory.facility( - "wellbore_character", family="auxiliary_subfield", factory=Subfield) - wellboreCharacter.meta['tip'] = "Wellbore character subfield." - - wellborePressure = pythia.pyre.inventory.facility( - "wellbore_pressure", family="auxiliary_subfield", factory=Subfield) - wellborePressure.meta['tip'] = "Wellbore pressure subfield." - - elementDimensions = pythia.pyre.inventory.facility( - "element_dimensions", family="auxiliary_subfield", factory=Subfield) - elementDimensions.meta['tip'] = "Element dimension subfield." - - timeDelay = pythia.pyre.inventory.facility("time_delay", family="auxiliary_subfield", factory=Subfield) - timeDelay.meta['tip'] = "time delay subfield." - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="auxsubfieldswellboresource"): - """Constructor. - """ - PetscComponent.__init__(self, name, facility="auxiliary_subfields") - return - - # PRIVATE METHODS //////////////////////////////////////////////////// - - def _configure(self): - PetscComponent._configure(self) - return - - -# FACTORIES //////////////////////////////////////////////////////////// - -def auxiliary_subfields(): - """Factory associated with AuxSubfieldsWellboreSource. - """ - return AuxSubfieldsWellboreSource() - - -# End of file diff --git a/pylith/sources/PointForce.py b/pylith/sources/PointForce.py deleted file mode 100644 index 87c4f97dfc..0000000000 --- a/pylith/sources/PointForce.py +++ /dev/null @@ -1,68 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/PointForce.py -# -# @brief Python object for solving the pointforce equation. -# -# Factory: source - -from .Source import Source -from .sources import PointForce as ModulePointForce - - -class PointForce(Source, ModulePointForce): - """Python source property manager. - - FACTORY: source - """ - - import pythia.pyre.inventory - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="pointforce"): - """Constructor. - """ - Source.__init__(self, name) - return - - def _defaults(self): - from .AuxSubfieldsPointForce import AuxSubfieldsPointForce - self.auxiliarySubfields = AuxSubfieldsPointForce("auxiliary_subfields") - - def preinitialize(self, problem): - """Setup source. - """ - Source.preinitialize(self, problem) - - return - - def _createModuleObj(self): - """Create handle to C++ PointForce. - """ - ModulePointForce.__init__(self) - return - - -# Factories - -def source(): - """Factory associated with PointForce. - """ - return PointForce() - - -# End of file diff --git a/pylith/sources/SquarePulseSource.py b/pylith/sources/SquarePulseSource.py deleted file mode 100644 index 4132db454b..0000000000 --- a/pylith/sources/SquarePulseSource.py +++ /dev/null @@ -1,71 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/SquarePulseSource.py -# -# @brief Python object for solving the squarepulsesource equation. -# -# Factory: source - -from .Source import Source -from .sources import SquarePulseSource as ModuleSquarePulseSource - - -class SquarePulseSource(Source, ModuleSquarePulseSource): - """Python source property manager. - - FACTORY: source - """ - - import pythia.pyre.inventory - - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="squarepulsesource"): - """Constructor. - """ - Source.__init__(self, name) - return - - def _defaults(self): - from .AuxSubfieldsSquarePulseSource import AuxSubfieldsSquarePulseSource - self.auxiliarySubfields = AuxSubfieldsSquarePulseSource("auxiliary_subfields") - - - def preinitialize(self, problem): - """Setup source. - """ - Source.preinitialize(self, problem) - - - return - - def _createModuleObj(self): - """Create handle to C++ SquarePulseSource. - """ - ModuleSquarePulseSource.__init__(self) - return - - -# Factories - -def source(): - """Factory associated with SquarePulseSource. - """ - return SquarePulseSource() - - -# End of file diff --git a/pylith/sources/TimeHistorySource.py b/pylith/sources/TimeHistorySource.py deleted file mode 100644 index b86def2120..0000000000 --- a/pylith/sources/TimeHistorySource.py +++ /dev/null @@ -1,113 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/TimeHistorySource.py -# -# @brief Python object for solving the timehistorysource equation. -# -# Factory: source - -from .Source import Source -from .sources import TimeHistorySource as ModuleTimeHistorySource - - -class TimeHistorySource(Source, ModuleTimeHistorySource): - """Python source property manager. - - FACTORY: source - """ - - import pythia.pyre.inventory - - useInitial = pythia.pyre.inventory.bool("use_initial", default=True) - useInitial.meta['tip'] = "Use initial term in time-dependent expression." - - useRate = pythia.pyre.inventory.bool("use_rate", default=False) - useRate.meta['tip'] = "Use rate term in time-dependent expression." - - useTimeHistory = pythia.pyre.inventory.bool("use_time_history", default=True) - useTimeHistory.meta['tip'] = "Use time history term in time-dependent expression." - - dbTimeHistory = pythia.pyre.inventory.facility( - "time_history", factory=NullComponent, family="temporal_database") - dbTimeHistory.meta['tip'] = "Time history with normalized amplitude as a function of time." - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="timehistorysource"): - """Constructor. - """ - Source.__init__(self, name) - return - - def _defaults(self): - from .AuxSubfieldsTimeHistorySource import AuxSubfieldsTimeHistorySource - self.auxiliarySubfields = AuxSubfieldsTimeHistorySource("auxiliary_subfields") - - def preinitialize(self, problem): - """Do pre-initialization setup. - """ - from pylith.mpi.Communicator import mpi_is_root - if mpi_is_root(): - self._info.log( - "Performing minimal initialization of time-dependent Neumann boundary condition '%s'." % self.aliases[-1]) - - - Source.preinitialize(self, problem) - ModuleTimeHistorySource.useTimeHistory(self, self.useTimeHistory) - if not isinstance(self.dbTimeHistory, NullComponent): - ModuleTimeHistorySource.setTimeHistoryDB( - self, self.dbTimeHistory) - return - - def _validate(self, context): - if isinstance(self.inventory.dbTimeHistory, NullComponent): - trait = self.inventory.getTrait("time_history") - self._validationError(context, trait, - f"Missing time history database for time history wavelet source '{self.aliases[-1]}'.") - - def _validationError(self, context, trait, msg): - from pythia.pyre.inventory.Item import Item - error = ValueError(msg) - descriptor = self.getTraitDescriptor(trait.name) - context.error(error, items=[Item(trait, descriptor)]) - - - - - def preinitialize(self, problem): - """Setup source. - """ - Source.preinitialize(self, problem) - - - return - - def _createModuleObj(self): - """Create handle to C++ TimeHistorySource. - """ - ModuleTimeHistorySource.__init__(self) - return - - -# Factories - -def source(): - """Factory associated with TimeHistorySource. - """ - return TimeHistorySource() - - -# End of file diff --git a/pylith/sources/WellboreSource.py b/pylith/sources/WellboreSource.py deleted file mode 100644 index cf1bad6a60..0000000000 --- a/pylith/sources/WellboreSource.py +++ /dev/null @@ -1,71 +0,0 @@ -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University of Chicago -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2016 University of California, Davis -# -# See COPYING for license information. -# -# ---------------------------------------------------------------------- -# -# @file pylith/sources/WellboreSource.py -# -# @brief Python object for solving the wellboresource equation. -# -# Factory: source - -from .Source import Source -from .sources import WellboreSource as ModuleWellboreSource - - -class WellboreSource(Source, ModuleWellboreSource): - """Python source property manager. - - FACTORY: source - """ - - import pythia.pyre.inventory - - - # PUBLIC METHODS ///////////////////////////////////////////////////// - - def __init__(self, name="wellboresource"): - """Constructor. - """ - Source.__init__(self, name) - return - - def _defaults(self): - from .AuxSubfieldsWellboreSource import AuxSubfieldsWellboreSource - self.auxiliarySubfields = AuxSubfieldsWellboreSource("auxiliary_subfields") - - - def preinitialize(self, problem): - """Setup source. - """ - Source.preinitialize(self, problem) - - - return - - def _createModuleObj(self): - """Create handle to C++ WellboreSource. - """ - ModuleWellboreSource.__init__(self) - return - - -# Factories - -def source(): - """Factory associated with WellboreSource. - """ - return WellboreSource() - - -# End of file diff --git a/pylith/sources/__init__.py b/pylith/sources/__init__.py index cc5d2b72b3..6e69b6e03a 100644 --- a/pylith/sources/__init__.py +++ b/pylith/sources/__init__.py @@ -20,11 +20,6 @@ __all__ = [ "Source", - "AuxSubfieldsWellboreSource", - "WellboreSource", - "SquarePulseSource", - "PointForce", - "AuxSubfieldsPointForce", "MomentTensorForce", "AuxSubfieldsMomentTensorForce", "SourceTimeFunctionMomentTensorForce", @@ -32,7 +27,6 @@ "SquareWavelet", "RickerWavelet", "TimeHistoryWavelet", - "TimeHistorySource", "GaussianWavelet" ] From 598e6954d57bb9e4445b1c5b61ccf10971b0a14b Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 13:14:45 -0600 Subject: [PATCH 52/65] Adjustments to permit compilation --- libsrc/pylith/fekernels/GaussianWavelet.hh | 2 ++ libsrc/pylith/fekernels/SquareWavelet.hh | 2 ++ libsrc/pylith/sources/Makefile.am | 1 - modulesrc/sources/sources.i | 3 --- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/pylith/fekernels/GaussianWavelet.hh b/libsrc/pylith/fekernels/GaussianWavelet.hh index 065e6698b7..a2045010e2 100644 --- a/libsrc/pylith/fekernels/GaussianWavelet.hh +++ b/libsrc/pylith/fekernels/GaussianWavelet.hh @@ -28,6 +28,8 @@ #include "pylith/utils/types.hh" +#include // USES assert() + // ===================================================================================================================== // Kernels for the Ricker Source Time Function in 2D. // ===================================================================================================================== diff --git a/libsrc/pylith/fekernels/SquareWavelet.hh b/libsrc/pylith/fekernels/SquareWavelet.hh index 76a5813958..5a1b81556e 100644 --- a/libsrc/pylith/fekernels/SquareWavelet.hh +++ b/libsrc/pylith/fekernels/SquareWavelet.hh @@ -28,6 +28,8 @@ #include "pylith/utils/types.hh" +#include // USES assert() + // ===================================================================================================================== // Kernels for the Square Source Time Function in 2D. // ===================================================================================================================== diff --git a/libsrc/pylith/sources/Makefile.am b/libsrc/pylith/sources/Makefile.am index b8f87e7059..7634ff9de2 100644 --- a/libsrc/pylith/sources/Makefile.am +++ b/libsrc/pylith/sources/Makefile.am @@ -22,7 +22,6 @@ include $(top_srcdir)/subpackage.am subpkginclude_HEADERS = \ Source.hh \ MomentTensorForce.hh \ - AuxiliaryFactorySquarePulseSource.hh \ AuxiliaryFactoryMomentTensorForce.hh \ AuxiliaryFactorySourceTime.hh \ DerivedFactoryMomentTensorForce.hh \ diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i index cc4b933a06..a3c70c1c28 100644 --- a/modulesrc/sources/sources.i +++ b/modulesrc/sources/sources.i @@ -56,9 +56,6 @@ import_array(); %include "../problems/Physics.i" %include "Source.i" -%include "WellboreSource.i" -%include "SquarePulseSource.i" -%include "PointForce.i" %include "MomentTensorForce.i" %include "SourceTimeFunctionMomentTensorForce.i" %include "SquareWavelet.i" From ee337908d7911c44529663c86ab5added5c02bd8 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 13:50:37 -0600 Subject: [PATCH 53/65] Fixed install files so that it runs --- libsrc/pylith/Makefile.am | 1 + libsrc/pylith/sources/SquarePulseSource.cc | 292 --------------------- libsrc/pylith/sources/SquarePulseSource.hh | 153 ----------- modulesrc/sources/sources.i | 2 - 4 files changed, 1 insertion(+), 447 deletions(-) delete mode 100644 libsrc/pylith/sources/SquarePulseSource.cc delete mode 100644 libsrc/pylith/sources/SquarePulseSource.hh diff --git a/libsrc/pylith/Makefile.am b/libsrc/pylith/Makefile.am index 498aaa4b90..ae8439c8c6 100644 --- a/libsrc/pylith/Makefile.am +++ b/libsrc/pylith/Makefile.am @@ -138,6 +138,7 @@ libpylith_la_SOURCES = \ sources/TimeHistoryWavelet.cc \ sources/Source.cc \ sources/SourceTimeFunctionMomentTensorForce.cc \ + sources/MomentTensorForce.cc \ topology/Mesh.cc \ topology/MeshOps.cc \ topology/FieldBase.cc \ diff --git a/libsrc/pylith/sources/SquarePulseSource.cc b/libsrc/pylith/sources/SquarePulseSource.cc deleted file mode 100644 index f1b5917786..0000000000 --- a/libsrc/pylith/sources/SquarePulseSource.cc +++ /dev/null @@ -1,292 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "pylith/sources/SquarePulseSource.hh" // implementation of object methods - -#include "pylith/sources/AuxiliaryFactorySquarePulseSource.hh" // USES AuxiliaryFactorySquarePulseSource -#include "pylith/feassemble/IntegratorDomain.hh" // USES IntegratorDomain -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/Field.hh" // USES Field::SubfieldInfo -#include "pylith/topology/FieldOps.hh" // USES FieldOps - -#include "pylith/fekernels/SquarePulseSource.hh" // USES SquarePulseSource kernels - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* -#include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* - -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include // USES typeid() - -// --------------------------------------------------------------------------------------------------------------------- -typedef pylith::feassemble::IntegratorDomain::ResidualKernels ResidualKernels; -typedef pylith::feassemble::IntegratorDomain::JacobianKernels JacobianKernels; -typedef pylith::feassemble::IntegratorDomain::ProjectKernels ProjectKernels; -typedef pylith::feassemble::Integrator::EquationPart EquationPart; - -// --------------------------------------------------------------------------------------------------------------------- -// Default constructor. -pylith::sources::SquarePulseSource::SquarePulseSource(void) : _useInertia(false), - _auxiliaryFactory(new pylith::sources::AuxiliaryFactorySquarePulseSource) { - pylith::utils::PyreComponent::setName("squarepulsesource"); -} // constructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Destructor. -pylith::sources::SquarePulseSource::~SquarePulseSource(void) { - deallocate(); -} // destructor - - -// --------------------------------------------------------------------------------------------------------------------- -// Deallocate PETSc and local data structures. -void -pylith::sources::SquarePulseSource::deallocate(void) { - Source::deallocate(); - - delete _auxiliaryFactory; - _auxiliaryFactory = NULL; -} // deallocate - - -// --------------------------------------------------------------------------------------------------------------------- -// Set time history database. -void -pylith::sources::SquarePulseSource::setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th) { - PYLITH_COMPONENT_DEBUG("setTimeHistoryDB(th" << th << ")"); - - _dbTimeHistory = th; -} // setTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Get time history database. -const spatialdata::spatialdb::TimeHistory * -pylith::sources::SquarePulseSource::getTimeHistoryDB(void) { - return _dbTimeHistory; -} // getTimeHistoryDB - - -// --------------------------------------------------------------------------------------------------------------------- -// Use time history term in time history expression. -void -pylith::sources::SquarePulseSource::useTimeHistory(const bool value) { - PYLITH_COMPONENT_DEBUG("useTimeHistory(value=" << value << ")"); - - _useTimeHistory = value; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Get flag associated with using time history term in time history expression. -bool -pylith::sources::SquarePulseSource::useTimeHistory(void) const { - return _useTimeHistory; -} // useTimeHistory - - -// --------------------------------------------------------------------------------------------------------------------- -// Verify configuration is acceptable. -void -pylith::sources::SquarePulseSource::verifyConfiguration(const pylith::topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("verifyConfiguration(solution=" << solution.getLabel() << ")"); - - // Verify solution contains expected fields. - if (!solution.hasSubfield("pressure")) { - throw std::runtime_error("Cannot find 'pressure' field in solution; required for 'SquarePulseSource'."); - } // if - - PYLITH_METHOD_END; -} // verifyConfiguration - - -// --------------------------------------------------------------------------------------------------------------------- -// Create integrator and set kernels. -pylith::feassemble::Integrator * -pylith::sources::SquarePulseSource::createIntegrator(const pylith::topology::Field &solution) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createIntegrator(solution=" << solution.getLabel() << ")"); - - pylith::sources::Source::locateSource(solution, getLabelName(), getLabelValue()); - - pylith::feassemble::IntegratorDomain *integrator = new pylith::feassemble::IntegratorDomain(this); - assert(integrator); - integrator->setLabelName(getLabelName()); - integrator->setLabelValue(getLabelValue()); - // printf("In SquarePulseSource end\n"); - // DMView(dmSoln, NULL); - - _setKernelsResidual(integrator, solution); - _setKernelsJacobian(integrator, solution); - - PYLITH_METHOD_RETURN(integrator); -} // createIntegrator - - -// --------------------------------------------------------------------------------------------------------------------- -// Create auxiliary field. -pylith::topology::Field * -pylith::sources::SquarePulseSource::createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createAuxiliaryField(solution=" << solution.getLabel() << ", domainMesh=" << typeid(domainMesh).name() << ")"); - - pylith::topology::Field *auxiliaryField = new pylith::topology::Field(domainMesh); - assert(auxiliaryField); - auxiliaryField->setLabel("SquarePulseSource auxiliary field"); - - assert(_normalizer); - _auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); - - // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. - - // :ATTENTION: In quasi-static problems, the time scale is usually quite large - // (order of tens to hundreds of years), which means that the density scale is very large, - // and the acceleration scale is very small. Nevertheless, density times gravitational - // acceleration will have a scale of pressure divided by length and should be within a few orders - // of magnitude of 1. - - // add in aux specific to square pulse - _auxiliaryFactory->addVolumeFlowRate(); // 0 - _auxiliaryFactory->addTimeDelay(); // 1 - - auxiliaryField->subfieldsSetup(); - auxiliaryField->createDiscretization(); - pylith::topology::FieldOps::checkDiscretization(solution, *auxiliaryField); - auxiliaryField->allocate(); - auxiliaryField->createOutputVector(); - - assert(_auxiliaryFactory); - _auxiliaryFactory->setValuesFromDB(); - - // Debug option - auxiliaryField->view("SquarePulse auxiliary field."); - - PYLITH_METHOD_RETURN(auxiliaryField); -} // createAuxiliaryField - - -// --------------------------------------------------------------------------------------------------------------------- -// Create derived field. -pylith::topology::Field * -pylith::sources::SquarePulseSource::createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh) { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("createDerivedField(solution=" << solution.getLabel() << ", domainMesh=)" << typeid(domainMesh).name() << ") empty method"); - - PYLITH_METHOD_RETURN(NULL); -} // createDerivedField - - -// --------------------------------------------------------------------------------------------------------------------- -// Get auxiliary factory associated with physics. -pylith::feassemble::AuxiliaryFactory * -pylith::sources::SquarePulseSource::_getAuxiliaryFactory(void) { - return _auxiliaryFactory; -} // _getAuxiliaryFactory - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS residual F(t,s,\dot{s}). -void -pylith::sources::SquarePulseSource::_setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsResidual(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - // Pressure - const PetscPointFunc f0p = pylith::fekernels::SquarePulseSource::f0p; - const PetscPointFunc f1p = NULL; - - kernels.resize(1); - kernels[0] = ResidualKernels(getSubfieldName(), pylith::feassemble::Integrator::LHS, f0p, f1p); - break; - } // QUASISTATIC - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC - case DYNAMIC: - { - break; - } // DYNAMIC - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsResidual(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsResidual - - -// --------------------------------------------------------------------------------------------------------------------- -// Set kernels for LHS Jacobian F(t,s,\dot{s}). -void -pylith::sources::SquarePulseSource::_setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const topology::Field &solution) const { - PYLITH_METHOD_BEGIN; - PYLITH_COMPONENT_DEBUG("_setKernelsJacobian(integrator=" << integrator << ", solution=" << solution.getLabel() << ")"); - - const spatialdata::geocoords::CoordSys *coordsys = solution.getMesh().getCoordSys(); - - std::vector kernels; - - switch (_formulation) { - case QUASISTATIC: - { - const PetscPointJac Jf0pp = NULL; - const PetscPointJac Jf1pp = NULL; - const PetscPointJac Jf2pp = NULL; - const PetscPointJac Jf3pp = NULL; - - kernels.resize(1); - const EquationPart equationPart = pylith::feassemble::Integrator::LHS; - kernels[0] = JacobianKernels(getSubfieldName(), getSubfieldName(), equationPart, Jf0pp, Jf1pp, Jf2pp, Jf3pp); - break; - } // QUASISTATIC - case DYNAMIC: - case DYNAMIC_IMEX: - { - break; - } // DYNAMIC_IMEX - default: - PYLITH_COMPONENT_LOGICERROR("Unknown formulation for equations (" << _formulation << ")."); - } // switch - - assert(integrator); - integrator->setKernelsJacobian(kernels, solution); - - PYLITH_METHOD_END; -} // _setKernelsJacobian - - -// End of file diff --git a/libsrc/pylith/sources/SquarePulseSource.hh b/libsrc/pylith/sources/SquarePulseSource.hh deleted file mode 100644 index 4c287fa594..0000000000 --- a/libsrc/pylith/sources/SquarePulseSource.hh +++ /dev/null @@ -1,153 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University of Chicago -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2015 University of California, Davis -// -// See COPYING for license information. -// -// ---------------------------------------------------------------------- -// - -/** @file libsrc/sources/SquarePulseSource.hh - * - * @brief C++ class for solving squarepulsesource equation. - */ - -#if !defined(pylith_sources_squarepulsesource_hh) -#define pylith_sources_squarepulsesource_hh - -#include "sourcesfwd.hh" // forward declarations - -#include "pylith/sources/Source.hh" // ISA Source - -class pylith::sources::SquarePulseSource : public pylith::sources::Source { - friend class TestSquarePulseSource; // unit testing - - // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////////////////////////////// -public: - - /// Default constructor. - SquarePulseSource(void); - - /// Destructor. - ~SquarePulseSource(void); - - /// Deallocate PETSc and local data structures. - void deallocate(void); - - /** Set time history database. - * - * @param[in] db Time history database. - */ - void setTimeHistoryDB(spatialdata::spatialdb::TimeHistory *th); - - /** Get time history database. - * - * @preturns Time history database. - */ - const spatialdata::spatialdb::TimeHistory *getTimeHistoryDB(void); - - /** Use time history term in time history expression. - * - * @param[in] value True if using time history term in expression. - */ - void useTimeHistory(const bool value); - - /** Get flag associated with using time history term in time history expression. - * - * @returns True if using time history term in expression, false otherwise. - */ - bool useTimeHistory(void) const; - - /** Verify configuration is acceptable. - * - * @param[in] solution Solution field. - */ - void verifyConfiguration(const pylith::topology::Field &solution) const; - - /** Create integrator and set kernels. - * - * @param[in] solution Solution field. - * - * @returns Integrator if applicable, otherwise NULL. - */ - pylith::feassemble::Integrator *createIntegrator(const pylith::topology::Field &solution); - - /** Create auxiliary field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Auxiliary field if applicable, otherwise NULL. - */ - pylith::topology::Field *createAuxiliaryField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - /** Create derived field. - * - * @param[in] solution Solution field. - * @param[in\ domainMesh Finite-element mesh associated with integration domain. - * - * @returns Derived field if applicable, otherwise NULL. - */ - pylith::topology::Field *createDerivedField(const pylith::topology::Field &solution, - const pylith::topology::Mesh &domainMesh); - - // PROTECTED METHODS /////////////////////////////////////////////////////////////////////////////////////////////// -protected: - - /** Get auxiliary factory associated with physics. - * - * @return Auxiliary factory for physics object. - */ - pylith::feassemble::AuxiliaryFactory *_getAuxiliaryFactory(void); - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - /** Set kernels for residual. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsResidual(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - /** Set kernels for Jacobian. - * - * @param[out] integrator Integrator for source. - * @param[in] solution Solution field. - */ - void _setKernelsJacobian(pylith::feassemble::IntegratorDomain *integrator, - const pylith::topology::Field &solution) const; - - // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - bool _useInertia; ///< Flag to include inertial term. - spatialdata::spatialdb::TimeHistory *_dbTimeHistory; ///< Time history database. - pylith::sources::AuxiliaryFactorySquarePulseSource *_auxiliaryFactory; ///< Factory for auxiliary subfields. - - bool _useTimeHistory; ///< Use time history term. - - // NOT IMPLEMENTED ///////////////////////////////////////////////////////////////////////////////////////////////// -private: - - SquarePulseSource(const SquarePulseSource &); ///< Not implemented. - const SquarePulseSource &operator=(const SquarePulseSource &); /// Not implemented. - -}; - -// class SquarePulseSource - -#endif // pylith_sources_squarepulsesource_hh - -// End of file diff --git a/modulesrc/sources/sources.i b/modulesrc/sources/sources.i index a3c70c1c28..dee6a1c37a 100644 --- a/modulesrc/sources/sources.i +++ b/modulesrc/sources/sources.i @@ -25,7 +25,6 @@ #include "pylith/sources/GaussianWavelet.hh" #include "pylith/sources/SourceTimeFunctionMomentTensorForce.hh" #include "pylith/sources/TimeHistoryWavelet.hh" - #include "pylith/utils/arrayfwd.hh" %} @@ -54,7 +53,6 @@ import_array(); // Interfaces %include "../utils/PyreComponent.i" %include "../problems/Physics.i" - %include "Source.i" %include "MomentTensorForce.i" %include "SourceTimeFunctionMomentTensorForce.i" From caf6d6ae833c00ed416785787f3494b5510752a8 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 15:35:40 -0600 Subject: [PATCH 54/65] Removed unrelated tests --- tests/libtests/sources/Makefile.am | 45 --- .../sources/TestAuxiliaryFactoryPointForce.cc | 218 ---------- .../sources/TestAuxiliaryFactoryPointForce.hh | 109 ----- .../TestAuxiliaryFactoryPointForce_Cases.cc | 173 -------- .../TestAuxiliaryFactoryWellboreSource.cc | 372 ------------------ .../TestAuxiliaryFactoryWellboreSource.hh | 110 ------ ...estAuxiliaryFactoryWellboreSource_Cases.cc | 258 ------------ 7 files changed, 1285 deletions(-) delete mode 100644 tests/libtests/sources/Makefile.am delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am deleted file mode 100644 index 151014e900..0000000000 --- a/tests/libtests/sources/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# -*- Makefile -*- -# -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2022 University of California, Davis -# -# See LICENSE.md for license information. -# -# ---------------------------------------------------------------------- -# - -include $(top_srcdir)/tests/check_catch2.am - -SUBDIRS = data - -TESTS = libtest_sources - -check_PROGRAMS = $(TESTS) - - -libtest_sources_SOURCES = \ - TestAuxiliaryFactoryMomentTensorForce.cc \ - TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ - TestAuxiliaryFactorySourceTime.cc \ - TestAuxiliaryFactorySourceTime_Cases.cc \ - TestAuxiliaryFactoryPointForce.cc \ - TestAuxiliaryFactoryPointForce_Cases.cc \ - $(top_srcdir)/tests/src/FieldTester.cc \ - $(top_srcdir)/tests/src/driver_catch2.cc - - -dist_noinst_HEADERS = \ - TestAuxiliaryFactoryMomentTensorForce.hh \ - TestAuxiliaryFactorySourceTime.hh \ - TestAuxiliaryFactoryPointForce.hh - - -# End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc deleted file mode 100644 index c9f3e3cb8c..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.cc +++ /dev/null @@ -1,218 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryPointForce.hh" // Implementation of class methods - -#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // Test subject -#include "tests/src/FieldTester.hh" // USES FieldTester - -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/MeshOps.hh" // USES MeshOps -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t - -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -// ------------------------------------------------------------------------------------------------ -// Constructor. -pylith::sources::TestAuxiliaryFactoryPointForce::TestAuxiliaryFactoryPointForce(TestAuxiliaryFactoryPointForce_Data* data) : - _data(data) { - PYLITH_METHOD_BEGIN; - - assert(_data->normalizer); - _data->normalizer->setLengthScale(1.0e+03); - _data->normalizer->setTimeScale(2.0); - _data->normalizer->setDensityScale(3.0e+3); - _data->normalizer->setPressureScale(2.25e+10); - - pylith::topology::Field::SubfieldInfo info; - pylith::string_vector componentNames; - - // pointForce - componentNames.resize(3); - componentNames[0] = "point_force_x"; - componentNames[1] = "point_force_y"; - componentNames[2] = "point_force_z"; - - info.description = pylith::topology::Field::Description( - "point_force", - "point_force", - componentNames, - componentNames.size(), - pylith::topology::Field::VECTOR, - _data->normalizer->getPressureScale() - ); - info.fe = pylith::topology::Field::Discretization( - 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false - ); - info.index = 0; - _data->subfields["point_force"] = info; - if (2 == _data->auxDim) { - _data->subfields["point_force"].description.numComponents = 2; - _data->subfields["point_force"].description.vectorFieldType = pylith::topology::Field::OTHER; - } // if - - // timeDelay - componentNames.resize(1); - componentNames[0] = "time_delay"; - info.description = pylith::topology::Field::Description( - "time_delay", - "time_delay", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorNonnegative - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 1; - _data->subfields["time_delay"] = info; - - _initialize(); - - PYLITH_METHOD_END; -} // constructor - - -// ------------------------------------------------------------------------------------------------ -// Destructor. -pylith::sources::TestAuxiliaryFactoryPointForce::~TestAuxiliaryFactoryPointForce(void) { - PYLITH_METHOD_BEGIN; - - delete _factory;_factory = NULL; - delete _data;_data = NULL; - delete _mesh;_mesh = NULL; - delete _auxiliaryField;_auxiliaryField = NULL; - - PYLITH_METHOD_END; -} // tearDown - - -// ------------------------------------------------------------------------------------------------ -// Test adding point force and time delay subfields. -void -pylith::sources::TestAuxiliaryFactoryPointForce::testAdd(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - assert(_data); - - CHECK(!_auxiliaryField->hasSubfield("point_force")); - CHECK(!_auxiliaryField->hasSubfield("time_delay")); - - _factory->addPointForce(); - _factory->addTimeDelay(); - - assert(_data->normalizer); - - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["point_force"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); - - PYLITH_METHOD_END; -} // testAdd - - -// ------------------------------------------------------------------------------------------------ -// Test setValues(). -void -pylith::sources::TestAuxiliaryFactoryPointForce::testSetValuesFromDB(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - - _factory->addPointForce(); - _factory->addTimeDelay(); - _auxiliaryField->subfieldsSetup(); - _auxiliaryField->createDiscretization(); - _auxiliaryField->allocate(); - - assert(_data); - assert(_data->normalizer); - _factory->setValuesFromDB(); - pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testSetValues - - -// ------------------------------------------------------------------------------------------------ -// Initialze mesh, coordinate system, auxiliary field, and factory. -void -pylith::sources::TestAuxiliaryFactoryPointForce::_initialize(void) { - PYLITH_METHOD_BEGIN; - assert(_data); - - pylith::meshio::MeshIOAscii iohandler; - assert(_data->meshFilename); - iohandler.setFilename(_data->meshFilename); - _mesh = new pylith::topology::Mesh();assert(_mesh); - iohandler.read(_mesh); - - assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); - assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); - - // Setup coordinates. - _mesh->setCoordSys(_data->cs); - assert(_data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); - - _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); - _auxiliaryField->setLabel("auxiliary"); - - _factory = new AuxiliaryFactoryPointForce(); - assert(_data->auxiliaryDB); - _factory->setQueryDB(_data->auxiliaryDB); - typedef std::map::const_iterator subfield_iter; - for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { - const char* subfieldName = iter->first.c_str(); - const pylith::topology::Field::Discretization& fe = iter->second.fe; - _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, - fe.feSpace, fe.isBasisContinuous); - } // for - assert(_data->normalizer); - _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); - - PYLITH_METHOD_END; -} // _initialize - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryPointForce_Data::TestAuxiliaryFactoryPointForce_Data(void) : - meshFilename(NULL), - cs(NULL), - normalizer(new spatialdata::units::Nondimensional), - auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryPointForce_Data::~TestAuxiliaryFactoryPointForce_Data(void) { - delete cs;cs = NULL; - delete normalizer;normalizer = NULL; - delete auxiliaryDB;auxiliaryDB = NULL; -} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh deleted file mode 100644 index e26d5fe05d..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh +++ /dev/null @@ -1,109 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// Robert L. Walker, Kegman, Inc. -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** - * @file tests/libtests/sources/TestAuxiliaryFactoryPointForce.hh - * - * @brief C++ TestAuxiliaryFactoryPointForce object. - * - * C++ unit testing for AuxiliaryFactoryPointForce. - */ - -#if !defined(pylith_sources_testauxiliaryfactorypointforce_hh) -#define pylith_sources_testauxiliaryfactorypointforce_hh - -#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent - -#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryPointForce -#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo -#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB -#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys -#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional - -#include // USES std::map - -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryPointForce; - class TestAuxiliaryFactoryPointForce_Data; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryPointForce : public pylith::utils::GenericComponent { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor. - TestAuxiliaryFactoryPointForce(TestAuxiliaryFactoryPointForce_Data* data); - - /// Destructor. - ~TestAuxiliaryFactoryPointForce(void); - - /// Test adding subfields. - void testAdd(void); - - /// Test setValuesFromDB(). - void testSetValuesFromDB(void); - - // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// -protected: - - /// Initialze mesh, coordinate system, auxiliary field, and factory. - void _initialize(void); - - // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// -protected: - - AuxiliaryFactoryPointForce* _factory; ///< Test subject. - TestAuxiliaryFactoryPointForce_Data* _data; ///< Test data. - - pylith::topology::Mesh* _mesh; ///< Finite-element mesh. - pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. - -}; // class TestAuxiliaryFactoryPointForce - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryPointForce_Data { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor - TestAuxiliaryFactoryPointForce_Data(void); - - /// Destructor - ~TestAuxiliaryFactoryPointForce_Data(void); - - // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// -public: - - size_t dimension; ///< Spatial dimension. - size_t auxDim; ///< Topological dimension of auxiliary field. - const char* meshFilename; ///< Name of file with ASCII mesh. - spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. - spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. - - std::map subfields; - spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - -}; // class TestAuxiliaryFactoryPointForce_Data - -#endif // pylith_sources_testAuxiliaryFactoryPointForce_hh - -// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc deleted file mode 100644 index 8371f47b82..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryPointForce_Cases.cc +++ /dev/null @@ -1,173 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryPointForce.hh" // Implementation of cases - -#include "pylith/sources/AuxiliaryFactoryPointForce.hh" // USES AuxiliaryFactoryPointForce -#include "spatialdata/geocoords/CSCart.hh" // USES CSCart -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -#include // USES fabs() - -// forward declarations -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryPointForce_Cases; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryPointForce_Cases { -public: - - // Data factory methods - static TestAuxiliaryFactoryPointForce_Data* Tri(void); - - static TestAuxiliaryFactoryPointForce_Data* Hex(void); - -private: - - static - double point_force_2d_x(const double x, - const double y) { - return 0.3*x*x + 0.1*x*y; - } // point_force_2d_x - - static - double point_force_2d_y(const double x, - const double y) { - return 0.8*x*y + 0.2*y*y; - } // point_force_2d_yy - - static - double point_force_2d_z(const double x, - const double y) { - return 0.3*x*x + 0.5*y*y; - } // point_force_2d_z - - static - const char* point_force_units(void) { - return "Pa"; - } // point_force_units - - static - double time_delay_2d(const double x, - const double y) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); - } // time_delay - - static - const char* time_units(void) { - return "s"; - } // time_units - - static - double point_force_3d_x(const double x, - const double y, - const double z) { - return -0.3*x*z + 0.1*x*z; - } // point_force_3d_x - - static - double point_force_3d_y(const double x, - const double y, - const double z) { - return -0.8*x*z + 0.2*y*y; - } // point_force_3d_y - - static - double point_force_3d_z(const double x, - const double y, - const double z) { - return -0.3*x*x + 0.5*y*z; - } // point_force_3d_z - - static - double time_delay_3d(const double x, - const double y, - const double z) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); - } // time_delay - -}; - -// ------------------------------------------------------------------------------------------------ -TEST_CASE("TestAuxiliaryFactoryPointForce::Tri::testAdd", "[TestAuxiliaryFactoryPointForce][add]") { - pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryPointForce::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryPointForce][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri()).testSetValuesFromDB(); -} - -TEST_CASE("TestAuxiliaryFactoryPointForce::Hex::testAdd", "[TestAuxiliaryFactoryPointForce][add]") { - pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryPointForce::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryPointForce][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryPointForce(pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex()).testSetValuesFromDB(); -} - -// -------------------------------------------------------------------------------------------------------------------- -pylith::sources::TestAuxiliaryFactoryPointForce_Data* -pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Tri(void) { - pylith::sources::TestAuxiliaryFactoryPointForce_Data* data = new pylith::sources::TestAuxiliaryFactoryPointForce_Data(); - assert(data); - - data->auxDim = 2; - data->dimension = 2; - data->meshFilename = "data/tri_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("point_force_x", point_force_2d_x, point_force_units()); - data->auxiliaryDB->addValue("point_force_y", point_force_2d_y, point_force_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Tri - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryPointForce_Data* -pylith::sources::TestAuxiliaryFactoryPointForce_Cases::Hex(void) { - pylith::sources::TestAuxiliaryFactoryPointForce_Data* data = new pylith::sources::TestAuxiliaryFactoryPointForce_Data(); - assert(data); - - data->auxDim = 3; - data->dimension = 3; - data->meshFilename = "data/hex_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("point_force_x", point_force_3d_x, point_force_units()); - data->auxiliaryDB->addValue("point_force_y", point_force_3d_y, point_force_units()); - data->auxiliaryDB->addValue("point_force_z", point_force_3d_z, point_force_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Hex diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc deleted file mode 100644 index f4111e96d6..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.cc +++ /dev/null @@ -1,372 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryWellboreSource.hh" // Implementation of class methods - -#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // Test subject -#include "tests/src/FieldTester.hh" // USES FieldTester - -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/MeshOps.hh" // USES MeshOps -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t - -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -// ------------------------------------------------------------------------------------------------ -// Constructor. -pylith::sources::TestAuxiliaryFactoryWellboreSource::TestAuxiliaryFactoryWellboreSource(TestAuxiliaryFactoryWellboreSource_Data* data) : - _data(data) { - PYLITH_METHOD_BEGIN; - - assert(_data->normalizer); - _data->normalizer->setLengthScale(1.0e+03); - _data->normalizer->setTimeScale(2.0); - _data->normalizer->setDensityScale(3.0e+3); - _data->normalizer->setPressureScale(2.25e+10); - - pylith::topology::Field::SubfieldInfo info; - pylith::string_vector componentNames; - - // fluid_density - componentNames.resize(1); - componentNames[0] = "fluid_density"; - info.description = pylith::topology::Field::Description( - "fluid_density", - "fluid_density", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getDensityScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["fluid_density"] = info; - - // fluid_viscosity - componentNames.resize(1); - componentNames[0] = "fluid_viscosity"; - info.description = pylith::topology::Field::Description( - "fluid_viscosity", - "fluid_viscosity", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getPressureScale() * _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["fluid_viscosity"] = info; - - // isotropic_permeability - componentNames.resize(1); - componentNames[0] = "isotropic_permeability"; - info.description = pylith::topology::Field::Description( - "isotropic_permeability", - "isotropic_permeability", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getLengthScale() * _data->normalizer->getLengthScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["isotropic_permeability"] = info; - - // wellbore_radius - componentNames.resize(1); - componentNames[0] = "wellbore_radius"; - info.description = pylith::topology::Field::Description( - "wellbore_radius", - "wellbore_radius", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getLengthScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["wellbore_radius"] = info; - - // wellbore_length - componentNames.resize(1); - componentNames[0] = "wellbore_length"; - info.description = pylith::topology::Field::Description( - "wellbore_length", - "wellbore_length", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getLengthScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["wellbore_length"] = info; - - // wellbore_pressure - componentNames.resize(1); - componentNames[0] = "wellbore_pressure"; - info.description = pylith::topology::Field::Description( - "wellbore_pressure", - "wellbore_pressure", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getPressureScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["wellbore_pressure"] = info; - - // wellbore_character - componentNames.resize(1); - componentNames[0] = "wellbore_character"; - info.description = pylith::topology::Field::Description( - "wellbore_character", - "wellbore_character", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - 1, - NULL - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 0; - _data->subfields["wellbore_character"] = info; - - // element_dimensions - componentNames.resize(3); - componentNames[0] = "element_dimensions_x"; - componentNames[1] = "element_dimensions_y"; - componentNames[2] = "element_dimensions_z"; - - info.description = pylith::topology::Field::Description( - "element_dimensions", - "element_dimensions", - componentNames, - componentNames.size(), - pylith::topology::Field::TENSOR, - _data->normalizer->getLengthScale(), - pylith::topology::FieldQuery::validatorPositive - ); - info.fe = pylith::topology::Field::Discretization( - 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false - ); - info.index = 0; - _data->subfields["element_dimensions"] = info; - if (2 == _data->auxDim) { - _data->subfields["element_dimensions"].description.numComponents = 2; - _data->subfields["element_dimensions"].description.vectorFieldType = pylith::topology::Field::OTHER; - } // if - - // timeDelay - componentNames.resize(1); - componentNames[0] = "time_delay"; - info.description = pylith::topology::Field::Description( - "time_delay", - "time_delay", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorNonnegative - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 1; - _data->subfields["time_delay"] = info; - - _initialize(); - - PYLITH_METHOD_END; -} // constructor - - -// ------------------------------------------------------------------------------------------------ -// Destructor. -pylith::sources::TestAuxiliaryFactoryWellboreSource::~TestAuxiliaryFactoryWellboreSource(void) { - PYLITH_METHOD_BEGIN; - - delete _factory;_factory = NULL; - delete _data;_data = NULL; - delete _mesh;_mesh = NULL; - delete _auxiliaryField;_auxiliaryField = NULL; - - PYLITH_METHOD_END; -} // tearDown - - -// ------------------------------------------------------------------------------------------------ -// Test adding moment tensor and time delay subfields. -void -pylith::sources::TestAuxiliaryFactoryWellboreSource::testAdd(void) { - PYLITH_METHOD_BEGIN; - assert(_factory); - assert(_data); - - CHECK(!_auxiliaryField->hasSubfield("fluid_density")); - CHECK(!_auxiliaryField->hasSubfield("fluid_viscosity")); - CHECK(!_auxiliaryField->hasSubfield("isotropic_permeability")); - CHECK(!_auxiliaryField->hasSubfield("wellbore_radius")); - CHECK(!_auxiliaryField->hasSubfield("wellbore_length")); - CHECK(!_auxiliaryField->hasSubfield("wellbore_pressure")); - CHECK(!_auxiliaryField->hasSubfield("wellbore_character")); - CHECK(!_auxiliaryField->hasSubfield("element_dimensions")); - CHECK(!_auxiliaryField->hasSubfield("time_delay")); - - _factory->addFluidDensity(); - _factory->addFluidViscosity(); - _factory->addIsotropicPermeability(); - _factory->addWellboreRadius(); - _factory->addWellboreLength(); - _factory->addWellboreCharacter(); - _factory->addElementDimensions(); - _factory->addTimeDelay(); - - assert(_data->normalizer); - - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["fluid_density"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["fluid_viscosity"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["isotropic_permeability"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_radius"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_length"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_pressure"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["wellbore_character"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["element_dimensions"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); - - PYLITH_METHOD_END; -} // testAdd - - -// ------------------------------------------------------------------------------------------------ -// Test setValues(). -void -pylith::sources::TestAuxiliaryFactoryWellboreSource::testSetValuesFromDB(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - - _factory->addFluidDensity(); - _factory->addFluidViscosity(); - _factory->addIsotropicPermeability(); - _factory->addWellboreRadius(); - _factory->addWellboreLength(); - _factory->addWellborePressure(); - _factory->addWellboreCharacter(); - _factory->addElementDimensions(); - _factory->addTimeDelay(); - _auxiliaryField->subfieldsSetup(); - _auxiliaryField->createDiscretization(); - _auxiliaryField->allocate(); - - assert(_data); - assert(_data->normalizer); - _factory->setValuesFromDB(); - pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testSetValues - - -// ------------------------------------------------------------------------------------------------ -// Initialze mesh, coordinate system, auxiliary field, and factory. -void -pylith::sources::TestAuxiliaryFactoryWellboreSource::_initialize(void) { - PYLITH_METHOD_BEGIN; - assert(_data); - - pylith::meshio::MeshIOAscii iohandler; - assert(_data->meshFilename); - iohandler.setFilename(_data->meshFilename); - _mesh = new pylith::topology::Mesh();assert(_mesh); - iohandler.read(_mesh); - - assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); - assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); - - // Setup coordinates. - _mesh->setCoordSys(_data->cs); - assert(_data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); - - _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); - _auxiliaryField->setLabel("auxiliary"); - - _factory = new AuxiliaryFactoryWellboreSource(); - assert(_data->auxiliaryDB); - _factory->setQueryDB(_data->auxiliaryDB); - typedef std::map::const_iterator subfield_iter; - for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { - const char* subfieldName = iter->first.c_str(); - const pylith::topology::Field::Discretization& fe = iter->second.fe; - _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, - fe.feSpace, fe.isBasisContinuous); - } // for - assert(_data->normalizer); - _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); - - PYLITH_METHOD_END; -} // _initialize - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::TestAuxiliaryFactoryWellboreSource_Data(void) : - meshFilename(NULL), - cs(NULL), - normalizer(new spatialdata::units::Nondimensional), - auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data::~TestAuxiliaryFactoryWellboreSource_Data(void) { - delete cs;cs = NULL; - delete normalizer;normalizer = NULL; - delete auxiliaryDB;auxiliaryDB = NULL; -} // testAdd diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh deleted file mode 100644 index efe8897499..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh +++ /dev/null @@ -1,110 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// Robert L. Walker, Kegman, Inc. -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** - * @file tests/libtests/sources/TestAuxiliaryFactoryWellboreSource.hh - * - * @brief C++ TestAuxiliaryFactoryWellboreSource object. - * - * C++ unit testing for AuxiliaryFactoryWellboreSource. - */ - -#if !defined(pylith_sources_testauxiliaryfactorywellboresource_hh) -#define pylith_sources_testauxiliaryfactorywellboresource_hh - -#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent - -#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryWellboreSource -#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo -#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB -#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys -#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional - -#include // USES std::map - -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryWellboreSource; - class TestAuxiliaryFactoryWellboreSource_Data; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryWellboreSource : public pylith::utils::GenericComponent { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor. - TestAuxiliaryFactoryWellboreSource(TestAuxiliaryFactoryWellboreSource_Data* data); - - /// Destructor. - ~TestAuxiliaryFactoryWellboreSource(void); - - /// Test adding density, body force, and gravity subfields. - void testAdd(void); - - /// Test setValuesFromDB(). - void testSetValuesFromDB(void); - - // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// -protected: - - /// Initialze mesh, coordinate system, auxiliary field, and factory. - void _initialize(void); - - // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// -protected: - - AuxiliaryFactoryWellboreSource* _factory; ///< Test subject. - TestAuxiliaryFactoryWellboreSource_Data* _data; ///< Test data. - - pylith::topology::Mesh* _mesh; ///< Finite-element mesh. - pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. - -}; // class TestAuxiliaryFactoryWellboreSource - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryWellboreSource_Data { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor - TestAuxiliaryFactoryWellboreSource_Data(void); - - /// Destructor - ~TestAuxiliaryFactoryWellboreSource_Data(void); - - // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// -public: - - size_t dimension; ///< Spatial dimension. - size_t auxDim; ///< Topological dimension of auxiliary field. - const char* meshFilename; ///< Name of file with ASCII mesh. - spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. - spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. - - std::map subfields; - spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. - -}; // class TestAuxiliaryFactoryWellboreSource_Data - -#endif // pylith_sources_testAuxiliaryFactoryWellboreSource_hh - -// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc deleted file mode 100644 index 617e1ef8e5..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryWellboreSource_Cases.cc +++ /dev/null @@ -1,258 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryWellboreSource.hh" // Implementation of cases - -#include "pylith/sources/AuxiliaryFactoryWellboreSource.hh" // USES AuxiliaryFactoryWellboreSource -#include "spatialdata/geocoords/CSCart.hh" // USES CSCart -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -#include // USES fabs() - -// forward declarations -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryWellboreSource_Cases; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases { -public: - - // Data factory methods - static TestAuxiliaryFactoryWellboreSource_Data* Tri(void); - - static TestAuxiliaryFactoryWellboreSource_Data* Hex(void); - -private: - - static - double fluid_density_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // fluid_density_2d - - static - const char* fluid_density_units(void) { - return "kg/m**3"; - } // fluid_density_units - - static - double fluid_viscosity_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // fluid_viscosity_2d - - static - const char* fluid_viscosity_units(void) { - return "Pa*s"; - } // fluid_viscosity_units - - static - double isotropic_permeability_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // isotropic_permeability_2d - - static - const char* isotropic_permeability_units(void) { - return "m**2"; - } // isotropic_permeability_units - - static - double wellbore_radius_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_radius_2d - - static - const char* wellbore_radius_units(void) { - return "m"; - } // wellbore_radius_units - - static - double wellbore_length_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_length_2d - - static - const char* wellbore_length_units(void) { - return "m"; - } // wellbore_length_units - - static - double wellbore_pressure_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_pressure_2d - - static - const char* wellbore_pressure_units(void) { - return "Pa"; - } // wellbore_pressure_units - - static - double wellbore_character_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_character_2d - - static - const char* wellbore_character_units(void) { - return "one"; - } // wellbore_character_units - - static - double time_delay_2d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // time_delay_2d - - static - const char* time_delay_units(void) { - return "s"; - } // time_delay_units - - static - double fluid_density_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // fluid_density_3d - - static - double fluid_viscosity_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // fluid_viscosity_3d - - static - double isotropic_permeability_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // isotropic_permeability_3d - - static - double wellbore_radius_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_radius_3d - - static - double wellbore_length_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_length_3d - - static - double wellbore_pressure_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_pressure_3d - - static - double wellbore_character_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // wellbore_character_2d - - static - double time_delay_3d(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // time_delay_3d - -}; - -// ------------------------------------------------------------------------------------------------ -TEST_CASE("TestAuxiliaryFactoryWellboreSource::Tri::testAdd", "[TestAuxiliaryFactoryWellboreSource][add]") { - pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryWellboreSource::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryWellboreSource][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri()).testSetValuesFromDB(); -} - -TEST_CASE("TestAuxiliaryFactoryWellboreSource::Hex::testAdd", "[TestAuxiliaryFactoryWellboreSource][add]") { - pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryWellboreSource::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryWellboreSource][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryWellboreSource(pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex()).testSetValuesFromDB(); -} - -// -------------------------------------------------------------------------------------------------------------------- -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* -pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Tri(void) { - pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* data = new pylith::sources::TestAuxiliaryFactoryWellboreSource_Data(); - assert(data); - - data->auxDim = 2; - data->dimension = 2; - data->meshFilename = "data/tri_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("fluid_density", fluid_density_2d, fluid_density_units()); - data->auxiliaryDB->addValue("fluid_viscosity", fluid_viscosity_2d, fluid_viscosity_units()); - data->auxiliaryDB->addValue("isotropic_permeability", isotropic_permeability_2d, isotropic_permeability_units()); - data->auxiliaryDB->addValue("wellbore_radius", wellbore_radius_2d, wellbore_radius_units()); - data->auxiliaryDB->addValue("wellbore_length", wellbore_length_2d, wellbore_length_units()); - data->auxiliaryDB->addValue("wellbore_pressure", wellbore_pressure_2d, wellbore_pressure_units()); - data->auxiliaryDB->addValue("wellbore_character", wellbore_character_2d, wellbore_character_units radius_units()); - data->auxiliaryDB->addValue("element_dimensions", element_dimensions_2d, element_dimensions_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Tri - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* -pylith::sources::TestAuxiliaryFactoryWellboreSource_Cases::Hex(void) { - pylith::sources::TestAuxiliaryFactoryWellboreSource_Data* data = new pylith::sources::TestAuxiliaryFactoryWellboreSource_Data(); - assert(data); - - data->auxDim = 3; - data->dimension = 3; - data->meshFilename = "data/hex_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("fluid_density", fluid_density_3d, fluid_density_units()); - data->auxiliaryDB->addValue("fluid_viscosity", fluid_viscosity_3d, fluid_viscosity_units()); - data->auxiliaryDB->addValue("isotropic_permeability", isotropic_permeability_3d, isotropic_permeability_units()); - data->auxiliaryDB->addValue("wellbore_radius", wellbore_radius_3d, wellbore_radius_units()); - data->auxiliaryDB->addValue("wellbore_length", wellbore_length_3d, wellbore_length_units()); - data->auxiliaryDB->addValue("wellbore_pressure", wellbore_pressure_3d, wellbore_pressure_units()); - data->auxiliaryDB->addValue("wellbore_character", wellbore_character_3d, wellbore_character_units radius_units()); - data->auxiliaryDB->addValue("element_dimensions", element_dimensions_3d, element_dimensions_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Hex From 875856d344a193b07791d482dbae73229f449831 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 16:26:06 -0600 Subject: [PATCH 55/65] Added makefile back --- tests/libtests/sources/Makefile.am | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/libtests/sources/Makefile.am diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am new file mode 100644 index 0000000000..151014e900 --- /dev/null +++ b/tests/libtests/sources/Makefile.am @@ -0,0 +1,45 @@ +# -*- Makefile -*- +# +# ---------------------------------------------------------------------- +# +# Brad T. Aagaard, U.S. Geological Survey +# Charles A. Williams, GNS Science +# Matthew G. Knepley, University at Buffalo +# +# This code was developed as part of the Computational Infrastructure +# for Geodynamics (http://geodynamics.org). +# +# Copyright (c) 2010-2022 University of California, Davis +# +# See LICENSE.md for license information. +# +# ---------------------------------------------------------------------- +# + +include $(top_srcdir)/tests/check_catch2.am + +SUBDIRS = data + +TESTS = libtest_sources + +check_PROGRAMS = $(TESTS) + + +libtest_sources_SOURCES = \ + TestAuxiliaryFactoryMomentTensorForce.cc \ + TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ + TestAuxiliaryFactorySourceTime.cc \ + TestAuxiliaryFactorySourceTime_Cases.cc \ + TestAuxiliaryFactoryPointForce.cc \ + TestAuxiliaryFactoryPointForce_Cases.cc \ + $(top_srcdir)/tests/src/FieldTester.cc \ + $(top_srcdir)/tests/src/driver_catch2.cc + + +dist_noinst_HEADERS = \ + TestAuxiliaryFactoryMomentTensorForce.hh \ + TestAuxiliaryFactorySourceTime.hh \ + TestAuxiliaryFactoryPointForce.hh + + +# End of file From 57fdecc62fcf00be864503f9fae6eaa45cfcd258 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 16:38:23 -0600 Subject: [PATCH 56/65] Removed vestigal parts of test makefile --- tests/libtests/sources/Makefile.am | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am index 151014e900..d286830194 100644 --- a/tests/libtests/sources/Makefile.am +++ b/tests/libtests/sources/Makefile.am @@ -30,8 +30,6 @@ libtest_sources_SOURCES = \ TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ TestAuxiliaryFactorySourceTime.cc \ TestAuxiliaryFactorySourceTime_Cases.cc \ - TestAuxiliaryFactoryPointForce.cc \ - TestAuxiliaryFactoryPointForce_Cases.cc \ $(top_srcdir)/tests/src/FieldTester.cc \ $(top_srcdir)/tests/src/driver_catch2.cc @@ -39,7 +37,6 @@ libtest_sources_SOURCES = \ dist_noinst_HEADERS = \ TestAuxiliaryFactoryMomentTensorForce.hh \ TestAuxiliaryFactorySourceTime.hh \ - TestAuxiliaryFactoryPointForce.hh # End of file From 6568888637f79b62736373aa628f6d4255e152ff Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 16:46:32 -0600 Subject: [PATCH 57/65] just removing source tests --- m4 | 2 +- tests/libtests/sources/Makefile.am | 42 ------------------------------ 2 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 tests/libtests/sources/Makefile.am diff --git a/m4 b/m4 index 44921313d4..e490e14fb1 160000 --- a/m4 +++ b/m4 @@ -1 +1 @@ -Subproject commit 44921313d4127dcddaafd6ca45cccb7744793bf0 +Subproject commit e490e14fb13595428d39055304bcf0ee7ab94806 diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am deleted file mode 100644 index d286830194..0000000000 --- a/tests/libtests/sources/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# -*- Makefile -*- -# -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2022 University of California, Davis -# -# See LICENSE.md for license information. -# -# ---------------------------------------------------------------------- -# - -include $(top_srcdir)/tests/check_catch2.am - -SUBDIRS = data - -TESTS = libtest_sources - -check_PROGRAMS = $(TESTS) - - -libtest_sources_SOURCES = \ - TestAuxiliaryFactoryMomentTensorForce.cc \ - TestAuxiliaryFactoryMomentTensorForce_Cases.cc \ - TestAuxiliaryFactorySourceTime.cc \ - TestAuxiliaryFactorySourceTime_Cases.cc \ - $(top_srcdir)/tests/src/FieldTester.cc \ - $(top_srcdir)/tests/src/driver_catch2.cc - - -dist_noinst_HEADERS = \ - TestAuxiliaryFactoryMomentTensorForce.hh \ - TestAuxiliaryFactorySourceTime.hh \ - - -# End of file From 4493475e3fe1978ebfa94917d39a2d5c50289454 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Fri, 6 Jun 2025 16:48:27 -0600 Subject: [PATCH 58/65] Just removing source tests --- .../TestAuxiliaryFactoryMomentTensorForce.cc | 220 ----- .../TestAuxiliaryFactoryMomentTensorForce.hh | 109 --- ...AuxiliaryFactoryMomentTensorForce_Cases.cc | 205 ----- .../sources/TestAuxiliaryFactorySourceTime.cc | 243 ------ .../sources/TestAuxiliaryFactorySourceTime.hh | 110 --- .../TestAuxiliaryFactorySourceTime_Cases.cc | 225 ----- tests/libtests/sources/TestSource.cc | 781 ------------------ tests/libtests/sources/TestSource.hh | 211 ----- tests/libtests/sources/data/Makefile.am | 29 - tests/libtests/sources/data/hex_onecell.mesh | 37 - tests/libtests/sources/data/tri_onecell.mesh | 32 - 11 files changed, 2202 deletions(-) delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh delete mode 100644 tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc delete mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh delete mode 100644 tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc delete mode 100644 tests/libtests/sources/TestSource.cc delete mode 100644 tests/libtests/sources/TestSource.hh delete mode 100644 tests/libtests/sources/data/Makefile.am delete mode 100644 tests/libtests/sources/data/hex_onecell.mesh delete mode 100644 tests/libtests/sources/data/tri_onecell.mesh diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc deleted file mode 100644 index 35f948f970..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.cc +++ /dev/null @@ -1,220 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// Robert L. Walker, Kegman, Inc. -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryMomentTensorForce.hh" // Implementation of class methods - -#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // Test subject -#include "tests/src/FieldTester.hh" // USES FieldTester - -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/MeshOps.hh" // USES MeshOps -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_* - -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -// ------------------------------------------------------------------------------------------------ -// Constructor. -pylith::sources::TestAuxiliaryFactoryMomentTensorForce::TestAuxiliaryFactoryMomentTensorForce(TestAuxiliaryFactoryMomentTensorForce_Data* data) : - _data(data) { - PYLITH_METHOD_BEGIN; - - assert(_data->normalizer); - _data->normalizer->setLengthScale(1.0e+03); - _data->normalizer->setTimeScale(2.0); - _data->normalizer->setDensityScale(3.0e+3); - _data->normalizer->setPressureScale(2.25e+10); - - pylith::topology::Field::SubfieldInfo info; - pylith::string_vector componentNames; - - // momentTensor - componentNames.resize(6); - componentNames[0] = "moment_tensor_xx"; - componentNames[1] = "moment_tensor_yy"; - componentNames[2] = "moment_tensor_zz"; - componentNames[3] = "moment_tensor_xy"; - componentNames[4] = "moment_tensor_yz"; - componentNames[5] = "moment_tensor_xz"; - - info.description = pylith::topology::Field::Description( - "moment_tensor", - "moment_tensor", - componentNames, - componentNames.size(), - pylith::topology::Field::TENSOR, - _data->normalizer->getPressureScale() * normalizer->getLengthScale() * normalizer->getLengthScale() * normalizer->getLengthScale(); - ); - info.fe = pylith::topology::Field::Discretization( - 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false - ); - info.index = 0; - _data->subfields["moment_tensor"] = info; - if (2 == _data->auxDim) { - _data->subfields["moment_tensor"].description.numComponents = 4; - _data->subfields["moment_tensor"].description.vectorFieldType = pylith::topology::Field::OTHER; - } // if - - // timeDelay - componentNames.resize(1); - componentNames[0] = "time_delay"; - info.description = pylith::topology::Field::Description( - "time_delay", - "time_delay", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorNonnegative - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 1; - _data->subfields["time_delay"] = info; - - _initialize(); - - PYLITH_METHOD_END; -} // constructor - - -// ------------------------------------------------------------------------------------------------ -// Destructor. -pylith::sources::TestAuxiliaryFactoryMomentTensorForce::~TestAuxiliaryFactoryMomentTensorForce(void) { - PYLITH_METHOD_BEGIN; - - delete _factory;_factory = NULL; - delete _data;_data = NULL; - delete _mesh;_mesh = NULL; - delete _auxiliaryField;_auxiliaryField = NULL; - - PYLITH_METHOD_END; -} // tearDown - - -// ------------------------------------------------------------------------------------------------ -// Test adding moment tensor and time delay subfields. -void -pylith::sources::TestAuxiliaryFactoryMomentTensorForce::testAdd(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - assert(_data); - - CHECK(!_auxiliaryField->hasSubfield("moment_tensor")); - CHECK(!_auxiliaryField->hasSubfield("time_delay")); - - _factory->addMomentTensor(); - _factory->addTimeDelay(); - - assert(_data->normalizer); - - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["moment_tensor"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); - - PYLITH_METHOD_END; -} // testAdd - - -// ------------------------------------------------------------------------------------------------ -// Test setValues(). -void -pylith::sources::TestAuxiliaryFactoryMomentTensorForce::testSetValuesFromDB(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - - _factory->addMomentTensor(); - _factory->addTimeDelay(); - _auxiliaryField->subfieldsSetup(); - _auxiliaryField->createDiscretization(); - _auxiliaryField->allocate(); - - assert(_data); - assert(_data->normalizer); - _factory->setValuesFromDB(); - pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testSetValues - - -// ------------------------------------------------------------------------------------------------ -// Initialze mesh, coordinate system, auxiliary field, and factory. -void -pylith::sources::TestAuxiliaryFactoryMomentTensorForce::_initialize(void) { - PYLITH_METHOD_BEGIN; - assert(_data); - - pylith::meshio::MeshIOAscii iohandler; - assert(_data->meshFilename); - iohandler.setFilename(_data->meshFilename); - _mesh = new pylith::topology::Mesh();assert(_mesh); - iohandler.read(_mesh); - - assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); - assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); - - // Setup coordinates. - _mesh->setCoordSys(_data->cs); - assert(_data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); - - _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); - _auxiliaryField->setLabel("auxiliary"); - - _factory = new AuxiliaryFactoryMomentTensorForce(); - assert(_data->auxiliaryDB); - _factory->setQueryDB(_data->auxiliaryDB); - typedef std::map::const_iterator subfield_iter; - for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { - const char* subfieldName = iter->first.c_str(); - const pylith::topology::Field::Discretization& fe = iter->second.fe; - _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, - fe.feSpace, fe.isBasisContinuous); - } // for - assert(_data->normalizer); - _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); - - PYLITH_METHOD_END; -} // _initialize - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data::TestAuxiliaryFactoryMomentTensorForce_Data(void) : - meshFilename(NULL), - cs(NULL), - normalizer(new spatialdata::units::Nondimensional), - auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data::~TestAuxiliaryFactoryMomentTensorForce_Data(void) { - delete cs;cs = NULL; - delete normalizer;normalizer = NULL; - delete auxiliaryDB;auxiliaryDB = NULL; -} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh deleted file mode 100644 index 795dcc090f..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh +++ /dev/null @@ -1,109 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// Robert L. Walker, Kegman, Inc. -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** - * @file tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce.hh - * - * @brief C++ TestAuxiliaryFactoryMomentTensorForce object. - * - * C++ unit testing for AuxiliaryFactoryMomentTensorForce. - */ - -#if !defined(pylith_sources_testauxiliaryfactorymomenttensorforce_hh) -#define pylith_sources_testauxiliaryfactorymomenttensorforce_hh - -#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent - -#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactoryMomentTensorForce -#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo -#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB -#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys -#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional - -#include // USES std::map - -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryMomentTensorForce; - class TestAuxiliaryFactoryMomentTensorForce_Data; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryMomentTensorForce : public pylith::utils::GenericComponent { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor. - TestAuxiliaryFactoryMomentTensorForce(TestAuxiliaryFactoryMomentTensorForce_Data* data); - - /// Destructor. - ~TestAuxiliaryFactoryMomentTensorForce(void); - - /// Test adding density, body force, and gravity subfields. - void testAdd(void); - - /// Test setValuesFromDB(). - void testSetValuesFromDB(void); - - // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// -protected: - - /// Initialze mesh, coordinate system, auxiliary field, and factory. - void _initialize(void); - - // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// -protected: - - AuxiliaryFactoryMomentTensorForce* _factory; ///< Test subject. - TestAuxiliaryFactoryMomentTensorForce_Data* _data; ///< Test data. - - pylith::topology::Mesh* _mesh; ///< Finite-element mesh. - pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. - -}; // class TestAuxiliaryFactoryMomentTensorForce - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor - TestAuxiliaryFactoryMomentTensorForce_Data(void); - - /// Destructor - ~TestAuxiliaryFactoryMomentTensorForce_Data(void); - - // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// -public: - - size_t dimension; ///< Spatial dimension. - size_t auxDim; ///< Topological dimension of auxiliary field. - const char* meshFilename; ///< Name of file with ASCII mesh. - spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. - spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. - - std::map subfields; - spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - -}; // class TestAuxiliaryFactoryMomentTensorForce_Data - -#endif // pylith_sources_testAuxiliaryFactoryMomentTensorForce_hh - -// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc deleted file mode 100644 index aa0de17b7a..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactoryMomentTensorForce_Cases.cc +++ /dev/null @@ -1,205 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactoryMomentTensorForce.hh" // Implementation of cases - -#include "pylith/sources/AuxiliaryFactoryMomentTensorForce.hh" // USES AuxiliaryFactoryMomentTensorForce -#include "spatialdata/geocoords/CSCart.hh" // USES CSCart -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -#include // USES fabs() - -// forward declarations -namespace pylith { - namespace sources { - class TestAuxiliaryFactoryMomentTensorForce_Cases; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases { -public: - - // Data factory methods - static TestAuxiliaryFactoryMomentTensorForce_Data* Tri(void); - - static TestAuxiliaryFactoryMomentTensorForce_Data* Hex(void); - -private: - - static - double moment_tensor_2d_xx(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // moment_tensor_2d_xx - - static - double moment_tensor_2d_yy(const double x, - const double y) { - return -0.8*x*y + 0.2*y*y; - } // moment_tensor_2d_yy - - static - double moment_tensor_2d_zz(const double x, - const double y) { - return -0.3*x*x + 0.5*y*y; - } // moment_tensor_2d_zz - - static - double moment_tensor_2d_xy(const double x, - const double y) { - return -0.3*x*x + 0.3*x*y; - } - - static - const char* moment_tensor_units(void) { - return "Pa"; - } // moment_tensor_units - - static - double time_delay_2d(const double x, - const double y) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); - } // time_delay - - static - const char* time_units(void) { - return "s"; - } // time_units - - static - double moment_tensor_3d_xx(const double x, - const double y, - const double z) { - return -0.3*x*z + 0.1*x*z; - } // moment_tensor_3d_xx - - static - double moment_tensor_3d_yy(const double x, - const double y, - const double z) { - return -0.8*x*z + 0.2*y*y; - } // moment_tensor_3d_yy - - static - double moment_tensor_3d_zz(const double x, - const double y, - const double z) { - return -0.3*x*x + 0.5*y*z; - } // moment_tensor_3d_zz - - static - double moment_tensor_3d_xy(const double x, - const double y, - const double z) { - return -0.3*x + 0.2*x*y; - } // moment_tensor_3d_xy - - static - double moment_tensor_3d_yz(const double x, - const double y, - const double z) { - return -0.3*x*z + 0.2*x*y; - } // moment_tensor_3d_yz - - static - double moment_tensor_3d_xz(const double x, - const double y, - const double z) { - return -0.3*x + 0.2*y; - } // moment_tensor_3d_xz - - static - double time_delay_3d(const double x, - const double y, - const double z) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); - } // time_delay - -}; - -// ------------------------------------------------------------------------------------------------ -TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Tri::testAdd", "[TestAuxiliaryFactoryMomentTensorForce][add]") { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Tri::testSetValuesFromDB", "[TestAuxiliaryFactoryMomentTensorForce][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri()).testSetValuesFromDB(); -} - -TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Hex::testAdd", "[TestAuxiliaryFactoryMomentTensorForce][add]") { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactoryMomentTensorForce::Hex::testSetValuesFromDB", "[TestAuxiliaryFactoryMomentTensorForce][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce(pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex()).testSetValuesFromDB(); -} - -// -------------------------------------------------------------------------------------------------------------------- -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Tri(void) { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* data = new pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data(); - assert(data); - - data->auxDim = 2; - data->dimension = 2; - data->meshFilename = "data/tri_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, moment_tensor_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Tri - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* -pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Cases::Hex(void) { - pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data* data = new pylith::sources::TestAuxiliaryFactoryMomentTensorForce_Data(); - assert(data); - - data->auxDim = 3; - data->dimension = 3; - data->meshFilename = "data/hex_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, moment_tensor_units()); - data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, moment_tensor_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Hex diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc deleted file mode 100644 index b45fb3ee43..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.cc +++ /dev/null @@ -1,243 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of class methods - -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // Test subject -#include "tests/src/FieldTester.hh" // USES FieldTester - -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/MeshOps.hh" // USES MeshOps -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii - -#include "pylith/utils/error.hh" // USES PYLITH_METHOD* -#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t - -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -// ------------------------------------------------------------------------------------------------ -// Constructor. -pylith::sources::TestAuxiliaryFactorySourceTime::TestAuxiliaryFactorySourceTime(TestAuxiliaryFactorySourceTime_Data* data) : - _data(data) { - PYLITH_METHOD_BEGIN; - - assert(_data->normalizer); - _data->normalizer->setLengthScale(1.0e+03); - _data->normalizer->setTimeScale(2.0); - _data->normalizer->setDensityScale(3.0e+3); - _data->normalizer->setPressureScale(2.25e+10); - - pylith::topology::Field::SubfieldInfo info; - pylith::string_vector componentNames; - - // momentTensor - componentNames.resize(6); - componentNames[0] = "moment_tensor_xx"; - componentNames[1] = "moment_tensor_yy"; - componentNames[2] = "moment_tensor_zz"; - componentNames[3] = "moment_tensor_xy"; - componentNames[4] = "moment_tensor_yz"; - componentNames[5] = "moment_tensor_xz"; - - info.description = pylith::topology::Field::Description( - "moment_tensor", - "moment_tensor", - componentNames, - componentNames.size(), - pylith::topology::Field::TENSOR, - _data->normalizer->getPressureScale() - ); - info.fe = pylith::topology::Field::Discretization( - 2, 2, _data->auxDim, _data->auxDim, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, false - ); - info.index = 0; - _data->subfields["moment_tensor"] = info; - if (2 == _data->auxDim) { - _data->subfields["moment_tensor"].description.numComponents = 4; - _data->subfields["moment_tensor"].description.vectorFieldType = pylith::topology::Field::OTHER; - } // if - - // timeDelay - componentNames.resize(1); - componentNames[0] = "time_delay"; - info.description = pylith::topology::Field::Description( - "time_delay", - "time_delay", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorNonnegative - ); - info.fe = pylith::topology::Field::Discretization( - 1, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 1; - _data->subfields["time_delay"] = info; - - // centerFrequency - componentNames.resize(1); - componentNames[0] = "center_frequency"; - info.description = pylith::topology::Field::Description( - "center_frequency", - "center_frequency", - componentNames, - componentNames.size(), - pylith::topology::Field::SCALAR, - 1.0 / _data->normalizer->getTimeScale(), - pylith::topology::FieldQuery::validatorNonnegative - ); - info.fe = pylith::topology::Field::Discretization( - 2, 2, _data->auxDim, 1, false, pylith::topology::Field::DEFAULT_BASIS, pylith::topology::Field::POLYNOMIAL_SPACE, true - ); - info.index = 2; - _data->subfields["center_frequency"] = info; - - _initialize(); - - PYLITH_METHOD_END; -} // constructor - - -// ------------------------------------------------------------------------------------------------ -// Destructor. -pylith::sources::TestAuxiliaryFactorySourceTime::~TestAuxiliaryFactorySourceTime(void) { - PYLITH_METHOD_BEGIN; - - delete _factory;_factory = NULL; - delete _data;_data = NULL; - delete _mesh;_mesh = NULL; - delete _auxiliaryField;_auxiliaryField = NULL; - - PYLITH_METHOD_END; -} // tearDown - - -// ------------------------------------------------------------------------------------------------ -// Test adding moment tensor and time delay subfields. -void -pylith::sources::TestAuxiliaryFactorySourceTime::testAdd(void) { - PYLITH_METHOD_BEGIN; - assert(_factory); - assert(_data); - - CHECK(!_auxiliaryField->hasSubfield("moment_tensor")); - CHECK(!_auxiliaryField->hasSubfield("time_delay")); - CHECK(!_auxiliaryField->hasSubfield("center_frequency")); - - _factory->addMomentTensor(); - _factory->addTimeDelay(); - _factory->addCenterFrequency(); - - assert(_data->normalizer); - - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["moment_tensor"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["time_delay"]); - pylith::testing::FieldTester::checkSubfieldInfo(*_auxiliaryField, _data->subfields["center_frequency"]); - - PYLITH_METHOD_END; -} // testAdd - - -// ------------------------------------------------------------------------------------------------ -// Test setValues(). -void -pylith::sources::TestAuxiliaryFactorySourceTime::testSetValuesFromDB(void) { - PYLITH_METHOD_BEGIN; - - assert(_factory); - - _factory->addMomentTensor(); - _factory->addTimeDelay(); - _factory->addCenterFrequency(); - _auxiliaryField->subfieldsSetup(); - _auxiliaryField->createDiscretization(); - _auxiliaryField->allocate(); - - assert(_data); - assert(_data->normalizer); - _factory->setValuesFromDB(); - pylith::testing::FieldTester::checkFieldWithDB(*_auxiliaryField, _data->auxiliaryDB, _data->normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testSetValues - - -// ------------------------------------------------------------------------------------------------ -// Initialze mesh, coordinate system, auxiliary field, and factory. -void -pylith::sources::TestAuxiliaryFactorySourceTime::_initialize(void) { - PYLITH_METHOD_BEGIN; - assert(_data); - - pylith::meshio::MeshIOAscii iohandler; - assert(_data->meshFilename); - iohandler.setFilename(_data->meshFilename); - _mesh = new pylith::topology::Mesh();assert(_mesh); - iohandler.read(_mesh); - - assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); - assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); - - // Setup coordinates. - _mesh->setCoordSys(_data->cs); - assert(_data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *_data->normalizer); - - _auxiliaryField = new pylith::topology::Field(*_mesh);assert(_auxiliaryField); - _auxiliaryField->setLabel("auxiliary"); - - _factory = new AuxiliaryFactorySourceTime(); - assert(_data->auxiliaryDB); - _factory->setQueryDB(_data->auxiliaryDB); - typedef std::map::const_iterator subfield_iter; - for (subfield_iter iter = _data->subfields.begin(); iter != _data->subfields.end(); ++iter) { - const char* subfieldName = iter->first.c_str(); - const pylith::topology::Field::Discretization& fe = iter->second.fe; - _factory->setSubfieldDiscretization(subfieldName, fe.basisOrder, fe.quadOrder, fe.dimension, fe.isFaultOnly, fe.cellBasis, - fe.feSpace, fe.isBasisContinuous); - } // for - assert(_data->normalizer); - _factory->initialize(_auxiliaryField, *_data->normalizer, _data->dimension); - - PYLITH_METHOD_END; -} // _initialize - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactorySourceTime_Data::TestAuxiliaryFactorySourceTime_Data(void) : - meshFilename(NULL), - cs(NULL), - normalizer(new spatialdata::units::Nondimensional), - auxiliaryDB(new spatialdata::spatialdb::UserFunctionDB) {} - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactorySourceTime_Data::~TestAuxiliaryFactorySourceTime_Data(void) { - delete cs;cs = NULL; - delete normalizer;normalizer = NULL; - delete auxiliaryDB;auxiliaryDB = NULL; -} // destructor diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh b/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh deleted file mode 100644 index f442189c9d..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh +++ /dev/null @@ -1,110 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// Robert L. Walker, Kegman, Inc. -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** - * @file tests/libtests/sources/TestAuxiliaryFactorySourceTime.hh - * - * @brief C++ TestAuxiliaryFactorySourceTime object. - * - * C++ unit testing for AuxiliaryFactorySourceTime. - */ - -#if !defined(pylith_sources_testauxiliaryfactorysourcetime_hh) -#define pylith_sources_testauxiliaryfactorysourcetime_hh - -#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent - -#include "pylith/sources/sourcesfwd.hh" // HOLDSA AuxiliaryFactorySourceTime -#include "pylith/topology/Field.hh" // HOLDSA Field::SubfieldInfo -#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA SpatialDB -#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA Coordsys -#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional - -#include // USES std::map - -namespace pylith { - namespace sources { - class TestAuxiliaryFactorySourceTime; - class TestAuxiliaryFactorySourceTime_Data; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactorySourceTime : public pylith::utils::GenericComponent { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor. - TestAuxiliaryFactorySourceTime(TestAuxiliaryFactorySourceTime_Data* data); - - /// Destructor. - ~TestAuxiliaryFactorySourceTime(void); - - /// Test adding density, body force, and gravity subfields. - void testAdd(void); - - /// Test setValuesFromDB(). - void testSetValuesFromDB(void); - - // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// -protected: - - /// Initialze mesh, coordinate system, auxiliary field, and factory. - void _initialize(void); - - // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// -protected: - - AuxiliaryFactorySourceTime* _factory; ///< Test subject. - TestAuxiliaryFactorySourceTime_Data* _data; ///< Test data. - - pylith::topology::Mesh* _mesh; ///< Finite-element mesh. - pylith::topology::Field* _auxiliaryField; ///< Auxiliary field for test subject. - -}; // class TestAuxiliaryFactorySourceTime - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactorySourceTime_Data { - // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// -public: - - /// Constructor - TestAuxiliaryFactorySourceTime_Data(void); - - /// Destructor - ~TestAuxiliaryFactorySourceTime_Data(void); - - // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// -public: - - size_t dimension; ///< Spatial dimension. - size_t auxDim; ///< Topological dimension of auxiliary field. - const char* meshFilename; ///< Name of file with ASCII mesh. - spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. - spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. - - std::map subfields; - spatialdata::spatialdb::UserFunctionDB* auxiliaryDB; ///< Spatial database with values for solution. - spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field spatial database. - -}; // class TestAuxiliaryFactorySourceTime_Data - -#endif // pylith_sources_testAuxiliaryFactorySourceTime_hh - -// End of file diff --git a/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc b/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc deleted file mode 100644 index fb268f0a43..0000000000 --- a/tests/libtests/sources/TestAuxiliaryFactorySourceTime_Cases.cc +++ /dev/null @@ -1,225 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestAuxiliaryFactorySourceTime.hh" // Implementation of cases - -#include "pylith/sources/AuxiliaryFactorySourceTime.hh" // USES AuxiliaryFactorySourceTime -#include "spatialdata/geocoords/CSCart.hh" // USES CSCart -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -#include "catch2/catch_test_macros.hpp" - -#include // USES fabs() - -// forward declarations -namespace pylith { - namespace sources { - class TestAuxiliaryFactorySourceTime_Cases; - } // sources -} // pylith - -// ------------------------------------------------------------------------------------------------ -class pylith::sources::TestAuxiliaryFactorySourceTime_Cases { -public: - - // Data factory methods - static TestAuxiliaryFactorySourceTime_Data* Tri(void); - - static TestAuxiliaryFactorySourceTime_Data* Hex(void); - -private: - - static - double moment_tensor_2d_xx(const double x, - const double y) { - return -0.3*x*x + 0.1*x*y; - } // moment_tensor_2d_xx - - static - double moment_tensor_2d_yy(const double x, - const double y) { - return -0.8*x*y + 0.2*y*y; - } // moment_tensor_2d_yy - - static - double moment_tensor_2d_zz(const double x, - const double y) { - return -0.3*x*x + 0.5*y*y; - } // moment_tensor_2d_zz - - static - double moment_tensor_2d_xy(const double x, - const double y) { - return -0.3*x*x + 0.3*x*y; - } - - static - const char* pressure_units(void) { - return "Pa"; - } // pressure_units - - static - double time_delay_2d(const double x, - const double y) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(y); - } // time_delay - - static - const char* time_units(void) { - return "s"; - } // time_units - - static - double center_frequency_2d(const double x, - const double y) { - return 6.4 + 5.0*fabs(x) + 4.3*fabs(y); - } // center_frequency - - static - const char* frequency_units(void) { - return "1/s"; - } // frequency_units - - static - double moment_tensor_3d_xx(const double x, - const double y, - const double z) { - return -0.3*x*z + 0.1*x*z; - } // moment_tensor_3d_xx - - static - double moment_tensor_3d_yy(const double x, - const double y, - const double z) { - return -0.8*x*z + 0.2*y*y; - } // moment_tensor_3d_yy - - static - double moment_tensor_3d_zz(const double x, - const double y, - const double z) { - return -0.3*x*x + 0.5*y*z; - } // moment_tensor_3d_zz - - static - double moment_tensor_3d_xy(const double x, - const double y, - const double z) { - return -0.3*x + 0.2*x*y; - } // moment_tensor_3d_xy - - static - double moment_tensor_3d_yz(const double x, - const double y, - const double z) { - return -0.3*x*z + 0.2*x*y; - } // moment_tensor_3d_yz - - static - double moment_tensor_3d_xz(const double x, - const double y, - const double z) { - return -0.3*x + 0.2*y; - } // moment_tensor_3d_xz - - static - double time_delay_3d(const double x, - const double y, - const double z) { - return 3.4 + 3.0*fabs(x) + 2.0*fabs(z); - } // time_delay - - static - double center_frequency_3d(const double x, - const double y, - const double z) { - return 6.4 + 4.0*fabs(x) + 5.3*fabs(z); - } // center_frequency - -}; - -// ------------------------------------------------------------------------------------------------ -TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactorySourceTime::Tri::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri()).testSetValuesFromDB(); -} - -TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testAdd", "[TestAuxiliaryFactorySourceTime][add]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testAdd(); -} -TEST_CASE("TestAuxiliaryFactorySourceTime::Hex::testSetValuesFromDB", "[TestAuxiliaryFactorySourceTime][testSetValuesFromDB]") { - pylith::sources::TestAuxiliaryFactorySourceTime(pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex()).testSetValuesFromDB(); -} - -// -------------------------------------------------------------------------------------------------------------------- -pylith::sources::TestAuxiliaryFactorySourceTime_Data* -pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Tri(void) { - pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); - assert(data); - - data->auxDim = 2; - data->dimension = 2; - data->meshFilename = "data/tri_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_2d_xx, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_2d_yy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_2d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_2d_xy, pressure_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_2d, time_units()); - data->auxiliaryDB->addValue("center_frequency", center_frequency_2d, frequency_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Tri - - -// ------------------------------------------------------------------------------------------------ -pylith::sources::TestAuxiliaryFactorySourceTime_Data* -pylith::sources::TestAuxiliaryFactorySourceTime_Cases::Hex(void) { - pylith::sources::TestAuxiliaryFactorySourceTime_Data* data = new pylith::sources::TestAuxiliaryFactorySourceTime_Data(); - assert(data); - - data->auxDim = 3; - data->dimension = 3; - data->meshFilename = "data/hex_onecell.mesh"; - data->cs = new spatialdata::geocoords::CSCart();assert(data->cs); - data->cs->setSpaceDim(data->dimension); - - assert(data->auxiliaryDB); - data->auxiliaryDB->addValue("moment_tensor_xx", moment_tensor_3d_xx, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yy", moment_tensor_3d_yy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_zz", moment_tensor_3d_zz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xy", moment_tensor_3d_xy, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_yz", moment_tensor_3d_yz, pressure_units()); - data->auxiliaryDB->addValue("moment_tensor_xz", moment_tensor_3d_xz, pressure_units()); - data->auxiliaryDB->addValue("time_delay", time_delay_3d, time_units()); - data->auxiliaryDB->addValue("center_frequency", center_frequency_3d, frequency_units()); - data->auxiliaryDB->setDescription("auxiliary"); - data->auxiliaryDB->setCoordSys(*data->cs); - - return data; -} // Hex diff --git a/tests/libtests/sources/TestSource.cc b/tests/libtests/sources/TestSource.cc deleted file mode 100644 index 559cf60408..0000000000 --- a/tests/libtests/sources/TestSource.cc +++ /dev/null @@ -1,781 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -#include - -#include "TestSource.hh" // Implementation of class methods - -#include "pylith/sources/Source.hh" // USES Source -#include "pylith/sources/Query.hh" // USES Query - -#include "pylith/topology/Mesh.hh" // USES Mesh -#include "pylith/topology/MeshOps.hh" // USES MeshOps::nondimensionalize() -#include "pylith/topology/Field.hh" // USES Field -#include "pylith/topology/Fields.hh" // USES Fields -#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh -#include "pylith/topology/FieldQuery.hh" // USES FieldQuery -#include "pylith/feassemble/AuxiliaryFactory.hh" // USES AuxiliaryFactory -#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii -#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END -#include "pylith/utils/journals.hh" // pythia::journal - -#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB -#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/spatialdb/GravityField.hh" // USES GravityField -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional - -// ---------------------------------------------------------------------- -// Setup testing data. -void -pylith::sources::TestSource::setUp(void) { - _mesh = new pylith::topology::Mesh();CPPUNIT_ASSERT(_mesh); - _solutionFields = NULL; -} // setUp - - -// ---------------------------------------------------------------------- -// Deallocate testing data. -void -pylith::sources::TestSource::tearDown(void) { - delete _solutionFields;_solutionFields = NULL; - delete _mesh;_mesh = NULL; -} // tearDown - - -// ---------------------------------------------------------------------- -// Test auxField(). -void -pylith::sources::TestSource::testAuxField(void) { - PYLITH_METHOD_BEGIN; - - _initializeFull(); - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - - const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); - for (int i = 0; i < data->numAuxSubfields; ++i) { - CPPUNIT_ASSERT(auxField->hasSubfield(data->auxSubfields[i])); - } // for - - CPPUNIT_ASSERT(!auxField->hasSubfield("abc4598245")); - - PYLITH_METHOD_END; -} // testAuxField - - -// ---------------------------------------------------------------------- -// Test auxSubfieldDiscretization(). -void -pylith::sources::TestSource::testAuxSubfieldDiscretization(void) { - PYLITH_METHOD_BEGIN; - - const topology::FieldBase::Discretization infoDefault = pylith::topology::Field::Discretization(1, 1, true, pylith::topology::FieldBase::POLYNOMIAL_SPACE); - const topology::FieldBase::Discretization infoA = pylith::topology::Field::Discretization(1, 2, false, pylith::topology::FieldBase::POLYNOMIAL_SPACE); - const topology::FieldBase::Discretization infoB = pylith::topology::Field::Discretization(2, 2, true, pylith::topology::FieldBase::POINT_SPACE); - - Source* source = _source();CPPUNIT_ASSERT(source); - source->auxSubfieldDiscretization("A", infoA.basisOrder, infoA.quadOrder, infoA.isBasisContinuous, infoA.feSpace); - source->auxSubfieldDiscretization("B", infoB.basisOrder, infoB.quadOrder, infoB.isBasisContinuous, infoB.feSpace); - - CPPUNIT_ASSERT(source->_auxiliaryFactory()); - { // A - const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("A"); - CPPUNIT_ASSERT_EQUAL(infoA.basisOrder, test.basisOrder); - CPPUNIT_ASSERT_EQUAL(infoA.quadOrder, test.quadOrder); - CPPUNIT_ASSERT_EQUAL(infoA.isBasisContinuous, test.isBasisContinuous); - CPPUNIT_ASSERT_EQUAL(infoA.feSpace, test.feSpace); - } // A - - { // B - const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("B"); - CPPUNIT_ASSERT_EQUAL(infoB.basisOrder, test.basisOrder); - CPPUNIT_ASSERT_EQUAL(infoB.quadOrder, test.quadOrder); - CPPUNIT_ASSERT_EQUAL(infoB.isBasisContinuous, test.isBasisContinuous); - CPPUNIT_ASSERT_EQUAL(infoB.feSpace, test.feSpace); - } // B - - { // C (default) - const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("C"); - CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); - CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); - CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); - CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); - } // C (default) - - { // default - const topology::FieldBase::Discretization& test = source->_auxiliaryFactory()->getSubfieldDiscretization("default"); - CPPUNIT_ASSERT_EQUAL(infoDefault.basisOrder, test.basisOrder); - CPPUNIT_ASSERT_EQUAL(infoDefault.quadOrder, test.quadOrder); - CPPUNIT_ASSERT_EQUAL(infoDefault.isBasisContinuous, test.isBasisContinuous); - CPPUNIT_ASSERT_EQUAL(infoDefault.feSpace, test.feSpace); - } // default - - PYLITH_METHOD_END; -} // testAuxSubfieldDiscretization - - -// ---------------------------------------------------------------------- -// Test auxFieldDB(). -void -pylith::sources::TestSource::testAuxFieldDB(void) { - PYLITH_METHOD_BEGIN; - - const std::string label = "test db"; - spatialdata::spatialdb::UserFunctionDB db; - db.setLabel(label.c_str()); - - Source* source = _source();CPPUNIT_ASSERT(source); - source->auxFieldDB(&db); - - CPPUNIT_ASSERT(source->_auxiliaryFactory()); - CPPUNIT_ASSERT(source->_auxiliaryFactory()->queryDB()); - CPPUNIT_ASSERT_EQUAL(label, std::string(source->_auxiliaryFactory()->queryDB()->getLabel())); - - PYLITH_METHOD_END; -} // testAuxFieldDB - - -// ---------------------------------------------------------------------- -// Test normalizer(). -void -pylith::sources::TestSource::testNormalizer(void) { - PYLITH_METHOD_BEGIN; - - spatialdata::units::Nondimensional normalizer; - const double scale = 5.0; - normalizer.setLengthScale(scale); - - Source* source = _source();CPPUNIT_ASSERT(source); - source->normalizer(normalizer); - CPPUNIT_ASSERT_EQUAL(scale, source->_normalizer->getLengthScale()); - - PYLITH_METHOD_END; -} // testNormalizer - - -// ---------------------------------------------------------------------- -// Test verifyConfiguration(). -void -pylith::sources::TestSource::testVerifyConfiguration(void) { - PYLITH_METHOD_BEGIN; - - // Call verifyConfiguration() - Source* source = _source();CPPUNIT_ASSERT(source); - CPPUNIT_ASSERT(_solutionFields); - source->verifyConfiguration(_solutionFields->get("solution")); - - // Nothing to test. - - PYLITH_METHOD_END; -} // testVerifyConfiguration - - -// ---------------------------------------------------------------------- -// Test dimension(), id(), and getLabel(). -void -pylith::sources::TestSource::testAccessors(void) { - PYLITH_METHOD_BEGIN; - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - - CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::dimension() failed.", data->dimension, source->dimension()); - - const int matId = 1234; - source->id(matId); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::id() failed.", matId, source->id()); - - const std::string& matLabel = "xyz"; - source->setLabel(matLabel.c_str()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Test of Source::getLabel() failed.", matLabel, std::string(source->getLabel())); - - PYLITH_METHOD_END; -} // testAccessors - - -// ---------------------------------------------------------------------- -// Test initialize(). -void -pylith::sources::TestSource::testInitialize(void) { - PYLITH_METHOD_BEGIN; - - // Call initialize() - _initializeFull(); // includes setting up auxField - - Source* source = _source();CPPUNIT_ASSERT(source); - const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); - - // source->_auxiliaryField->view("AUX FIELDS"); // :DEBUGGING: - - // Check result - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - CPPUNIT_ASSERT_EQUAL(std::string("auxiliary subfields"), std::string(auxField->getLabel())); - CPPUNIT_ASSERT_EQUAL(data->dimension, auxField->getSpaceDim()); - - PylithReal norm = 0.0; - PylithReal t = 0.0; - const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); - pylith::topology::FieldQuery query(*auxField); - query.initializeWithDefaultQueryFns(); - CPPUNIT_ASSERT(data->normalizer); - query.openDB(data->auxDB, data->normalizer->getLengthScale()); - PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); - query.closeDB(data->auxDB); - const PylithReal tolerance = 1.0e-6; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of auxiliary field values failed.", 0.0, norm, tolerance); - -#if 1 - // Verify solution and perturbation fields can be exactly represented by discretization. - norm = 0.0; - t = 0.0; - - pylith::topology::Field& solution = _solutionFields->get("solution"); - // solution.view("SOLUTION"); // :DEBUG: - const PetscDM dmSoln = solution.dmMesh();CPPUNIT_ASSERT(dmSoln); - pylith::topology::FieldQuery solnQuery(solution); - solnQuery.initializeWithDefaultQueryFns(); - CPPUNIT_ASSERT(data->normalizer); - solnQuery.openDB(data->solnDB, data->normalizer->getLengthScale()); - err = DMPlexComputeL2DiffLocal(dmSoln, t, solnQuery.functions(), (void**)solnQuery.contextPtrs(), solution.localVector(), &norm);CPPUNIT_ASSERT(!err); - solnQuery.closeDB(data->solnDB); - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized solution field failed representation test.", 0.0, norm, tolerance); - - pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); - // perturbation.view("PERTURBATION"); // :DEBUG: - const PetscDM dmPerturb = perturbation.dmMesh();CPPUNIT_ASSERT(dmPerturb); - pylith::topology::FieldQuery perturbQuery(perturbation); - perturbQuery.initializeWithDefaultQueryFns(); - CPPUNIT_ASSERT(data->normalizer); - perturbQuery.openDB(data->perturbDB, data->normalizer->getLengthScale()); - err = DMPlexComputeL2DiffLocal(dmPerturb, t, perturbQuery.functions(), (void**)perturbQuery.contextPtrs(), perturbation.localVector(), &norm);CPPUNIT_ASSERT(!err); - perturbQuery.closeDB(data->perturbDB); - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Discretized perturbation field failed representation test.", 0.0, norm, tolerance); -#endif - - PYLITH_METHOD_END; -} // testInitialize - - -// ---------------------------------------------------------------------- -// Test computeResidual(). -void -pylith::sources::TestSource::testComputeResidual(void) { - PYLITH_METHOD_BEGIN; - - // Call initialize() - _initializeFull(); // includes setting up auxField - - CPPUNIT_ASSERT(_mesh); - CPPUNIT_ASSERT(_solutionFields); - pylith::topology::Field& solution = _solutionFields->get("solution"); - pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); - - pylith::topology::Field residualRHS(*_mesh); - residualRHS.cloneSection(solution); - residualRHS.setLabel("residual RHS"); - residualRHS.createDiscretization(); - residualRHS.allocate(); - - pylith::topology::Field residualLHS(*_mesh); - residualLHS.cloneSection(solution); - residualLHS.setLabel("residual LHS"); - residualLHS.createDiscretization(); - residualLHS.allocate(); - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - -#if 0 // :DEBUG: - PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: - DMSetFromOptions(residualRHS.dmMesh()); // :DEBUG: -#endif // :DEBUG: - - const PylithReal t = data->t; - const PylithReal dt = data->dt; - source->computeRHSResidual(&residualRHS, t, dt, solution); - source->computeLHSResidual(&residualLHS, t, dt, solution, solutionDot); - - // We don't use Dirichlet BC, so we must manually zero out the residual values for constrained DOF. - _zeroBoundary(&residualRHS); - _zeroBoundary(&residualLHS); - -#if 0 // :DEBUG: - solution.view("SOLUTION"); // :DEBUG: - solutionDot.view("SOLUTION_DOT"); // :DEBUG: - residualRHS.view("RESIDUAL RHS"); // :DEBUG: - residualLHS.view("RESIDUAL LHS"); // :DEBUG: -#endif // :DEBUG: - - PetscErrorCode err; - PetscVec residualVec = NULL; - err = VecDuplicate(residualRHS.localVector(), &residualVec);CPPUNIT_ASSERT(!err); - err = VecWAXPY(residualVec, -1.0, residualRHS.localVector(), residualLHS.localVector());CPPUNIT_ASSERT(!err); - - PylithReal norm = 0.0; - PylithReal normRHS = 0.0; - PylithReal normLHS = 0.0; - err = VecNorm(residualRHS.localVector(), NORM_2, &normRHS);CPPUNIT_ASSERT(!err); - err = VecNorm(residualLHS.localVector(), NORM_2, &normLHS);CPPUNIT_ASSERT(!err); - err = VecNorm(residualVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); - err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); - const PylithReal tolerance = 1.0e-6; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Test of F(s) - G(s) == 0 failed.", 0.0, norm, tolerance); - // Avoid trivial satisfaction of norm with zero values. - CPPUNIT_ASSERT_MESSAGE("RHS and LHS residuals are both exactly zero, which is suspicious.", normRHS > 0.0 || normLHS > 0.0); - - PYLITH_METHOD_END; -} // testComputeResidual - - -// ---------------------------------------------------------------------- -// Test computeJacobian(). -void -pylith::sources::TestSource::testComputeJacobian(void) { - PYLITH_METHOD_BEGIN; - - // Create linear problem (MMS) with two trial solutions, s and p. - // - // Check that Jg(s)*(p - s) = G(p) - G(s). - - // Call initialize() - _initializeFull(); - - CPPUNIT_ASSERT(_mesh); - CPPUNIT_ASSERT(_solutionFields); - pylith::topology::Field& solution = _solutionFields->get("solution"); - pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - - pylith::topology::Field residual1(*_mesh); - residual1.cloneSection(solution); - residual1.setLabel("residual1"); - residual1.createDiscretization(); - residual1.allocate(); - - pylith::topology::Field residual2(*_mesh); - residual2.cloneSection(perturbation); - residual2.setLabel("residual2"); - residual2.createDiscretization(); - residual2.allocate(); - -#if 0 // :DEBUG: - PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "3"); // :DEBUG: - DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: -#endif // :DEBUG: - - const PylithReal t = data->t; - const PylithReal dt = data->dt; - source->computeLHSResidual(&residual1, t, dt, solution); - source->computeLHSResidual(&residual2, t, dt, perturbation); - - // residual1.view("RESIDUAL 1 RHS"); // :DEBUG: - // residual2.view("RESIDUAL 2 RHS"); // :DEBUG: - - // Compute Jacobian - PetscErrorCode err; - PetscMat jacobianMat = NULL; - err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); - err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); - PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner - - source->computeLHSJacobian(jacobianMat, precondMat, t, dt, solution); - CPPUNIT_ASSERT_EQUAL(false, source->needNewLHSJacobian()); - // _zeroBoundary(&residual1); - // _zeroBoundary(&residual2, jacobianMat); - err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); - err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); - - // Check that J(s)*(p - s) = G(p) - G(s). - - PetscVec residualVec = NULL; - err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); - err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); - - PetscVec solnIncrVec = NULL; - err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); - err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); - - // result = Jg*(-solnIncr) + residual - PetscVec resultVec = NULL; - err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); - err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); - err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); - err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); - -#if 0 // :DEBUG: - std::cout << "SOLN INCR" << std::endl; - VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); - std::cout << "G2-G1" << std::endl; - VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); - std::cout << "RESULT" << std::endl; - VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); -#endif // :DEBUG: - - PylithReal norm = 0.0; - err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); - err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); - err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); - err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); - err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); - - const PylithReal tolerance = 1.0e-6; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jg(s)*(p-s) - (G(p) - G(s)) == 0 failed.", 0.0, norm, tolerance); - CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", norm > 0.0); - - PYLITH_METHOD_END; -} // testComputeJacobian - - -// ---------------------------------------------------------------------- -// Test computeLHSJacobianImplicit(). -void -pylith::sources::TestSource::testComputeLHSJacobianImplicit(void) { - PYLITH_METHOD_BEGIN; - - Source* source = _source();CPPUNIT_ASSERT(source); - const TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - if (data->isExplicit) { - PYLITH_METHOD_END; - } // if - - // Create linear problem (MMS) with two trial solutions, s,s_dor and p,p_dot. - // - // Check that Jf(s,s_dot)*(p - s) = F(p,p_dot) - F(s,s_dot). - - // Call initialize() - _initializeFull(); // includes setting up auxField - - CPPUNIT_ASSERT(_mesh); - CPPUNIT_ASSERT(_solutionFields); - pylith::topology::Field& solution = _solutionFields->get("solution"); - pylith::topology::Field& solutionDot = _solutionFields->get("solution_dot"); - pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); - pylith::topology::Field& perturbationDot = _solutionFields->get("perturbation_dot"); - - pylith::topology::Field residual1(*_mesh); - residual1.cloneSection(solution); - residual1.setLabel("residual1"); - residual1.createDiscretization(); - residual1.allocate(); - - pylith::topology::Field residual2(*_mesh); - residual2.cloneSection(perturbation); - residual2.setLabel("residual2"); - residual2.createDiscretization(); - residual2.allocate(); - -#if 0 // :DEBUG: - PetscOptionsSetValue(NULL, "-dm_plex_print_fem", "2"); // :DEBUG: - DMSetFromOptions(_solution1->dmMesh()); // :DEBUG: -#endif // :DEBUG: - - const PylithReal t = data->t; - const PylithReal dt = data->dt; - const PylithReal s_tshift = data->s_tshift; - source->computeLHSResidual(&residual1, t, dt, solution, solutionDot); - source->computeLHSResidual(&residual2, t, dt, perturbation, perturbationDot); - - // residual1.view("RESIDUAL 1 LHS"); // :DEBUG: - // residual2.view("RESIDUAL 2 LHS"); // :DEBUG: - - PetscErrorCode err; - - PetscVec residualVec = NULL; - err = VecDuplicate(residual1.localVector(), &residualVec);CPPUNIT_ASSERT(!err); - err = VecWAXPY(residualVec, -1.0, residual1.localVector(), residual2.localVector());CPPUNIT_ASSERT(!err); - - PetscVec solnIncrVec = NULL; - err = VecDuplicate(solution.localVector(), &solnIncrVec);CPPUNIT_ASSERT(!err); - err = VecWAXPY(solnIncrVec, -1.0, solution.localVector(), perturbation.localVector());CPPUNIT_ASSERT(!err); - - // Compute Jacobian - PetscMat jacobianMat = NULL; - err = DMCreateMatrix(solution.dmMesh(), &jacobianMat);CPPUNIT_ASSERT(!err); - err = MatZeroEntries(jacobianMat);CPPUNIT_ASSERT(!err); - PetscMat precondMat = jacobianMat; // Use Jacobian == preconditioner - - source->computeLHSJacobianImplicit(jacobianMat, precondMat, t, dt, s_tshift, solution, solutionDot); - CPPUNIT_ASSERT_EQUAL(false, source->needNewLHSJacobian()); - err = MatAssemblyBegin(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); - err = MatAssemblyEnd(jacobianMat, MAT_FINAL_ASSEMBLY);PYLITH_CHECK_ERROR(err); - - // result = J*(-solnIncr) + residual - PetscVec resultVec = NULL; - err = VecDuplicate(residualVec, &resultVec);CPPUNIT_ASSERT(!err); - err = VecZeroEntries(resultVec);CPPUNIT_ASSERT(!err); - err = VecScale(solnIncrVec, -1.0);CPPUNIT_ASSERT(!err); - err = MatMultAdd(jacobianMat, solnIncrVec, residualVec, resultVec);CPPUNIT_ASSERT(!err); - -#if 0 // :DEBUG: - std::cout << "SOLN INCR" << std::endl; - VecView(solnIncrVec, PETSC_VIEWER_STDOUT_SELF); - std::cout << "F2-F1" << std::endl; - VecView(residualVec, PETSC_VIEWER_STDOUT_SELF); - std::cout << "RESULT" << std::endl; - VecView(resultVec, PETSC_VIEWER_STDOUT_SELF); -#endif // :DEBUG: - - PylithReal norm = 0.0, normSolnIncr = 0.0, normResidual = 0.0; - err = VecNorm(resultVec, NORM_2, &norm);CPPUNIT_ASSERT(!err); - err = VecNorm(solnIncrVec, NORM_2, &normSolnIncr);CPPUNIT_ASSERT(!err); - err = VecNorm(residualVec, NORM_2, &normResidual);CPPUNIT_ASSERT(!err); - err = VecDestroy(&resultVec);CPPUNIT_ASSERT(!err); - err = VecDestroy(&solnIncrVec);CPPUNIT_ASSERT(!err); - err = VecDestroy(&residualVec);CPPUNIT_ASSERT(!err); - err = MatDestroy(&jacobianMat);CPPUNIT_ASSERT(!err); - - const PylithReal tolerance = 1.0e-6; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of Jf(s)*(p-s) - (F(p) - F(s)) == 0 failed.", 0.0, norm, tolerance); - CPPUNIT_ASSERT_MESSAGE("Norm of resulting vector is exactly zero, which is suspicious.", (0 < normResidual && 0 < norm) || (0 == normResidual && 0 == norm)); - - PYLITH_METHOD_END; -} // testComputeLHSJacobianImplicit - - -// ---------------------------------------------------------------------- -// Test computeLHSJacobianExplicit(). -void -pylith::sources::TestSource::testComputeLHSJacobianInverseExplicit(void) { - PYLITH_METHOD_BEGIN; - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - if (!data->isExplicit) { - PYLITH_METHOD_END; - } // if - - CPPUNIT_ASSERT_MESSAGE("Test not implemented.", false); // :TODO: ADD MORE HERE - - PYLITH_METHOD_END; -} // testComputeLHSJacobianInverseExplicit - - -// ---------------------------------------------------------------------- -// Test updateStateVars(). -void -pylith::sources::TestSource::testUpdateStateVars(void) { - PYLITH_METHOD_BEGIN; - - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - if (!data->auxUpdateDB) { - PYLITH_METHOD_END; - } // if - - // Call initialize() - _initializeFull(); // includes setting up auxField - - // We test updating the state variables in the auxiliary field by - // passing the perturbation as the "new" solution and the existing - // auxiliary field. We test whether the "updated" auxiliary field - // matches the database with the updated auxiliary field. - - Source* source = _source();CPPUNIT_ASSERT(source); - CPPUNIT_ASSERT(_solutionFields); - pylith::topology::Field& perturbation = _solutionFields->get("perturbation"); -#if 0 - source->_auxiliaryField->view("INITIAL_AUX FIELDS"); // :DEBUGGING: -#endif - source->_updateStateVars(data->t, data->dt, perturbation); - - const pylith::topology::Field* auxField = source->auxField();CPPUNIT_ASSERT(auxField); - source->_auxiliaryField->view("UPDATED_AUX FIELDS"); // :DEBUGGING: - - // Check updated auxiliary field. - PylithReal norm = 0.0; - PylithReal t = 0.0; - const PetscDM dm = auxField->dmMesh();CPPUNIT_ASSERT(dm); - pylith::topology::FieldQuery query(*auxField); - query.initializeWithDefaultQueryFns(); - CPPUNIT_ASSERT(data->normalizer); - query.openDB(data->auxUpdateDB, data->normalizer->getLengthScale()); -#if 0 // :DEBUG: - PetscOptionsSetValue(NULL, "-dm_plex_print_l2", "1"); // :DEBUG: - DMSetFromOptions(dm); // :DEBUG: -#endif - PetscErrorCode err = DMPlexComputeL2DiffLocal(dm, t, query.functions(), (void**)query.contextPtrs(), auxField->localVector(), &norm);CPPUNIT_ASSERT(!err); - query.closeDB(data->auxUpdateDB); - const PylithReal tolerance = 1.0e-6; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Check of updated auxiliary field values failed.", 0.0, norm, tolerance); - - PYLITH_METHOD_END; -} // testUpdateStateVars - - -// ---------------------------------------------------------------------- -// Do minimal initilaization of test data. -void -pylith::sources::TestSource::_initializeMin(void) { - PYLITH_METHOD_BEGIN; - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - - pylith::meshio::MeshIOAscii iohandler; - CPPUNIT_ASSERT(data->meshFilename); - iohandler.filename(data->meshFilename); - iohandler.read(_mesh);CPPUNIT_ASSERT(_mesh); - - CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any cells.", _mesh->numCells() > 0); - CPPUNIT_ASSERT_MESSAGE("Test mesh does not contain any vertices.", _mesh->numVertices() > 0); - - // Setup coordinates. - _mesh->setCoordSys(data->cs); - CPPUNIT_ASSERT(data->normalizer); - pylith::topology::MeshOps::nondimensionalize(_mesh, *data->normalizer); - - // id and label initialized in derived class - source->normalizer(*data->normalizer); - source->gravityField(data->gravityField); - - // Setup solution fields. - delete _solutionFields;_solutionFields = new pylith::topology::Fields(*_mesh);CPPUNIT_ASSERT(_solutionFields); - _solutionFields->add("solution","solution"); - _solutionFields->add("solution_dot","solution_dot"); - _solutionFields->add("perturbation","perturbation"); - _solutionFields->add("perturbation_dot","perturbation_dot"); - this->_setupSolutionFields(); - - PYLITH_METHOD_END; -} // _initializeMin - - -// ---------------------------------------------------------------------- -// Complete initilaization of test data. -void -pylith::sources::TestSource::_initializeFull(void) { - PYLITH_METHOD_BEGIN; - - Source* source = _source();CPPUNIT_ASSERT(source); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - CPPUNIT_ASSERT(_mesh); - - // Set auxiliary fields spatial database. - source->auxFieldDB(data->auxDB); - - for (int i = 0; i < data->numAuxSubfields; ++i) { - const pylith::topology::FieldBase::Discretization& info = data->auxDiscretizations[i]; - source->auxSubfieldDiscretization(data->auxSubfields[i], info.basisOrder, info.quadOrder, info.isBasisContinuous, info.feSpace); - } // for - - CPPUNIT_ASSERT(_solutionFields); - source->initialize(_solutionFields->get("solution")); - - PYLITH_METHOD_END; -} // _initializeFull - - -// ---------------------------------------------------------------------- -// Set field to zero on the boundary. -void -pylith::sources::TestSource::_zeroBoundary(pylith::topology::Field* field) { - PYLITH_METHOD_BEGIN; - - CPPUNIT_ASSERT(field); - TestSource_Data* data = _data();CPPUNIT_ASSERT(data); - CPPUNIT_ASSERT(data->boundaryLabel); - - PetscDM dmMesh = field->mesh().dmMesh();CPPUNIT_ASSERT(dmMesh); - PetscDMLabel label = NULL; - PetscIS pointIS = NULL; - const PetscInt *points; - PetscInt numPoints = 0; - PetscBool hasLabel = PETSC_FALSE; - PetscErrorCode err; - err = DMHasLabel(dmMesh, data->boundaryLabel, &hasLabel);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(hasLabel); - err = DMGetLabel(dmMesh, data->boundaryLabel, &label);CPPUNIT_ASSERT(!err); - err = DMLabelGetStratumIS(label, 1, &pointIS);CPPUNIT_ASSERT(!err);CPPUNIT_ASSERT(pointIS); - err = ISGetLocalSize(pointIS, &numPoints);CPPUNIT_ASSERT(!err); - err = ISGetIndices(pointIS, &points);CPPUNIT_ASSERT(!err); - - pylith::topology::VecVisitorMesh fieldVisitor(*field); - PylithScalar* fieldArray = fieldVisitor.localArray();CPPUNIT_ASSERT(fieldArray); - - for (PylithInt p = 0; p < numPoints; ++p) { - const PylithInt p_bc = points[p]; - - const PylithInt off = fieldVisitor.sectionOffset(p_bc); - const PylithInt dof = fieldVisitor.sectionDof(p_bc); - for (PylithInt i = 0; i < dof; ++i) { - fieldArray[off+i] = 0.0; - } // for - } // for - - err = ISRestoreIndices(pointIS, &points);PYLITH_CHECK_ERROR(err); - err = ISDestroy(&pointIS);PYLITH_CHECK_ERROR(err); - - PYLITH_METHOD_END; -} // _zeroBoundary - - -// ---------------------------------------------------------------------- -// Constructor -pylith::sources::TestSource_Data::TestSource_Data(void) : - dimension(0), - meshFilename(0), - boundaryLabel(NULL), - cs(NULL), - gravityField(NULL), - - normalizer(new spatialdata::units::Nondimensional), - - t(0.0), - dt(0.0), - s_tshift(0.0), - perturbation(1.0e-4), - - numSolnSubfields(0), - solnDiscretizations(NULL), - solnDB(new spatialdata::spatialdb::UserFunctionDB), - perturbDB(new spatialdata::spatialdb::UserFunctionDB), - - numAuxSubfields(0), - auxSubfields(NULL), - auxDiscretizations(NULL), - auxDB(new spatialdata::spatialdb::UserFunctionDB), - auxUpdateDB(NULL), - - isExplicit(false) { // constructor - CPPUNIT_ASSERT(normalizer); - - CPPUNIT_ASSERT(solnDB); - solnDB->setLabel("solution"); - - CPPUNIT_ASSERT(perturbDB); - perturbDB->setLabel("solution+perturbation"); - - CPPUNIT_ASSERT(auxDB); - auxDB->setLabel("auxiliary field"); -} // constructor - - -// ---------------------------------------------------------------------- -// Destructor -pylith::sources::TestSource_Data::~TestSource_Data(void) { - delete cs;cs = NULL; - delete gravityField;gravityField = NULL; - delete normalizer;normalizer = NULL; - delete solnDB;solnDB = NULL; - delete auxDB;auxDB = NULL; - delete auxUpdateDB;auxUpdateDB = NULL; -} // destructor - - -// End of file diff --git a/tests/libtests/sources/TestSource.hh b/tests/libtests/sources/TestSource.hh deleted file mode 100644 index 9245c92889..0000000000 --- a/tests/libtests/sources/TestSource.hh +++ /dev/null @@ -1,211 +0,0 @@ -// -*- C++ -*- -// -// ---------------------------------------------------------------------- -// -// Brad T. Aagaard, U.S. Geological Survey -// Charles A. Williams, GNS Science -// Matthew G. Knepley, University at Buffalo -// -// This code was developed as part of the Computational Infrastructure -// for Geodynamics (http://geodynamics.org). -// -// Copyright (c) 2010-2022 University of California, Davis -// -// See LICENSE.md for license information. -// -// ---------------------------------------------------------------------- -// - -/** - * @file tests/libtests/sources/TestSource.hh - * - * @brief C++ abstract base class for testing source objects. - */ - -#if !defined(pylith_sources_testSource_hh) -#define pylith_sources_testSource_hh - -#include -#include "pylith/utils/GenericComponent.hh" // ISA GenericComponent - -#include "pylith/sources/sourcesfwd.hh" // forward declarations -#include "pylith/topology/topologyfwd.hh" // forward declarations -#include "pylith/topology/Field.hh" // HASA FieldBase::Discretization - -#include "spatialdata/spatialdb/spatialdbfwd.hh" // HOLDSA UserFunctionDB -#include "spatialdata/geocoords/geocoordsfwd.hh" // HOLDSA CoordSys -#include "spatialdata/units/unitsfwd.hh" // HOLDSA Nondimensional - -/// Namespace for pylith package -namespace pylith { - namespace sources { - class TestSource; - - class TestSource_Data; // test data - } // sources -} // pylith - -/// C++ abstract base class for testing source objects. -class pylith::sources::TestSource : public CppUnit::TestFixture, public pylith::utils::GenericComponent { - // CPPUNIT TEST SUITE ///////////////////////////////////////////////// - CPPUNIT_TEST_SUITE(TestSource); - - CPPUNIT_TEST(testAuxField); - CPPUNIT_TEST(testAuxSubfieldDiscretization); - CPPUNIT_TEST(testAuxFieldDB); - CPPUNIT_TEST(testNormalizer); - - CPPUNIT_TEST(testVerifyConfiguration); - - CPPUNIT_TEST(testAccessors); - CPPUNIT_TEST(testInitialize); - - CPPUNIT_TEST(testComputeResidual); - CPPUNIT_TEST(testComputeJacobian); - CPPUNIT_TEST(testComputeLHSJacobianImplicit); - CPPUNIT_TEST(testComputeLHSJacobianInverseExplicit); - CPPUNIT_TEST(testUpdateStateVars); - - CPPUNIT_TEST_SUITE_END_ABSTRACT(); - - // PUBLIC METHODS ///////////////////////////////////////////////////// -public: - - /// Setup testing data. - virtual - void setUp(void); - - /// Deallocate testing data. - void tearDown(void); - - /// Test auxField(). - void testAuxField(void); - - /// Test constructor. - void testConstructor(void); - - // /// Test accessors (field, dbTimeHistory, useInitial, useRate, useTimeHistory). - // void testAccessors(void); - - /// Test dimension(), id(), and getLabel(). - void testAccessors(void); - - /// Test auxFieldDiscretization(). - void testAuxFieldDiscretization(void); - - /// Test auxFieldDB(). - void testAuxFieldDB(void); - - /// Test normalizer(). - void testNormalizer(void); - - /// Test verifyConfiguration(). - void testVerifyConfiguration(void); - - /// Test checkConstraints(). - void testCheckConstraints(void); - - /// Test initialize(). - void testInitialize(void); - - /// Test computeRHSResidual(), computeLHSResidual(). - void testComputeResidual(void); - - /// Test computeJacobian(). - void testComputeJacobian(void); - - /// Test computeLHSJacobianImplicit(). - void testComputeLHSJacobianImplicit(void); - - /// Test computeLHSJacobianInverseExplicit(). - void testComputeLHSJacobianInverseExplicit(void); - - /// Test _updateStateVars(). - void testUpdateStateVars(void); - - // PROTECTED METHODS ////////////////////////////////////////////////// -protected: - - /** Get source. - * - * @returns Pointer to source. - */ - virtual - Source* _source(void) = 0; - - /** Get test data. - * - * @returns Pointer to test data. - */ - virtual - TestSource_Data* _data(void) = 0; - - /// Do minimal initilaization of test data. - void _initializeMin(void); - - /// Do full initilaization of test data. - void _initializeFull(void); - - /** Set field (and, optionally, matrix rows and columns) to zero on the boundary. - * - * @param[out] field Field in which to set boundary values to zero. - */ - void _zeroBoundary(pylith::topology::Field* field); - - /// Setup and populate solution fields. - virtual - void _setupSolutionFields(void) = 0; - - // PROTECTED MEMBERS ////////////////////////////////////////////////// -protected: - - // TestSource - pylith::topology::Mesh* _mesh; ///< Finite-element mesh. - pylith::topology::Fields* _solutionFields; ///< Contrainer for solution fields. - -}; // class TestSource - -// ============================================================================= -class pylith::sources::TestSource_Data { - // PUBLIC METHODS /////////////////////////////////////////////////////// -public: - - /// Constructor - TestSource_Data(void); - - /// Destructor - ~TestSource_Data(void); - - // PUBLIC MEMBERS /////////////////////////////////////////////////////// -public: - - int dimension; ///< Dimension of source. - const char* meshFilename; ///< Name of file with ASCII mesh. - const char* boundaryLabel; ///< Group defining domain boundary. - - spatialdata::geocoords::CoordSys* cs; ///< Coordinate system. - spatialdata::spatialdb::GravityField* gravityField; ///< Gravity field. - spatialdata::units::Nondimensional* normalizer; ///< Scales for nondimensionalization. - - PylithReal t; ///< Time for solution in simulation. - PylithReal dt; ///< Time step in simulation. - PylithReal s_tshift; ///< Time shift for LHS Jacobian. - PylithReal perturbation; ///< Maximum amplitude of random perturbation. - - int numSolnSubfields; ///< Number of solution fields. - pylith::topology::Field::Discretization* solnDiscretizations; ///< Discretizations for solution fields. - spatialdata::spatialdb::UserFunctionDB* solnDB; ///< Spatial database with solution. - spatialdata::spatialdb::UserFunctionDB* perturbDB; ///< Spatial database with solution + perturbation. - - int numAuxSubfields; ///< Number of auxiliary subfields. - const char** auxSubfields; ///< Names of auxiliary subfields. - pylith::topology::Field::Discretization* auxDiscretizations; ///< Discretizations for auxiliary subfields. - spatialdata::spatialdb::UserFunctionDB* auxDB; ///< Spatial database with auxiliary field. - spatialdata::spatialdb::UserFunctionDB* auxUpdateDB; ///< Spatial database with updated auxiliary field. - - bool isExplicit; ///< True for explicit time stepping. -}; - -#endif // pylith_sources_testSource_hh - -// End of file diff --git a/tests/libtests/sources/data/Makefile.am b/tests/libtests/sources/data/Makefile.am deleted file mode 100644 index ad879dbb44..0000000000 --- a/tests/libtests/sources/data/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ -# -*- Makefile -*- -# -# ---------------------------------------------------------------------- -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2022 University of California, Davis -# -# See LICENSE.md for license information. -# -# ---------------------------------------------------------------------- -# - -dist_noinst_DATA = \ - tri_onecell.mesh \ - hex_onecell.mesh - -noinst_TMP = - -export_datadir = $(abs_builddir) -include $(top_srcdir)/tests/data.am - - -# End of file diff --git a/tests/libtests/sources/data/hex_onecell.mesh b/tests/libtests/sources/data/hex_onecell.mesh deleted file mode 100644 index 76565397d3..0000000000 --- a/tests/libtests/sources/data/hex_onecell.mesh +++ /dev/null @@ -1,37 +0,0 @@ -mesh = { - dimension = 3 - use-index-zero = true - vertices = { - dimension = 3 - count = 8 - coordinates = { - 0 -4.000000000000000000e+03 -4.000000000000000000e+03 4.000000000000000000e+03 - 1 -4.000000000000000000e+03 -4.000000000000000000e+03 2.000000000000000000e+03 - 2 -4.000000000000000000e+03 -2.000000000000000000e+03 2.000000000000000000e+03 - 3 -4.000000000000000000e+03 -2.000000000000000000e+03 4.000000000000000000e+03 - 4 -2.000000000000000000e+03 -4.000000000000000000e+03 4.000000000000000000e+03 - 5 -2.000000000000000000e+03 -4.000000000000000000e+03 2.000000000000000000e+03 - 6 -2.000000000000000000e+03 -2.000000000000000000e+03 2.000000000000000000e+03 - 7 -2.000000000000000000e+03 -2.000000000000000000e+03 4.000000000000000000e+03 - } - } - cells = { - count = 1 - num-corners = 8 - simplices = { - 0 0 1 2 3 4 5 6 7 - } - material-ids = { - 0 24 - } - } - group = { - type = vertices - name = boundary - count = 8 - indices = { - 0 1 2 3 4 5 6 7 - } - } - -} diff --git a/tests/libtests/sources/data/tri_onecell.mesh b/tests/libtests/sources/data/tri_onecell.mesh deleted file mode 100644 index aa364381eb..0000000000 --- a/tests/libtests/sources/data/tri_onecell.mesh +++ /dev/null @@ -1,32 +0,0 @@ -mesh = { - dimension = 2 - use-index-zero = true - vertices = { - dimension = 2 - count = 3 - coordinates = { - 0 -1.0e+3 -1.0e+3 - 1 +1.0e+3 -1.0e+3 - 2 -1.0e+3 +1.0e+3 - } - } - cells = { - count = 1 - num-corners = 3 - simplices = { - 0 0 1 2 - } - material-ids = { - 0 24 - } - } - group = { - type = vertices - name = boundary - count = 3 - indices = { - 0 1 2 - } - } - -} From a3ce73d083045e0e689f158c27401dc2bd081f19 Mon Sep 17 00:00:00 2001 From: Robert Walker <43224558+rwalkerlewis@users.noreply.github.com> Date: Fri, 6 Jun 2025 22:46:02 -0600 Subject: [PATCH 59/65] Update configure.ac --- configure.ac | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac index 62063e398a..247b20e3b9 100644 --- a/configure.ac +++ b/configure.ac @@ -236,8 +236,6 @@ AC_CONFIG_FILES([Makefile tests/libtests/meshio/Makefile tests/libtests/problems/Makefile tests/libtests/problems/data/Makefile - tests/libtests/sources/Makefile - tests/libtests/sources/data/Makefile tests/libtests/meshio/data/Makefile tests/libtests/scales/Makefile tests/libtests/topology/Makefile From 0daf65a39f56c01a39f34045f1776a0217952c5c Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 31 Dec 2025 06:04:42 +0000 Subject: [PATCH 60/65] Added functioning MMS tests to moment tensor source --- configure.ac | 3 + libsrc/pylith/feassemble/DSLabelAccess.icc | 5 - libsrc/pylith/problems/Problem.cc | 2 +- .../AuxiliaryFactoryMomentTensorForce.cc | 25 +- .../sources/AuxiliaryFactorySourceTime.cc | 10 +- .../DerivedFactoryMomentTensorForce.cc | 5 +- libsrc/pylith/sources/MomentTensorForce.cc | 14 +- .../SourceTimeFunctionMomentTensorForce.cc | 5 +- .../SourceTimeFunctionMomentTensorForce.hh | 5 +- libsrc/pylith/sources/TimeHistoryWavelet.cc | 6 +- libsrc/pylith/sources/TimeHistoryWavelet.hh | 3 +- m4 | 2 +- modulesrc/sources/TimeHistoryWavelet.i | 3 +- tests/libtests/sources/Makefile.am | 14 + tests/mmstests/Makefile.am | 3 +- tests/mmstests/sources/Makefile.am | 15 + .../sources/momenttensor-2d/Makefile.am | 49 ++ .../momenttensor-2d/MomentTensorSource2D.cc | 424 +++++++++++++++++ .../momenttensor-2d/MomentTensorSource2D.hh | 33 ++ .../MomentTensorUniformStrain2D.cc | 450 ++++++++++++++++++ .../MomentTensorUniformStrain2D.hh | 38 ++ .../sources/momenttensor-2d/TestCases.cc | 70 +++ .../momenttensor-2d/TestMomentTensorSource.cc | 204 ++++++++ .../momenttensor-2d/TestMomentTensorSource.hh | 124 +++++ .../sources/momenttensor-2d/data/quad.mesh | 78 +++ .../sources/momenttensor-2d/data/tri.mesh | 80 ++++ 26 files changed, 1624 insertions(+), 46 deletions(-) create mode 100644 tests/libtests/sources/Makefile.am create mode 100644 tests/mmstests/sources/Makefile.am create mode 100644 tests/mmstests/sources/momenttensor-2d/Makefile.am create mode 100644 tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc create mode 100644 tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.hh create mode 100644 tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc create mode 100644 tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.hh create mode 100644 tests/mmstests/sources/momenttensor-2d/TestCases.cc create mode 100644 tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc create mode 100644 tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh create mode 100644 tests/mmstests/sources/momenttensor-2d/data/quad.mesh create mode 100644 tests/mmstests/sources/momenttensor-2d/data/tri.mesh diff --git a/configure.ac b/configure.ac index 247b20e3b9..bac1e411d1 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,7 @@ AC_CONFIG_FILES([Makefile tests/libtests/problems/data/Makefile tests/libtests/meshio/data/Makefile tests/libtests/scales/Makefile + tests/libtests/sources/Makefile tests/libtests/topology/Makefile tests/libtests/topology/data/Makefile tests/libtests/testing/Makefile @@ -252,6 +253,8 @@ AC_CONFIG_FILES([Makefile tests/mmstests/incompressibleelasticity/nofaults-2d/Makefile tests/mmstests/poroelasticity/Makefile tests/mmstests/poroelasticity/nofaults-2d/Makefile + tests/mmstests/sources/Makefile + tests/mmstests/sources/momenttensor-2d/Makefile tests/fullscale/Makefile tests/fullscale/cornercases/Makefile tests/fullscale/cornercases/nofaults-2d/Makefile diff --git a/libsrc/pylith/feassemble/DSLabelAccess.icc b/libsrc/pylith/feassemble/DSLabelAccess.icc index 903f32aee3..80e0b529a8 100644 --- a/libsrc/pylith/feassemble/DSLabelAccess.icc +++ b/libsrc/pylith/feassemble/DSLabelAccess.icc @@ -79,12 +79,7 @@ pylith::feassemble::DSLabelAccess::DSLabelAccess(const PetscDM dm, _numPoints = numPointsNew; } else { err = ISDestroy(&_pointsIS);PYLITH_CHECK_ERROR(err); - err = ISRestoreIndices(_cellsIS, &cellIndices);PYLITH_CHECK_ERROR(err); - } else { - err = ISDestroy(&_cellsIS);PYLITH_CHECK_ERROR(err); } // if/else - // } else { - // err = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_OWN_POINTER,&_cellsIS); } PYLITH_METHOD_END; diff --git a/libsrc/pylith/problems/Problem.cc b/libsrc/pylith/problems/Problem.cc index c0d027f48c..96204f5e38 100644 --- a/libsrc/pylith/problems/Problem.cc +++ b/libsrc/pylith/problems/Problem.cc @@ -421,7 +421,7 @@ pylith::problems::Problem::preinitialize(const pylith::topology::Mesh& mesh) { const size_t numSources = _sources.size(); for (size_t i = 0; i < numSources; ++i) { assert(_sources[i]); - _sources[i]->setNormalizer(*_normalizer); + _sources[i]->setScales(*_scales); _sources[i]->setFormulation(_formulation); } // for diff --git a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc index f3b67adcef..120b576bc2 100644 --- a/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/AuxiliaryFactoryMomentTensorForce.cc @@ -23,9 +23,9 @@ #include "pylith/topology/Field.hh" // USES Field #include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery #include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/scales/Scales.hh" // USES Scales #include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include "pylith/utils/error.hh" // USES PYLITH_METHOD* #include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* @@ -52,7 +52,15 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // m PYLITH_JOURNAL_DEBUG("addMomentTensor(void)"); const char* subfieldName = "moment_tensor"; - const char* componentNames[6] = { + // For 2D: Mxx, Myy, Mxy, Myx (4 components) + // For 3D: Mxx, Myy, Mzz, Mxy, Myz, Mxz (6 components using symmetric Voigt notation) + const char* componentNames2D[4] = { + "moment_tensor_xx", + "moment_tensor_yy", + "moment_tensor_xy", + "moment_tensor_yx" + }; + const char* componentNames3D[6] = { "moment_tensor_xx", "moment_tensor_yy", "moment_tensor_zz", @@ -60,8 +68,9 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addMomentTensor(void) { // m "moment_tensor_yz", "moment_tensor_xz" }; + const char** componentNames = (3 == _spaceDim) ? componentNames3D : componentNames2D; const int tensorSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; - const PylithReal pressureScale = _normalizer->getPressureScale(); + const PylithReal pressureScale = _scales->getRigidityScale(); pylith::topology::Field::Description description; description.label = subfieldName; @@ -92,7 +101,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeDelay(void) { // time const char* subfieldName = "time_delay"; pylith::topology::Field::Description description; - const PylithReal timeScale = _normalizer->getTimeScale(); + const PylithReal timeScale = _scales->getTimeScale(); description.label = subfieldName; description.alias = subfieldName; description.vectorFieldType = pylith::topology::Field::SCALAR; @@ -119,7 +128,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addCenterFrequency(void) { / PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); const char* subfieldName = "center_frequency"; - const PylithReal timeScale = _normalizer->getTimeScale(); + const PylithReal timeScale = _scales->getTimeScale(); pylith::topology::Field::Description description; description.label = subfieldName; @@ -148,7 +157,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeHistoryStartTime(void const char* subfieldName = "time_history_start_time"; assert(_defaultDescription); - assert(_normalizer); + assert(_scales); pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); subfieldDescription.label = subfieldName; subfieldDescription.alias = subfieldName; @@ -156,7 +165,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeHistoryStartTime(void subfieldDescription.numComponents = 1; subfieldDescription.componentNames.resize(1); subfieldDescription.componentNames[0] = subfieldName; - subfieldDescription.scale = _normalizer->getTimeScale(); + subfieldDescription.scale = _scales->getTimeScale(); subfieldDescription.validator = NULL; _field->subfieldAdd(subfieldDescription, getSubfieldDiscretization(subfieldName)); @@ -176,7 +185,7 @@ pylith::sources::AuxiliaryFactoryMomentTensorForce::addTimeHistoryValue(void) { const char* subfieldName = "time_history_value"; assert(_defaultDescription); - assert(_normalizer); + assert(_scales); pylith::topology::FieldBase::Description subfieldDescription(*_defaultDescription); subfieldDescription.label = subfieldName; subfieldDescription.alias = subfieldName; diff --git a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc index a9328707a8..17111b3598 100644 --- a/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc +++ b/libsrc/pylith/sources/AuxiliaryFactorySourceTime.cc @@ -23,9 +23,9 @@ #include "pylith/topology/Field.hh" // USES Field #include "pylith/topology/FieldQuery.hh" // HOLDSA FieldQuery #include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/scales/Scales.hh" // USES Scales #include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include "pylith/utils/error.hh" // USES PYLITH_METHOD* #include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* @@ -52,7 +52,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addCenterFrequency(void) { // cente PYLITH_JOURNAL_DEBUG("addCenterFrequency(void)"); const char* subfieldName = "center_frequency"; - const PylithReal timeScale = _normalizer->getTimeScale(); + const PylithReal timeScale = _scales->getTimeScale(); pylith::topology::Field::Description description; description.label = subfieldName; @@ -80,7 +80,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryStartTime(void) { const char* subfieldName = "time_history_start_time"; - assert(_normalizer); + assert(_scales); pylith::topology::Field::Description description; description.label = subfieldName; description.alias = subfieldName; @@ -88,7 +88,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryStartTime(void) { description.numComponents = 1; description.componentNames.resize(1); description.componentNames[0] = subfieldName; - description.scale = _normalizer->getTimeScale(); + description.scale = _scales->getTimeScale(); description.validator = NULL; _field->subfieldAdd(description, getSubfieldDiscretization(subfieldName)); @@ -107,7 +107,7 @@ pylith::sources::AuxiliaryFactorySourceTime::addTimeHistoryValue(void) { const char* subfieldName = "time_history_value"; - assert(_normalizer); + assert(_scales); pylith::topology::Field::Description description; description.label = subfieldName; description.alias = subfieldName; diff --git a/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc index 0b69f3ffcf..57f146caf3 100644 --- a/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc +++ b/libsrc/pylith/sources/DerivedFactoryMomentTensorForce.cc @@ -21,8 +21,7 @@ #include "DerivedFactoryMomentTensorForce.hh" // implementation of object methods #include "pylith/topology/Field.hh" // USES Field - -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional +#include "pylith/scales/Scales.hh" // USES Scales #include "pylith/utils/error.hh" // USES PYLITH_METHOD* #include "pylith/utils/journals.hh" // USES PYLITH_JOURNAL* @@ -51,7 +50,7 @@ pylith::sources::DerivedFactoryMomentTensorForce::addCauchyStress(void) { const char* fieldName = "cauchy_stress"; const char* componentNames[6] = { "stress_xx", "stress_yy", "stress_zz", "stress_xy", "stress_yz", "stress_xz" }; const int stressSize = (3 == _spaceDim) ? 6 : (2 == _spaceDim) ? 4 : 1; - const PylithReal pressureScale = _normalizer->getPressureScale(); + const PylithReal pressureScale = _scales->getRigidityScale(); pylith::topology::Field::Description description; description.label = fieldName; diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 9c87ee9288..53f6335dc0 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -29,6 +29,7 @@ #include "pylith/topology/Field.hh" // USES Field::SubfieldInfo #include "pylith/topology/FieldOps.hh" // USES FieldOps #include "pylith/fekernels/DispVel.hh" // USES DispVel kernels +#include "pylith/scales/Scales.hh" // USES Scales #include "spatialdata/spatialdb/TimeHistory.hh" // USES TimeHistory #include "pylith/utils/error.hh" // USES PYLITH_METHOD_* @@ -116,6 +117,7 @@ pylith::sources::MomentTensorForce::createIntegrator(const pylith::topology::Fie pylith::feassemble::IntegratorDomain* integrator = new pylith::feassemble::IntegratorDomain(this);assert(integrator); integrator->setLabelName(getLabelName()); integrator->setLabelValue(getLabelValue()); + integrator->createLabelDS(solution, solution.getMesh().getDimension()); _setKernelsResidual(integrator, solution); @@ -140,8 +142,8 @@ pylith::sources::MomentTensorForce::createAuxiliaryField(const pylith::topology: assert(_sourceTimeFunction); pylith::sources::AuxiliaryFactoryMomentTensorForce* auxiliaryFactory = _sourceTimeFunction->getAuxiliaryFactory();assert(auxiliaryFactory); - assert(_normalizer); - auxiliaryFactory->initialize(auxiliaryField, *_normalizer, domainMesh.getDimension()); + assert(_scales); + auxiliaryFactory->initialize(auxiliaryField, *_scales, domainMesh.getDimension()); // :ATTENTION: The order for adding subfields must match the order of the auxiliary fields in the FE kernels. @@ -190,13 +192,13 @@ pylith::sources::MomentTensorForce::updateAuxiliaryField(pylith::topology::Field PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField="<getTimeScale(); + const PylithScalar timeScale = _scales->getTimeScale(); - _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale, _normalizer); + _sourceTimeFunction->updateAuxiliaryField(auxiliaryField, t, timeScale); // if (_useTimeHistory) { - // assert(_normalizer); - // const PylithScalar timeScale = _normalizer->getTimeScale(); + // assert(_scales); + // const PylithScalar timeScale = _scales->getTimeScale(); // AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); // } // if diff --git a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc index e4128f697d..0212ebfd43 100644 --- a/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc +++ b/libsrc/pylith/sources/SourceTimeFunctionMomentTensorForce.cc @@ -90,15 +90,14 @@ pylith::sources::SourceTimeFunctionMomentTensorForce::addKernelsUpdateStateVars( void pylith::sources::SourceTimeFunctionMomentTensorForce::updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, - const PylithReal timeScale, - spatialdata::units::Nondimensional* _normalizer) { + const PylithReal timeScale) { PYLITH_METHOD_BEGIN; PYLITH_COMPONENT_DEBUG("updateAuxiliaryField(auxiliaryField"<getTimeScale(); AuxiliaryFactorySourceTime::updateAuxiliaryField(auxiliaryField, t, timeScale, _dbTimeHistory); } // if } diff --git a/libsrc/pylith/sources/TimeHistoryWavelet.hh b/libsrc/pylith/sources/TimeHistoryWavelet.hh index 17bd6252ac..6f6cbf476d 100644 --- a/libsrc/pylith/sources/TimeHistoryWavelet.hh +++ b/libsrc/pylith/sources/TimeHistoryWavelet.hh @@ -95,8 +95,7 @@ public: */ void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, - const PylithReal timeScale, - spatialdata::units::Nondimensional* _normalizer); + const PylithReal timeScale) override; // PRIVATE MEMBERS ///////////////////////////////////////////////////////////////////////////////////////////////// private: diff --git a/m4 b/m4 index e490e14fb1..44921313d4 160000 --- a/m4 +++ b/m4 @@ -1 +1 @@ -Subproject commit e490e14fb13595428d39055304bcf0ee7ab94806 +Subproject commit 44921313d4127dcddaafd6ca45cccb7744793bf0 diff --git a/modulesrc/sources/TimeHistoryWavelet.i b/modulesrc/sources/TimeHistoryWavelet.i index 1f7b2f8143..31cd1c5851 100644 --- a/modulesrc/sources/TimeHistoryWavelet.i +++ b/modulesrc/sources/TimeHistoryWavelet.i @@ -89,8 +89,7 @@ public: */ void updateAuxiliaryField(pylith::topology::Field* auxiliaryField, const PylithReal t, - const PylithReal timeScale, - spatialdata::units::Nondimensional* _normalizer); + const PylithReal timeScale); }; diff --git a/tests/libtests/sources/Makefile.am b/tests/libtests/sources/Makefile.am new file mode 100644 index 0000000000..f49710d792 --- /dev/null +++ b/tests/libtests/sources/Makefile.am @@ -0,0 +1,14 @@ +# ================================================================================================= +# This code is part of PyLith, developed through the Computational Infrastructure +# for Geodynamics (https://github.com/geodynamics/pylith). +# +# Copyright (c) 2010-2025, University of California, Davis and the PyLith Development Team. +# All rights reserved. +# +# See https://mit-license.org/ and LICENSE.md and for license information. +# ================================================================================================= + +# Placeholder for sources tests + + +# End of file diff --git a/tests/mmstests/Makefile.am b/tests/mmstests/Makefile.am index 27b90fa4b0..2b16c85f94 100644 --- a/tests/mmstests/Makefile.am +++ b/tests/mmstests/Makefile.am @@ -11,7 +11,8 @@ SUBDIRS = \ linearelasticity \ incompressibleelasticity \ - poroelasticity + poroelasticity \ + sources # End of file diff --git a/tests/mmstests/sources/Makefile.am b/tests/mmstests/sources/Makefile.am new file mode 100644 index 0000000000..8a93b11ddf --- /dev/null +++ b/tests/mmstests/sources/Makefile.am @@ -0,0 +1,15 @@ +# ================================================================================================= +# This code is part of PyLith, developed through the Computational Infrastructure +# for Geodynamics (https://github.com/geodynamics/pylith). +# +# Copyright (c) 2010-2025, University of California, Davis and the PyLith Development Team. +# All rights reserved. +# +# See https://mit-license.org/ and LICENSE.md and for license information. +# ================================================================================================= + +SUBDIRS = \ + momenttensor-2d + + +# End of file diff --git a/tests/mmstests/sources/momenttensor-2d/Makefile.am b/tests/mmstests/sources/momenttensor-2d/Makefile.am new file mode 100644 index 0000000000..da16df986d --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/Makefile.am @@ -0,0 +1,49 @@ +# ================================================================================================= +# This code is part of PyLith, developed through the Computational Infrastructure +# for Geodynamics (https://github.com/geodynamics/pylith). +# +# Copyright (c) 2010-2025, 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 $(top_srcdir)/tests/check_catch2.am + +MMS_DRIVER = mmstest_sources_momenttensor2d + +TESTS = \ + run_MomentTensorSource2D.sh \ + run_MomentTensorUniformStrain2D.sh + +check_SCRIPTS = $(TESTS) + +check_PROGRAMS = $(MMS_DRIVER) + +mmstest_sources_momenttensor2d_SOURCES = \ + $(top_srcdir)/tests/src/MMSTest.cc \ + $(top_srcdir)/tests/src/driver_catch2.cc \ + TestMomentTensorSource.cc \ + TestCases.cc \ + MomentTensorSource2D.cc \ + MomentTensorUniformStrain2D.cc + +run_%.sh: + echo "#!/bin/bash" > $@ + echo "$(abs_builddir)/$(MMS_DRIVER) [$*]" >> $@ + chmod +x $@ + +dist_noinst_HEADERS = \ + TestMomentTensorSource.hh \ + MomentTensorSource2D.hh \ + MomentTensorUniformStrain2D.hh + +dist_noinst_DATA = \ + data/tri.mesh \ + data/quad.mesh + +export_datadir = $(abs_builddir) +include $(top_srcdir)/tests/data.am + + +# End of file diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc new file mode 100644 index 0000000000..865227c0dc --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc @@ -0,0 +1,424 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "MomentTensorSource2D.hh" // Implementation of test data + +#include "pylith/problems/TimeDependent.hh" // USES TimeDependent +#include "pylith/topology/Field.hh" // USES pylith::topology::Field::Discretization +#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t + +#include "pylith/scales/ElasticityScales.hh" // USES ElasticityScales + +// --------------------------------------------------------------------------------------------------------------------- +namespace pylith { + class _MomentTensorSource2D; +} // pylith + +class pylith::_MomentTensorSource2D { + // Physical constants for the problem + static constexpr double LENGTH_SCALE = 1.0e+4; // 10 km + static constexpr double VELOCITY_SCALE = 3000.0; // 3 km/s (shear wave speed) + static constexpr double TIME_SCALE = LENGTH_SCALE / VELOCITY_SCALE; + static constexpr double DENSITY_SCALE = 2500.0; // kg/m^3 + static constexpr double PRESSURE_SCALE = DENSITY_SCALE * VELOCITY_SCALE * VELOCITY_SCALE; + + static constexpr double TIME_SNAPSHOT = 0.5; // Time for test evaluation + static constexpr double CENTER_FREQUENCY = 1.0; // Hz + static constexpr double TIME_DELAY = 0.5; // s + + // Density + static double density(const double x, + const double y) { + return 2500.0; + } // density + + static const char* density_units(void) { + return "kg/m**3"; + } // density_units + + // Vs + static double vs(const double x, + const double y) { + return 3000.0; + } // vs + + static const char* vs_units(void) { + return "m/s"; + } // vs_units + + // Vp + static double vp(const double x, + const double y) { + return sqrt(3.0)*vs(x,y); + } // vp + + static const char* vp_units(void) { + return "m/s"; + } // vp_units + + // Moment tensor components (in 2D: Mxx, Myy, Mxy, Myx) + // Using an isotropic source: Mxx = Myy = 1, Mxy = Myx = 0 + static double moment_xx(const double x, const double y) { + return 1.0e+15; // Newton-meters (Pa*m^3) + } + static double moment_yy(const double x, const double y) { + return 1.0e+15; + } + static double moment_xy(const double x, const double y) { + return 0.0; + } + static double moment_yx(const double x, const double y) { + return 0.0; + } + static const char* moment_units(void) { + return "Pa*m**3"; + } + + // Time delay + static double time_delay(const double x, const double y) { + return TIME_DELAY; + } + static const char* time_delay_units(void) { + return "s"; + } + + // Center frequency + static double center_frequency(const double x, const double y) { + return CENTER_FREQUENCY; + } + static const char* center_frequency_units(void) { + return "1/s"; + } + + // Solution subfields. + // For this MMS test, we use zero displacement/velocity to isolate testing of the + // moment tensor source term contribution. This verifies that: + // 1. The auxiliary fields are correctly set up + // 2. The kernel correctly computes the source contribution + // 3. The discretization converges at the expected rate + + // Displacement (zero - testing source term only) + static double disp_x(const double x, + const double y, + const double t) { + return 0.0; + } // disp_x + + static double disp_y(const double x, + const double y, + const double t) { + return 0.0; + } // disp_y + + static const char* disp_units(void) { + return "m"; + } // disp_units + + // Velocity (zero) + static double vel_x(const double x, + const double y, + const double t) { + return 0.0; + } // vel_x + + static double vel_y(const double x, + const double y, + const double t) { + return 0.0; + } // vel_y + + static const char* vel_units(void) { + return "m/s"; + } // vel_units + + // Acceleration (zero) + static double acc_x(const double x, + const double y, + const double t) { + return 0.0; + } // acc_x + + static double acc_y(const double x, + const double y, + const double t) { + return 0.0; + } // acc_y + + static const char* acc_units(void) { + return "m/s**2"; + } // acc_units + + static PetscErrorCode solnkernel_disp(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = disp_x(x[0], x[1], t); + s[1] = disp_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_disp + + static PetscErrorCode solnkernel_vel(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = vel_x(x[0], x[1], t); + s[1] = vel_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_vel + + static PetscErrorCode solnkernel_acc(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = acc_x(x[0], x[1], t); + s[1] = acc_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_acc + +public: + + static + TestMomentTensorSource_Data* createData(void) { + TestMomentTensorSource_Data* data = new TestMomentTensorSource_Data();assert(data); + + data->journalName = "MomentTensorSource2D"; + data->isJacobianLinear = true; + data->tolerance = 1.0e-6; + data->allowZeroResidual = true; // Zero solution with source gives non-zero residual + + data->meshFilename = ":UNKNOWN:"; // Set in child class. + data->boundaryLabel = "boundary"; + + // Initialize scales first before using them + pylith::scales::ElasticityScales::setDynamicElasticity(&data->scales, LENGTH_SCALE, VELOCITY_SCALE); + data->formulation = pylith::problems::Physics::DYNAMIC; + + data->t = TIME_SNAPSHOT; + data->dt = 0.05; + + // Material information + data->numAuxSubfields = 3; + static const char* _auxSubfields[3] = {"density", "shear_modulus", "bulk_modulus"}; + data->auxSubfields = _auxSubfields; + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 1), // density + pylith::topology::Field::Discretization(0, 1), // shear_modulus + pylith::topology::Field::Discretization(0, 1), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + data->auxDB.addValue("density", density, density_units()); + data->auxDB.addValue("vp", vp, vp_units()); + data->auxDB.addValue("vs", vs, vs_units()); + data->auxDB.setCoordSys(data->cs); + + data->material.setFormulation(data->formulation); + data->material.useBodyForce(false); + data->rheology.useReferenceState(false); + + data->material.setIdentifier("elasticity"); + data->material.setName("material-id=24"); + data->material.setLabelValue(24); + + // Source information + data->numSourceAuxSubfields = 3; + static const char* _sourceAuxSubfields[3] = {"moment_tensor", "time_delay", "center_frequency"}; + data->sourceAuxSubfields = _sourceAuxSubfields; + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 1), // moment_tensor + pylith::topology::Field::Discretization(0, 1), // time_delay + pylith::topology::Field::Discretization(0, 1), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->sourceAuxDB.addValue("moment_tensor_xx", moment_xx, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_yy", moment_yy, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_xy", moment_xy, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_yx", moment_yx, moment_units()); + data->sourceAuxDB.addValue("time_delay", time_delay, time_delay_units()); + data->sourceAuxDB.addValue("center_frequency", center_frequency, center_frequency_units()); + data->sourceAuxDB.setCoordSys(data->cs); + + data->source.setFormulation(data->formulation); + data->source.setIdentifier("source"); + data->source.setName("moment-tensor-source"); + data->source.setLabelValue(24); + data->source.setSubfieldName("velocity"); // Apply source to velocity field for dynamic problems + + // Boundary conditions + static const PylithInt constrainedDOF[2] = {0, 1}; + static const PylithInt numConstrained = 2; + pylith::bc::DirichletUserFn* bc = NULL; + data->bcs.resize(2); + bc = new pylith::bc::DirichletUserFn();assert(bc); + bc->setSubfieldName("displacement"); + bc->setLabelName("boundary"); + bc->setLabelValue(1); + bc->setConstrainedDOF(constrainedDOF, numConstrained); + bc->setUserFn(solnkernel_disp); + bc->setUserFnDot(solnkernel_vel); + data->bcs[0] = bc; + + bc = new pylith::bc::DirichletUserFn();assert(bc); + bc->setSubfieldName("velocity"); + bc->setLabelName("boundary"); + bc->setLabelValue(1); + bc->setConstrainedDOF(constrainedDOF, numConstrained); + bc->setUserFn(solnkernel_vel); + bc->setUserFnDot(solnkernel_acc); + data->bcs[1] = bc; + + static const pylith::testing::MMSTest::solution_fn _exactSolnFns[2] = { + solnkernel_disp, + solnkernel_vel, + }; + data->exactSolnFns = const_cast(_exactSolnFns); + static const pylith::testing::MMSTest::solution_fn _exactSolnDotFns[2] = { + solnkernel_vel, + solnkernel_acc, + }; + data->exactSolnDotFns = const_cast(_exactSolnDotFns); + + return data; + } // createData + +}; // _MomentTensorSource2D + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorSource2D::TriP1(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorSource2D::createData();assert(data); + + data->meshFilename = "data/tri.mesh"; + data->useAsciiMesh = true; + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(1, 1), // disp + pylith::topology::Field::Discretization(1, 1), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // TriP1 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorSource2D::TriP2(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorSource2D::createData();assert(data); + + data->meshFilename = "data/tri.mesh"; + data->useAsciiMesh = true; + + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // density + pylith::topology::Field::Discretization(0, 2), // shear_modulus + pylith::topology::Field::Discretization(0, 2), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // moment_tensor + pylith::topology::Field::Discretization(0, 2), // time_delay + pylith::topology::Field::Discretization(0, 2), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(2, 2), // disp + pylith::topology::Field::Discretization(2, 2), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // TriP2 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorSource2D::QuadQ1(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorSource2D::createData();assert(data); + + data->meshFilename = "data/quad.mesh"; + data->useAsciiMesh = true; + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(1, 1), // disp + pylith::topology::Field::Discretization(1, 1), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // QuadQ1 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorSource2D::QuadQ2(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorSource2D::createData();assert(data); + + data->meshFilename = "data/quad.mesh"; + data->useAsciiMesh = true; + + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // density + pylith::topology::Field::Discretization(0, 2), // shear_modulus + pylith::topology::Field::Discretization(0, 2), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // moment_tensor + pylith::topology::Field::Discretization(0, 2), // time_delay + pylith::topology::Field::Discretization(0, 2), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(2, 2), // disp + pylith::topology::Field::Discretization(2, 2), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // QuadQ2 + + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.hh b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.hh new file mode 100644 index 0000000000..6cc6e0147c --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.hh @@ -0,0 +1,33 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "TestMomentTensorSource.hh" + +namespace pylith { + class MomentTensorSource2D; +} + +class pylith::MomentTensorSource2D { +public: + + // Data factory methods + + static TestMomentTensorSource_Data* TriP1(void); + + static TestMomentTensorSource_Data* TriP2(void); + + static TestMomentTensorSource_Data* QuadQ1(void); + + static TestMomentTensorSource_Data* QuadQ2(void); + +}; // class MomentTensorSource2D + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc new file mode 100644 index 0000000000..d0db6dd874 --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc @@ -0,0 +1,450 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "MomentTensorUniformStrain2D.hh" // Implementation of test data + +#include "pylith/problems/TimeDependent.hh" // USES TimeDependent +#include "pylith/topology/Field.hh" // USES pylith::topology::Field::Discretization +#include "pylith/utils/journals.hh" // USES pythia::journal::debug_t + +#include "pylith/scales/ElasticityScales.hh" // USES ElasticityScales + +// --------------------------------------------------------------------------------------------------------------------- +namespace pylith { + class _MomentTensorUniformStrain2D; +} // pylith + +/** MMS test with linear (uniform strain) solution for moment tensor source. + * + * The manufactured solution uses a linear displacement field: + * u_x(x,t) = A * x * t + * u_y(x,t) = B * y * t + * + * This gives uniform strain and can be exactly represented by linear elements. + * For linear elasticity (no body force), the residual depends only on the + * inertia and stress divergence terms. Since the strain is uniform, the + * stress divergence is zero. + * + * With the moment tensor source, the weak form residual includes an additional + * source term contribution. For MMS, we verify that the discrete residual + * matches the analytical one. + */ +class pylith::_MomentTensorUniformStrain2D { + static pylith::scales::Scales scales; + + // Physical constants + static constexpr double LENGTH_SCALE = 1.0e+4; // 10 km + static constexpr double VELOCITY_SCALE = 3000.0; // 3 km/s + static constexpr double TIME_SCALE = LENGTH_SCALE / VELOCITY_SCALE; + static constexpr double DENSITY_SCALE = 2500.0; // kg/m^3 + static constexpr double PRESSURE_SCALE = DENSITY_SCALE * VELOCITY_SCALE * VELOCITY_SCALE; + + // Solution parameters (nondimensional) + static constexpr double AMPLITUDE_X = 0.01; // Strain amplitude in x + static constexpr double AMPLITUDE_Y = 0.02; // Strain amplitude in y + static constexpr double TIME_SNAPSHOT = 0.5; // Nondimensional time + + // Source parameters + static constexpr double CENTER_FREQUENCY = 1.0; // Hz (dimensional) + static constexpr double TIME_DELAY = 0.5; // s (dimensional) + static constexpr double MOMENT_MAGNITUDE = 1.0e+15; // Pa*m^3 (dimensional) + + // Density + static double density(const double x, + const double y) { + return 2500.0; + } // density + + static const char* density_units(void) { + return "kg/m**3"; + } // density_units + + // Vs + static double vs(const double x, + const double y) { + return 3000.0; + } // vs + + static const char* vs_units(void) { + return "m/s"; + } // vs_units + + // Vp + static double vp(const double x, + const double y) { + return sqrt(3.0)*vs(x,y); + } // vp + + static const char* vp_units(void) { + return "m/s"; + } // vp_units + + // Moment tensor components (isotropic source in 2D: Mxx = Myy, Mxy = Myx = 0) + static double moment_xx(const double x, const double y) { + return MOMENT_MAGNITUDE; + } + static double moment_yy(const double x, const double y) { + return MOMENT_MAGNITUDE; + } + static double moment_xy(const double x, const double y) { + return 0.0; + } + static double moment_yx(const double x, const double y) { + return 0.0; + } + static const char* moment_units(void) { + return "Pa*m**3"; + } + + // Time delay + static double time_delay(const double x, const double y) { + return TIME_DELAY; + } + static const char* time_delay_units(void) { + return "s"; + } + + // Center frequency + static double center_frequency(const double x, const double y) { + return CENTER_FREQUENCY; + } + static const char* center_frequency_units(void) { + return "1/s"; + } + + // Solution subfields - Linear displacement field (uniform strain) + + // Displacement: u_x = A_x * x * t, u_y = A_y * y * t + static double disp_x(const double x, + const double y, + const double t) { + return AMPLITUDE_X * x * t; + } // disp_x + + static double disp_y(const double x, + const double y, + const double t) { + return AMPLITUDE_Y * y * t; + } // disp_y + + static const char* disp_units(void) { + return "m"; + } // disp_units + + // Velocity: v_x = A_x * x, v_y = A_y * y + static double vel_x(const double x, + const double y, + const double t) { + return AMPLITUDE_X * x; + } // vel_x + + static double vel_y(const double x, + const double y, + const double t) { + return AMPLITUDE_Y * y; + } // vel_y + + static const char* vel_units(void) { + return "m/s"; + } // vel_units + + // Acceleration: a_x = 0, a_y = 0 (constant velocity) + static double acc_x(const double x, + const double y, + const double t) { + return 0.0; + } // acc_x + + static double acc_y(const double x, + const double y, + const double t) { + return 0.0; + } // acc_y + + static const char* acc_units(void) { + return "m/s**2"; + } // acc_units + + static PetscErrorCode solnkernel_disp(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = disp_x(x[0], x[1], t); + s[1] = disp_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_disp + + static PetscErrorCode solnkernel_vel(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = vel_x(x[0], x[1], t); + s[1] = vel_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_vel + + static PetscErrorCode solnkernel_acc(PetscInt spaceDim, + PetscReal t, + const PetscReal x[], + PetscInt numComponents, + PetscScalar* s, + void* context) { + assert(2 == spaceDim); + assert(x); + assert(2 == numComponents); + assert(s); + + s[0] = acc_x(x[0], x[1], t); + s[1] = acc_y(x[0], x[1], t); + + return PETSC_SUCCESS; + } // solnkernel_acc + +public: + + static + TestMomentTensorSource_Data* createData(void) { + TestMomentTensorSource_Data* data = new TestMomentTensorSource_Data();assert(data); + + data->journalName = "MomentTensorUniformStrain2D"; + data->isJacobianLinear = true; + data->tolerance = 1.0e-5; // Slightly larger tolerance for wave solution + data->allowZeroResidual = false; // Nonzero solution should give nonzero residual check + + data->meshFilename = ":UNKNOWN:"; // Set in child class. + data->boundaryLabel = "boundary"; + + // Initialize scales first before using them + pylith::scales::ElasticityScales::setDynamicElasticity(&data->scales, LENGTH_SCALE, VELOCITY_SCALE); + scales.setLengthScale(data->scales.getLengthScale()); + scales.setTimeScale(data->scales.getTimeScale()); + scales.setRigidityScale(data->scales.getRigidityScale()); + scales.setDisplacementScale(data->scales.getDisplacementScale()); + scales.setTemperatureScale(data->scales.getTemperatureScale()); + + data->formulation = pylith::problems::Physics::DYNAMIC; + + data->t = TIME_SNAPSHOT; + data->dt = 0.05; + + // Material information + data->numAuxSubfields = 3; + static const char* _auxSubfields[3] = {"density", "shear_modulus", "bulk_modulus"}; + data->auxSubfields = _auxSubfields; + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 1), // density + pylith::topology::Field::Discretization(0, 1), // shear_modulus + pylith::topology::Field::Discretization(0, 1), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + data->auxDB.addValue("density", density, density_units()); + data->auxDB.addValue("vp", vp, vp_units()); + data->auxDB.addValue("vs", vs, vs_units()); + data->auxDB.setCoordSys(data->cs); + + data->material.setFormulation(data->formulation); + data->material.useBodyForce(false); + data->rheology.useReferenceState(false); + + data->material.setIdentifier("elasticity"); + data->material.setName("material-id=24"); + data->material.setLabelValue(24); + + // Source information + data->numSourceAuxSubfields = 3; + static const char* _sourceAuxSubfields[3] = {"moment_tensor", "time_delay", "center_frequency"}; + data->sourceAuxSubfields = _sourceAuxSubfields; + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 1), // moment_tensor + pylith::topology::Field::Discretization(0, 1), // time_delay + pylith::topology::Field::Discretization(0, 1), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->sourceAuxDB.addValue("moment_tensor_xx", moment_xx, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_yy", moment_yy, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_xy", moment_xy, moment_units()); + data->sourceAuxDB.addValue("moment_tensor_yx", moment_yx, moment_units()); + data->sourceAuxDB.addValue("time_delay", time_delay, time_delay_units()); + data->sourceAuxDB.addValue("center_frequency", center_frequency, center_frequency_units()); + data->sourceAuxDB.setCoordSys(data->cs); + + data->source.setFormulation(data->formulation); + data->source.setIdentifier("source"); + data->source.setName("moment-tensor-source"); + data->source.setLabelValue(24); + data->source.setSubfieldName("velocity"); // Apply source to velocity field for dynamic problems + + // Boundary conditions + static const PylithInt constrainedDOF[2] = {0, 1}; + static const PylithInt numConstrained = 2; + pylith::bc::DirichletUserFn* bc = NULL; + data->bcs.resize(2); + bc = new pylith::bc::DirichletUserFn();assert(bc); + bc->setSubfieldName("displacement"); + bc->setLabelName("boundary"); + bc->setLabelValue(1); + bc->setConstrainedDOF(constrainedDOF, numConstrained); + bc->setUserFn(solnkernel_disp); + bc->setUserFnDot(solnkernel_vel); + data->bcs[0] = bc; + + bc = new pylith::bc::DirichletUserFn();assert(bc); + bc->setSubfieldName("velocity"); + bc->setLabelName("boundary"); + bc->setLabelValue(1); + bc->setConstrainedDOF(constrainedDOF, numConstrained); + bc->setUserFn(solnkernel_vel); + bc->setUserFnDot(solnkernel_acc); + data->bcs[1] = bc; + + static const pylith::testing::MMSTest::solution_fn _exactSolnFns[2] = { + solnkernel_disp, + solnkernel_vel, + }; + data->exactSolnFns = const_cast(_exactSolnFns); + static const pylith::testing::MMSTest::solution_fn _exactSolnDotFns[2] = { + solnkernel_vel, + solnkernel_acc, + }; + data->exactSolnDotFns = const_cast(_exactSolnDotFns); + + return data; + } // createData + +}; // _MomentTensorUniformStrain2D + +// Static member initialization +pylith::scales::Scales pylith::_MomentTensorUniformStrain2D::scales; + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorUniformStrain2D::TriP1(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorUniformStrain2D::createData();assert(data); + + data->meshFilename = "data/tri.mesh"; + data->useAsciiMesh = true; + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(1, 1), // disp + pylith::topology::Field::Discretization(1, 1), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // TriP1 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorUniformStrain2D::TriP2(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorUniformStrain2D::createData();assert(data); + + data->meshFilename = "data/tri.mesh"; + data->useAsciiMesh = true; + + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // density + pylith::topology::Field::Discretization(0, 2), // shear_modulus + pylith::topology::Field::Discretization(0, 2), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // moment_tensor + pylith::topology::Field::Discretization(0, 2), // time_delay + pylith::topology::Field::Discretization(0, 2), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(2, 2), // disp + pylith::topology::Field::Discretization(2, 2), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // TriP2 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorUniformStrain2D::QuadQ1(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorUniformStrain2D::createData();assert(data); + + data->meshFilename = "data/quad.mesh"; + data->useAsciiMesh = true; + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(1, 1), // disp + pylith::topology::Field::Discretization(1, 1), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // QuadQ1 + + +// ------------------------------------------------------------------------------------------------ +pylith::TestMomentTensorSource_Data* +pylith::MomentTensorUniformStrain2D::QuadQ2(void) { + TestMomentTensorSource_Data* data = pylith::_MomentTensorUniformStrain2D::createData();assert(data); + + data->meshFilename = "data/quad.mesh"; + data->useAsciiMesh = true; + + static const pylith::topology::Field::Discretization _auxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // density + pylith::topology::Field::Discretization(0, 2), // shear_modulus + pylith::topology::Field::Discretization(0, 2), // bulk_modulus + }; + data->auxDiscretizations = const_cast(_auxDiscretizations); + + static const pylith::topology::Field::Discretization _sourceAuxDiscretizations[3] = { + pylith::topology::Field::Discretization(0, 2), // moment_tensor + pylith::topology::Field::Discretization(0, 2), // time_delay + pylith::topology::Field::Discretization(0, 2), // center_frequency + }; + data->sourceAuxDiscretizations = const_cast(_sourceAuxDiscretizations); + + data->numSolnSubfields = 2; + static const pylith::topology::Field::Discretization _solnDiscretizations[2] = { + pylith::topology::Field::Discretization(2, 2), // disp + pylith::topology::Field::Discretization(2, 2), // vel + }; + data->solnDiscretizations = const_cast(_solnDiscretizations); + + return data; +} // QuadQ2 + + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.hh b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.hh new file mode 100644 index 0000000000..7799579dd7 --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.hh @@ -0,0 +1,38 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "TestMomentTensorSource.hh" + +namespace pylith { + class MomentTensorUniformStrain2D; +} + +/** MMS test with nonzero uniform strain solution for moment tensor source. + * + * The manufactured solution uses a linear displacement field (uniform strain) + * with the moment tensor source contribution. + */ +class pylith::MomentTensorUniformStrain2D { +public: + + // Data factory methods + + static TestMomentTensorSource_Data* TriP1(void); + + static TestMomentTensorSource_Data* TriP2(void); + + static TestMomentTensorSource_Data* QuadQ1(void); + + static TestMomentTensorSource_Data* QuadQ2(void); + +}; // class MomentTensorUniformStrain2D + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/TestCases.cc b/tests/mmstests/sources/momenttensor-2d/TestCases.cc new file mode 100644 index 0000000000..c03943bf61 --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/TestCases.cc @@ -0,0 +1,70 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, University of California, Davis and the PyLith Development Team. +// All rights reserved. +// +// See https://mit-license.org/ and LICENSE.md and for license information. +// ================================================================================================= + +/** Test cases for TestMomentTensorSource + * + * Note: We only test discretization since the moment tensor source is a forcing + * term that doesn't depend on the solution, so it has no Jacobian contribution. + */ + +#include "TestMomentTensorSource.hh" // USES TestMomentTensorSource + +#include "catch2/catch_test_macros.hpp" + +// ------------------------------------------------------------------------------------------------ +#include "MomentTensorSource2D.hh" + +// TriP1 +TEST_CASE("MomentTensorSource2D::TriP1::testDiscretization", "[MomentTensorSource2D][TriP1][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorSource2D::TriP1()).testDiscretization(); +} + +// TriP2 +TEST_CASE("MomentTensorSource2D::TriP2::testDiscretization", "[MomentTensorSource2D][TriP2][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorSource2D::TriP2()).testDiscretization(); +} + +// QuadQ1 +TEST_CASE("MomentTensorSource2D::QuadQ1::testDiscretization", "[MomentTensorSource2D][QuadQ1][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorSource2D::QuadQ1()).testDiscretization(); +} + +// QuadQ2 +TEST_CASE("MomentTensorSource2D::QuadQ2::testDiscretization", "[MomentTensorSource2D][QuadQ2][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorSource2D::QuadQ2()).testDiscretization(); +} + +// ------------------------------------------------------------------------------------------------ +#include "MomentTensorUniformStrain2D.hh" + +// MomentTensorUniformStrain2D - Nonzero manufactured solution tests + +// TriP1 +TEST_CASE("MomentTensorUniformStrain2D::TriP1::testDiscretization", "[MomentTensorUniformStrain2D][TriP1][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorUniformStrain2D::TriP1()).testDiscretization(); +} + +// TriP2 +TEST_CASE("MomentTensorUniformStrain2D::TriP2::testDiscretization", "[MomentTensorUniformStrain2D][TriP2][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorUniformStrain2D::TriP2()).testDiscretization(); +} + +// QuadQ1 +TEST_CASE("MomentTensorUniformStrain2D::QuadQ1::testDiscretization", "[MomentTensorUniformStrain2D][QuadQ1][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorUniformStrain2D::QuadQ1()).testDiscretization(); +} + +// QuadQ2 +TEST_CASE("MomentTensorUniformStrain2D::QuadQ2::testDiscretization", "[MomentTensorUniformStrain2D][QuadQ2][discretization]") { + pylith::TestMomentTensorSource(pylith::MomentTensorUniformStrain2D::QuadQ2()).testDiscretization(); +} + + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc new file mode 100644 index 0000000000..e4bae1d35e --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc @@ -0,0 +1,204 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "TestMomentTensorSource.hh" // Implementation of class methods + +#include "pylith/problems/TimeDependent.hh" // USES TimeDependent + +#include "pylith/materials/Query.hh" // USES Query + +#include "pylith/topology/Mesh.hh" // USES Mesh +#include "pylith/topology/MeshOps.hh" // USES MeshOps::nondimensionalize() +#include "pylith/topology/Field.hh" // USES Field +#include "pylith/topology/VisitorMesh.hh" // USES VecVisitorMesh +#include "pylith/topology/FieldQuery.hh" // USES FieldQuery +#include "pylith/feassemble/AuxiliaryFactory.hh" // USES AuxiliaryFactory +#include "pylith/problems/SolutionFactory.hh" // USES SolutionFactory +#include "pylith/meshio/MeshIOAscii.hh" // USES MeshIOAscii +#include "pylith/meshio/MeshIOPetsc.hh" // USES MeshIOPetsc +#include "pylith/utils/error.hh" // USES PYLITH_METHOD_BEGIN/END +#include "pylith/utils/journals.hh" // pythia::journal + +#include "pylith/scales/ElasticityScales.hh" // USES ElasticityScales + +// ------------------------------------------------------------------------------------------------ +// Constuctor. +pylith::TestMomentTensorSource::TestMomentTensorSource(TestMomentTensorSource_Data* data) : + _data(data) { + assert(_data); + + GenericComponent::setName(_data->journalName); + _jacobianConvergenceRate = _data->jacobianConvergenceRate; + _tolerance = _data->tolerance; + _isJacobianLinear = _data->isJacobianLinear; + _allowZeroResidual = _data->allowZeroResidual; +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor. +pylith::TestMomentTensorSource::~TestMomentTensorSource(void) { + delete _data;_data = NULL; +} // destructor + + +// ------------------------------------------------------------------------------------------------ +// Initialize objects for test. +void +pylith::TestMomentTensorSource::_initialize(void) { + PYLITH_METHOD_BEGIN; + assert(_mesh); + assert(_data); + + PetscErrorCode err = PETSC_SUCCESS; + + if (_data->useAsciiMesh) { + pylith::meshio::MeshIOAscii iohandler; + iohandler.setFilename(_data->meshFilename); + iohandler.read(_mesh);assert(_mesh); + } else { + if (_data->meshOptions) { + err = PetscOptionsInsertString(NULL, _data->meshOptions);PYLITH_CHECK_ERROR(err); + } // if + pylith::meshio::MeshIOPetsc iohandler; + iohandler.setFilename(_data->meshFilename); + iohandler.read(_mesh);assert(_mesh); + } // if/else + + assert(pylith::topology::MeshOps::getNumCells(*_mesh) > 0); + assert(pylith::topology::MeshOps::getNumVertices(*_mesh) > 0); + + // Set up coordinates. + _mesh->setCoordSys(&_data->cs); + pylith::topology::MeshOps::nondimensionalize(_mesh, _data->scales); + + // Set up material + _data->material.setBulkRheology(&_data->rheology); + _data->material.setAuxiliaryFieldDB(&_data->auxDB); + + for (size_t i = 0; i < _data->numAuxSubfields; ++i) { + const pylith::topology::FieldBase::Discretization& info = _data->auxDiscretizations[i]; + _data->material.setAuxiliarySubfieldDiscretization(_data->auxSubfields[i], info.basisOrder, info.quadOrder, + _data->spaceDim, pylith::topology::FieldBase::DEFAULT_BASIS, + info.feSpace, info.isBasisContinuous); + } // for + + // Set up source + _data->source.setSourceTimeFunction(&_data->sourceTimeFunction); + _data->source.setAuxiliaryFieldDB(&_data->sourceAuxDB); + + for (size_t i = 0; i < _data->numSourceAuxSubfields; ++i) { + const pylith::topology::FieldBase::Discretization& info = _data->sourceAuxDiscretizations[i]; + _data->source.setAuxiliarySubfieldDiscretization(_data->sourceAuxSubfields[i], info.basisOrder, info.quadOrder, + _data->spaceDim, pylith::topology::FieldBase::DEFAULT_BASIS, + info.feSpace, info.isBasisContinuous); + } // for + + // Set up problem. + assert(_problem); + _problem->setScales(_data->scales); + pylith::materials::Material* materials[1] = { &_data->material }; + _problem->setMaterials(materials, 1); + _problem->setBoundaryConditions(_data->bcs.data(), _data->bcs.size()); + pylith::sources::Source* sources[1] = { &_data->source }; + _problem->setSources(sources, 1); + _problem->setStartTime(_data->t); + _problem->setEndTime(_data->t+_data->dt); + _problem->setInitialTimeStep(_data->dt); + _problem->setFormulation(_data->formulation); + + // Set up solution field. + assert(!_solution); + _solution = new pylith::topology::Field(*_mesh);assert(_solution); + _solution->setLabel("solution"); + pylith::problems::SolutionFactory factory(*_solution, _data->scales); + factory.addDisplacement(_data->solnDiscretizations[0]); + assert(pylith::problems::Physics::DYNAMIC == _data->formulation); + assert(2 == _data->numSolnSubfields); + factory.addVelocity(_data->solnDiscretizations[1]); + _problem->setSolution(_solution); + + pylith::testing::MMSTest::_initialize(); + + PYLITH_METHOD_END; +} // _initialize + + +// ------------------------------------------------------------------------------------------------ +// Set functions for computing the exact solution and its time derivative. +void +pylith::TestMomentTensorSource::_setExactSolution(void) { + assert(_data->exactSolnFns); + + const pylith::topology::Field* solution = _problem->getSolution();assert(solution); + + PetscErrorCode err = PETSC_SUCCESS; + PetscDS ds = NULL; + err = DMGetDS(solution->getDM(), &ds);PYLITH_CHECK_ERROR(err); + for (size_t i = 0; i < _data->numSolnSubfields; ++i) { + err = PetscDSSetExactSolution(ds, i, _data->exactSolnFns[i], NULL);PYLITH_CHECK_ERROR(err); + if (_data->exactSolnDotFns) { + err = PetscDSSetExactSolutionTimeDerivative(ds, i, _data->exactSolnDotFns[i], NULL);PYLITH_CHECK_ERROR(err); + } // if + } // for +} // _setExactSolution + + +// ------------------------------------------------------------------------------------------------ +// Constructor +pylith::TestMomentTensorSource_Data::TestMomentTensorSource_Data(void) : + spaceDim(2), + meshFilename(NULL), + meshOptions(NULL), + boundaryLabel(NULL), + useAsciiMesh(true), + + jacobianConvergenceRate(1.0), + tolerance(1.0e-9), + isJacobianLinear(true), + allowZeroResidual(false), + + t(0.0), + dt(0.05), + formulation(pylith::problems::Physics::DYNAMIC), + + numSolnSubfields(0), + solnDiscretizations(NULL), + + numAuxSubfields(0), + auxSubfields(NULL), + auxDiscretizations(NULL), + + numSourceAuxSubfields(0), + sourceAuxSubfields(NULL), + sourceAuxDiscretizations(NULL) { + auxDB.setDescription("material auxiliary field spatial database"); + sourceAuxDB.setDescription("source auxiliary field spatial database"); + cs.setSpaceDim(spaceDim); + + const double lengthScale = 8.0e+3; + const double velocityScale = 3000.0; + pylith::scales::ElasticityScales::setDynamicElasticity(&scales, lengthScale, velocityScale); +} // constructor + + +// ------------------------------------------------------------------------------------------------ +// Destructor +pylith::TestMomentTensorSource_Data::~TestMomentTensorSource_Data(void) { + for (size_t i = 0; i < bcs.size(); ++i) { + delete bcs[i];bcs[i] = NULL; + } // for + +} // destructor + + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh new file mode 100644 index 0000000000..3a02b2275b --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh @@ -0,0 +1,124 @@ +// ================================================================================================= +// This code is part of PyLith, developed through the Computational Infrastructure +// for Geodynamics (https://github.com/geodynamics/pylith). +// +// Copyright (c) 2010-2025, 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 "tests/src/MMSTest.hh" // ISA MMSTEST + +#include "pylith/materials/Elasticity.hh" // USES Elasticity +#include "pylith/materials/IsotropicLinearElasticity.hh" // USES IsotropicLinearElasticity +#include "pylith/sources/MomentTensorForce.hh" // USES MomentTensorForce +#include "pylith/sources/RickerWavelet.hh" // USES RickerWavelet +#include "pylith/bc/DirichletUserFn.hh" // USES DirichletUserFn + +#include "spatialdata/spatialdb/UserFunctionDB.hh" // USES UserFunctionDB +#include "spatialdata/geocoords/CSCart.hh" // USES CSCart +#include "pylith/scales/Scales.hh" // USES Scales + +#include "pylith/problems/Physics.hh" // USES FormulationEnum +#include "pylith/topology/Field.hh" // HASA FieldBase::Discretization + +namespace pylith { + class TestMomentTensorSource; + class TestMomentTensorSource_Data; +} + +/// C++ class for testing moment tensor source using MMS. +class pylith::TestMomentTensorSource : public pylith::testing::MMSTest { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /** Constructor + * + * @param[in] data Data for MMS test. + */ + TestMomentTensorSource(TestMomentTensorSource_Data* data); + + /// Destructor. + ~TestMomentTensorSource(void); + + // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// +protected: + + /// Initialize objects for test. + void _initialize(void); + + /// Set exact solution and time derivative of solution in domain. + void _setExactSolution(void); + + // PROTECTED MEMBERS ////////////////////////////////////////////////////////////////////////// +protected: + + TestMomentTensorSource_Data* _data; ///< Test parameters. + +}; // class TestMomentTensorSource + +// ================================================================================================ +class pylith::TestMomentTensorSource_Data { + // PUBLIC METHODS ///////////////////////////////////////////////////////////////////////////// +public: + + /// Constructor + TestMomentTensorSource_Data(void); + + /// Destructor + ~TestMomentTensorSource_Data(void); + + // PUBLIC MEMBERS ///////////////////////////////////////////////////////////////////////////// +public: + + const char* journalName; ///< Name for MMSTest journals. + int spaceDim; ///< Spatial dimension of domain. + const char* meshFilename; ///< Name of file with ASCII mesh. + const char* meshOptions; ///< Command line options for mesh. + const char* boundaryLabel; ///< Group defining domain boundary. + bool useAsciiMesh; ///< Use MeshIOAscii to read mesh, otherwise use PETSc. + + PylithReal jacobianConvergenceRate; ///< Expected convergence rate for Jacobian (when not linear). + PylithReal tolerance; ///< Tolerance for discretization and residual test. + bool isJacobianLinear; ///< Jacobian should be linear. + bool allowZeroResidual; ///< Allow residual to be exactly zero. + + PylithReal t; ///< Time for MMS solution. + PylithReal dt; ///< Time step in simulation. + spatialdata::geocoords::CSCart cs; ///< Coordinate system. + pylith::scales::Scales scales; ///< Scales for nondimensionalization. + pylith::problems::Physics::FormulationEnum formulation; ///< Time stepping formulation + + pylith::materials::Elasticity material; ///< Material. + pylith::materials::IsotropicLinearElasticity rheology; ///< Bulk rheology for material. + pylith::sources::MomentTensorForce source; ///< Moment tensor source. + pylith::sources::RickerWavelet sourceTimeFunction; ///< Source time function. + std::vector bcs; ///< Dirichlet boundary conditions. + + // Solution field. + size_t numSolnSubfields; ///< Number of solution fields. + pylith::topology::Field::Discretization const* solnDiscretizations; ///< Discretizations for solution fields. + + /// Array of functions providing exact solution. + pylith::testing::MMSTest::solution_fn* exactSolnFns; + + /// Array of functions providing exact solution time derivative. + pylith::testing::MMSTest::solution_fn* exactSolnDotFns; + + // Material auxiliary fields. + size_t numAuxSubfields; ///< Number of auxiliary subfields for materials. + const char** auxSubfields; ///< Names of auxiliary subfields for materials. + pylith::topology::Field::Discretization const* auxDiscretizations; ///< Discretizations for auxiliary subfields. + spatialdata::spatialdb::UserFunctionDB auxDB; ///< Spatial database for auxiliary field. + + // Source auxiliary fields. + size_t numSourceAuxSubfields; ///< Number of auxiliary subfields for source. + const char** sourceAuxSubfields; ///< Names of auxiliary subfields for source. + pylith::topology::Field::Discretization const* sourceAuxDiscretizations; ///< Discretizations for source auxiliary subfields. + spatialdata::spatialdb::UserFunctionDB sourceAuxDB; ///< Spatial database for source auxiliary field. + +}; // TestMomentTensorSource_Data + +// End of file diff --git a/tests/mmstests/sources/momenttensor-2d/data/quad.mesh b/tests/mmstests/sources/momenttensor-2d/data/quad.mesh new file mode 100644 index 0000000000..3c3fc4212a --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/data/quad.mesh @@ -0,0 +1,78 @@ +mesh = { + dimension = 2 + use-index-zero = true + vertices = { + dimension = 2 + count = 16 + coordinates = { + 0 -4.0e+3 -4.0e+3 + 1 -4.0e+3 -2.0e+3 + 2 -4.0e+3 +2.0e+3 + 3 -4.0e+3 +4.0e+3 + 4 -2.0e+3 -4.0e+3 + 5 -2.0e+3 -2.0e+3 + 6 -2.0e+3 +2.0e+3 + 7 -2.0e+3 +4.0e+3 + 8 +2.0e+3 -4.0e+3 + 9 +2.0e+3 -2.0e+3 + 10 +2.0e+3 +2.0e+3 + 11 +2.0e+3 +4.0e+3 + 12 +4.0e+3 -4.0e+3 + 13 +4.0e+3 -2.0e+3 + 14 +4.0e+3 +2.0e+3 + 15 +4.0e+3 +4.0e+3 + } + } + cells = { + count = 9 + num-corners = 4 + simplices = { + 0 0 4 5 1 + 1 1 5 6 2 + 2 2 6 7 3 + 3 4 8 9 5 + 4 5 9 10 6 + 5 6 10 11 7 + 6 8 12 13 9 + 7 9 13 14 10 + 8 10 14 15 11 + } + material-ids = { + 0 24 + 1 24 + 2 24 + 3 24 + 4 24 + 5 24 + 6 24 + 7 24 + 8 24 + } + } + vertex-group = { + name = boundary_vertices + count = 12 + indices = { + 0 1 2 3 4 7 8 11 12 13 14 15 + } + } + face-group = { + name = boundary + count = 12 + indices = { + 0 0 1 + 0 0 4 + 1 1 2 + 2 2 3 + 2 3 7 + 3 4 8 + 5 7 11 + 6 8 12 + 6 12 13 + 7 13 14 + 8 14 15 + 8 11 15 + } + } + +} diff --git a/tests/mmstests/sources/momenttensor-2d/data/tri.mesh b/tests/mmstests/sources/momenttensor-2d/data/tri.mesh new file mode 100644 index 0000000000..c8ca67d822 --- /dev/null +++ b/tests/mmstests/sources/momenttensor-2d/data/tri.mesh @@ -0,0 +1,80 @@ +mesh = { + dimension = 2 + use-index-zero = true + vertices = { + dimension = 2 + count = 12 + coordinates = { + 0 -4.0e+3 -4.0e+3 + 1 -4.0e+3 0.0e+3 + 2 -4.0e+3 +4.0e+3 + 3 -2.0e+3 -2.0e+3 + 4 -2.0e+3 +2.0e+3 + 5 0.0e+3 -4.0e+3 + 6 0.0e+3 +4.0e+3 + 7 +2.0e+3 -2.0e+3 + 8 +2.0e+3 +2.0e+3 + 9 +4.0e+3 -4.0e+3 + 10 +4.0e+3 0.0e+3 + 11 +4.0e+3 +4.0e+3 + } + } + cells = { + count = 14 + num-corners = 3 + simplices = { + 0 0 3 1 + 1 1 3 4 + 2 1 4 2 + 3 0 5 3 + 4 2 4 6 + 5 3 5 7 + 6 3 7 8 + 7 3 8 4 + 8 4 8 6 + 9 5 9 7 + 10 8 11 6 + 11 7 9 10 + 12 7 10 8 + 13 8 10 11 + } + material-ids = { + 0 24 + 1 24 + 2 24 + 3 24 + 4 24 + 5 24 + 6 24 + 7 24 + 8 24 + 9 24 + 10 24 + 11 24 + 12 24 + 13 24 + } + } + vertex-group = { + name = boundary_vertices + count = 8 + indices = { + 0 1 2 5 6 9 10 11 + } + } + face-group = { + name = boundary + count = 8 + indices = { + 0 0 1 + 2 1 2 + 3 0 5 + 4 2 6 + 9 5 9 + 10 6 11 + 11 9 10 + 13 10 11 + } + } + +} From b9330e90fe77d0eb38bb26366e587a3053b73286 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 21 Jan 2026 00:51:59 +0000 Subject: [PATCH 61/65] Updated docs to include source components --- docs/user/components/index.md | 1 + .../sources/AuxSubfieldsMomentTensorForce.md | 29 +++ .../sources/AuxSubfieldsSourceTime.md | 25 +++ .../components/sources/GaussianWavelet.md | 41 ++++ .../components/sources/MomentTensorForce.md | 84 ++++++++ docs/user/components/sources/RickerWavelet.md | 42 ++++ docs/user/components/sources/Source.md | 45 +++++ .../SourceTimeFunctionMomentTensorForce.md | 17 ++ docs/user/components/sources/SquareWavelet.md | 41 ++++ .../components/sources/TimeHistoryWavelet.md | 48 +++++ docs/user/components/sources/index.md | 19 ++ docs/user/physics/index.md | 1 + docs/user/physics/sources/index.md | 44 +++++ .../physics/sources/moment-tensor-force.md | 180 ++++++++++++++++++ 14 files changed, 617 insertions(+) create mode 100644 docs/user/components/sources/AuxSubfieldsMomentTensorForce.md create mode 100644 docs/user/components/sources/AuxSubfieldsSourceTime.md create mode 100644 docs/user/components/sources/GaussianWavelet.md create mode 100644 docs/user/components/sources/MomentTensorForce.md create mode 100644 docs/user/components/sources/RickerWavelet.md create mode 100644 docs/user/components/sources/Source.md create mode 100644 docs/user/components/sources/SourceTimeFunctionMomentTensorForce.md create mode 100644 docs/user/components/sources/SquareWavelet.md create mode 100644 docs/user/components/sources/TimeHistoryWavelet.md create mode 100644 docs/user/components/sources/index.md create mode 100644 docs/user/physics/sources/index.md create mode 100644 docs/user/physics/sources/moment-tensor-force.md diff --git a/docs/user/components/index.md b/docs/user/components/index.md index 1a55b970e3..4a61a02dea 100644 --- a/docs/user/components/index.md +++ b/docs/user/components/index.md @@ -14,6 +14,7 @@ faults/index.md materials/index.md meshio/index.md problems/index.md +sources/index.md testing/index.md topology/index.md utils/index.md diff --git a/docs/user/components/sources/AuxSubfieldsMomentTensorForce.md b/docs/user/components/sources/AuxSubfieldsMomentTensorForce.md new file mode 100644 index 0000000000..a33e7a456e --- /dev/null +++ b/docs/user/components/sources/AuxSubfieldsMomentTensorForce.md @@ -0,0 +1,29 @@ +# AuxSubfieldsMomentTensorForce + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.AuxSubfieldsMomentTensorForce` +:Journal name: `auxsubfieldsmomenttensorforce` + +Container for moment tensor force auxiliary subfields. + +This component defines the discretization for the moment tensor and time delay auxiliary subfields. + +## Pyre Facilities + +* `moment_tensor`: Moment tensor subfield. + - **current value**: 'subfield', from {default} + - **configurable as**: subfield, moment_tensor +* `time_delay`: Time delay subfield. + - **current value**: 'subfield', from {default} + - **configurable as**: subfield, time_delay + +## Example + +Example of setting `AuxSubfieldsMomentTensorForce` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +auxiliary_subfields.moment_tensor.basis_order = 0 +auxiliary_subfields.time_delay.basis_order = 0 +::: + diff --git a/docs/user/components/sources/AuxSubfieldsSourceTime.md b/docs/user/components/sources/AuxSubfieldsSourceTime.md new file mode 100644 index 0000000000..d94c10b940 --- /dev/null +++ b/docs/user/components/sources/AuxSubfieldsSourceTime.md @@ -0,0 +1,25 @@ +# AuxSubfieldsSourceTime + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.AuxSubfieldsSourceTime` +:Journal name: `auxsubfieldssourcetime` + +Container for source time function auxiliary subfields. + +This component defines the discretization for the center frequency auxiliary subfield used by wavelet source time functions. + +## Pyre Facilities + +* `center_frequency`: Center frequency subfield. + - **current value**: 'subfield', from {default} + - **configurable as**: subfield, center_frequency + +## Example + +Example of setting `AuxSubfieldsSourceTime` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +::: + diff --git a/docs/user/components/sources/GaussianWavelet.md b/docs/user/components/sources/GaussianWavelet.md new file mode 100644 index 0000000000..82fdc72eaa --- /dev/null +++ b/docs/user/components/sources/GaussianWavelet.md @@ -0,0 +1,41 @@ +# GaussianWavelet + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.GaussianWavelet` +:Journal name: `gaussianwavelet` + +Gaussian wavelet source time function. + +The Gaussian wavelet provides a smooth pulse. + +The wavelet is defined as: + +$S(t) = \frac{1}{2\pi^2 f_0^2} \exp\left(-\pi^2 f_0^2 (t-t_d)^2\right)$ + +where $f_0$ is the center frequency and $t_d$ is the time delay. + +Implements `SourceTimeFunctionMomentTensorForce`. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for source time function parameters. + - **current value**: 'auxiliary_subfields', from {file='...', line=..., function='__set__'} + - **configurable as**: auxiliary_subfields + +## Example + +Example of setting `GaussianWavelet` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +source_time_function = pylith.sources.GaussianWavelet + +# Center frequency specified in the auxiliary field database +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.0*s, 5.0] + +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +::: + diff --git a/docs/user/components/sources/MomentTensorForce.md b/docs/user/components/sources/MomentTensorForce.md new file mode 100644 index 0000000000..818b23622b --- /dev/null +++ b/docs/user/components/sources/MomentTensorForce.md @@ -0,0 +1,84 @@ +# MomentTensorForce + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.MomentTensorForce` +:Journal name: `momenttensorforce` + +Moment tensor point source. + +This component implements a point source using a moment tensor representation. +The moment tensor describes the equivalent body forces of a seismic source. +The temporal evolution of the source is controlled by a source time function. + +Implements `Source`. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for auxiliary subfields. + - **current value**: 'auxiliary_subfields', from {file='...', line=..., function='__set__'} + - **configurable as**: auxiliary_subfields +* `db_auxiliary_field`: Database for source parameters. + - **current value**: 'simpledb', from {default} + - **configurable as**: simpledb, db_auxiliary_field +* `derived_subfields`: Discretization of derived subfields. + - **current value**: 'emptybin', from {default} + - **configurable as**: emptybin, derived_subfields +* `observers`: Observers (e.g., output). + - **current value**: 'singlephysicsobserver', from {default} + - **configurable as**: singlephysicsobserver, observers +* `reader`: Reader for source points list. + - **current value**: 'pointslist', from {default} + - **configurable as**: pointslist, reader +* `source_time_function`: Source time function for moment tensor force. + - **current value**: 'timehistorywavelet', from {default} + - **configurable as**: timehistorywavelet, source_time_function + +## Pyre Properties + +* `description`=\: Descriptive label for source. + - **default value**: '' + - **current value**: '', from {default} + - **validator**: +* `field`=\: Solution subfield associated with source. + - **default value**: 'displacement' + - **current value**: 'displacement', from {default} +* `label`=\: Name of label for source. + - **default value**: 'source-id' + - **current value**: 'source-id', from {default} +* `label_value`=\: Value of label identifying source. + - **default value**: 1 + - **current value**: 1, from {default} + +## Example + +Example of setting `MomentTensorForce` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem] +sources = [source] +sources.source = pylith.sources.MomentTensorForce + +[pylithapp.problem.sources.source] +description = Earthquake source +label_value = 2 + +# Specify source locations +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 + +# Use Ricker wavelet source time function +source_time_function = pylith.sources.RickerWavelet + +# Source parameters (moment tensor and time delay) +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.0*s, 5.0] + +# Discretization of auxiliary subfields +auxiliary_subfields.moment_tensor.basis_order = 0 +auxiliary_subfields.time_delay.basis_order = 0 +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +::: + diff --git a/docs/user/components/sources/RickerWavelet.md b/docs/user/components/sources/RickerWavelet.md new file mode 100644 index 0000000000..9443d5a040 --- /dev/null +++ b/docs/user/components/sources/RickerWavelet.md @@ -0,0 +1,42 @@ +# RickerWavelet + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.RickerWavelet` +:Journal name: `rickerwavelet` + +Ricker wavelet source time function. + +The Ricker wavelet (Mexican hat wavelet) is the negative normalized second derivative of a Gaussian. +It is commonly used as a source time function in seismic wave propagation studies. + +The wavelet is defined as: + +$S(t) = \left(1 - 2\pi^2 f_0^2 (t-t_d)^2\right) \exp\left(-\pi^2 f_0^2 (t-t_d)^2\right)$ + +where $f_0$ is the center frequency and $t_d$ is the time delay. + +Implements `SourceTimeFunctionMomentTensorForce`. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for source time function parameters. + - **current value**: 'auxiliary_subfields', from {file='...', line=..., function='__set__'} + - **configurable as**: auxiliary_subfields + +## Example + +Example of setting `RickerWavelet` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +source_time_function = pylith.sources.RickerWavelet + +# Center frequency specified in the auxiliary field database +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.0*s, 5.0] + +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +::: + diff --git a/docs/user/components/sources/Source.md b/docs/user/components/sources/Source.md new file mode 100644 index 0000000000..060a404c78 --- /dev/null +++ b/docs/user/components/sources/Source.md @@ -0,0 +1,45 @@ +# Source + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.Source` +:Journal name: `source` + +Abstract base class for point sources. + +This is the base class for all point source implementations in PyLith. +Point sources are used to specify internal forcing terms at discrete points within the domain. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for auxiliary subfields. + - **current value**: 'emptybin', from {default} + - **configurable as**: emptybin, auxiliary_subfields +* `db_auxiliary_field`: Database for source parameters. + - **current value**: 'simpledb', from {default} + - **configurable as**: simpledb, db_auxiliary_field +* `derived_subfields`: Discretization of derived subfields. + - **current value**: 'emptybin', from {default} + - **configurable as**: emptybin, derived_subfields +* `observers`: Observers (e.g., output). + - **current value**: 'singlephysicsobserver', from {default} + - **configurable as**: singlephysicsobserver, observers +* `reader`: Reader for source points list. + - **current value**: 'pointslist', from {default} + - **configurable as**: pointslist, reader + +## Pyre Properties + +* `description`=\: Descriptive label for source. + - **default value**: '' + - **current value**: '', from {default} + - **validator**: +* `field`=\: Solution subfield associated with source. + - **default value**: 'displacement' + - **current value**: 'displacement', from {default} +* `label`=\: Name of label for source. + - **default value**: 'source-id' + - **current value**: 'source-id', from {default} +* `label_value`=\: Value of label identifying source. + - **default value**: 1 + - **current value**: 1, from {default} + diff --git a/docs/user/components/sources/SourceTimeFunctionMomentTensorForce.md b/docs/user/components/sources/SourceTimeFunctionMomentTensorForce.md new file mode 100644 index 0000000000..46d8ed60dd --- /dev/null +++ b/docs/user/components/sources/SourceTimeFunctionMomentTensorForce.md @@ -0,0 +1,17 @@ +# SourceTimeFunctionMomentTensorForce + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.SourceTimeFunctionMomentTensorForce` +:Journal name: `sourcetimefunctionmomenttensorforce` + +Abstract base class for source time functions. + +This is the base class for source time functions used with moment tensor force sources. +Derived classes implement specific wavelet types. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for physical properties and state variables. + - **current value**: 'emptybin', from {default} + - **configurable as**: emptybin, auxiliary_subfields + diff --git a/docs/user/components/sources/SquareWavelet.md b/docs/user/components/sources/SquareWavelet.md new file mode 100644 index 0000000000..046e3d0eee --- /dev/null +++ b/docs/user/components/sources/SquareWavelet.md @@ -0,0 +1,41 @@ +# SquareWavelet + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.SquareWavelet` +:Journal name: `squarewavelet` + +Square wavelet (step function) source time function. + +The square wavelet is a Heaviside step function that activates the source at the time delay. + +The wavelet is defined as: + +$S(t) = \begin{cases} 0 & t < t_d \\ 1 & t \geq t_d \end{cases}$ + +where $t_d$ is the time delay. + +Implements `SourceTimeFunctionMomentTensorForce`. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for source time function parameters. + - **current value**: 'auxiliary_subfields', from {file='...', line=..., function='__set__'} + - **configurable as**: auxiliary_subfields + +## Example + +Example of setting `SquareWavelet` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +source_time_function = pylith.sources.SquareWavelet + +# Source parameters specified in the auxiliary field database +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.5*s, 1.0] + +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +::: + diff --git a/docs/user/components/sources/TimeHistoryWavelet.md b/docs/user/components/sources/TimeHistoryWavelet.md new file mode 100644 index 0000000000..44890fe64a --- /dev/null +++ b/docs/user/components/sources/TimeHistoryWavelet.md @@ -0,0 +1,48 @@ +# TimeHistoryWavelet + +% WARNING: Do not edit; this is a generated file! +:Full name: `pylith.sources.TimeHistoryWavelet` +:Journal name: `timehistorywavelet` + +User-specified time history source time function. + +This source time function allows specification of an arbitrary wavelet shape using a time history database. +The time history should contain normalized amplitudes (typically between 0 and 1) as a function of time. + +Implements `SourceTimeFunctionMomentTensorForce`. + +## Pyre Facilities + +* `auxiliary_subfields`: Discretization information for source time function parameters. + - **current value**: 'auxiliary_subfields', from {file='...', line=..., function='__set__'} + - **configurable as**: auxiliary_subfields +* `time_history`: Time history with normalized amplitude as a function of time. + - **current value**: 'nullcomponent', from {default} + - **configurable as**: nullcomponent, time_history + +## Pyre Properties + +* `use_time_history`=\: Use time history term in time-dependent expression. + - **default value**: True + - **current value**: True, from {default} + +## Example + +Example of setting `TimeHistoryWavelet` Pyre properties and facilities in a parameter file. + +:::{code-block} cfg +[pylithapp.problem.sources.source] +source_time_function = pylith.sources.TimeHistoryWavelet + +# Specify time history database +source_time_function.time_history = spatialdata.spatialdb.TimeHistory +source_time_function.time_history.description = Source time history +source_time_function.time_history.filename = wavelet.timedb + +# Source parameters specified in the auxiliary field database +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_history_start_time] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.0*s] +::: + diff --git a/docs/user/components/sources/index.md b/docs/user/components/sources/index.md new file mode 100644 index 0000000000..e57deaf671 --- /dev/null +++ b/docs/user/components/sources/index.md @@ -0,0 +1,19 @@ +# sources + +% WARNING: Do not edit; this is a generated file. + +:::{toctree} +--- +maxdepth: 1 +--- +Source.md +MomentTensorForce.md +SourceTimeFunctionMomentTensorForce.md +RickerWavelet.md +GaussianWavelet.md +SquareWavelet.md +TimeHistoryWavelet.md +AuxSubfieldsMomentTensorForce.md +AuxSubfieldsSourceTime.md +::: + diff --git a/docs/user/physics/index.md b/docs/user/physics/index.md index 8bbbaf27b0..839d69d6d6 100644 --- a/docs/user/physics/index.md +++ b/docs/user/physics/index.md @@ -5,4 +5,5 @@ materials/index.md bc/index.md faults/index.md +sources/index.md ::: diff --git a/docs/user/physics/sources/index.md b/docs/user/physics/sources/index.md new file mode 100644 index 0000000000..1390d526aa --- /dev/null +++ b/docs/user/physics/sources/index.md @@ -0,0 +1,44 @@ +(sec-user-physics-sources)= +# Point Sources + +Point sources provide a mechanism for specifying internal sources within the domain, such as moment tensor sources for earthquake simulations or other force sources. +These sources are implemented at discrete points rather than on surfaces like boundary conditions or faults. + +## Point Source Implementation + +Point sources in PyLith are implemented using a moment tensor force representation. +The source is specified at discrete points in the domain, and the moment tensor components define the force couples applied at each point. +The temporal behavior of the source is controlled by a source time function, which can be an analytical wavelet or a user-specified time history. + +## Specifying Point Sources + +There are three basic steps in specifying point sources: + +1. Create a file specifying the locations of the point sources. +2. Set the parameters for each source using `cfg` files or command line arguments. +3. Specify the spatial variation in source parameters (moment tensor, time delay) using a spatial database. +4. Select a source time function and specify its parameters. + +## Arrays of Source Components + +A dynamic array of source components associates a name (string) with each source. +The default source is `MomentTensorForce`. + +```{code-block} cfg +--- +caption: Array of sources in a `cfg` file. +--- +[pylithapp.problem] +# Array of point sources +sources = [source1, source2] + +# Default source is MomentTensorForce +# Both sources use the default type +``` + +## Source Implementations + +:::{toctree} +moment-tensor-force.md +::: + diff --git a/docs/user/physics/sources/moment-tensor-force.md b/docs/user/physics/sources/moment-tensor-force.md new file mode 100644 index 0000000000..1922926fcc --- /dev/null +++ b/docs/user/physics/sources/moment-tensor-force.md @@ -0,0 +1,180 @@ +(sec-user-physics-moment-tensor-force)= +# Moment Tensor Force (`MomentTensorForce`) + +The `MomentTensorForce` component implements point sources using a moment tensor representation. +This is commonly used in seismology to represent earthquake sources or other internal force sources. + +A moment tensor describes the equivalent body forces of a seismic source. +In 2D, the moment tensor has 4 independent components (symmetric $2 \times 2$ tensor), while in 3D it has 6 independent components (symmetric $3 \times 3$ tensor). + +The temporal evolution of the source is controlled by a source time function, which multiplies the moment tensor amplitude at each time step. +PyLith provides several built-in source time functions as well as support for user-defined time histories. + +## Source Parameters + +The source parameters include the moment tensor components and a time delay. +The time delay allows offsetting the source time function for each point source, enabling simulation of rupture propagation. + +```{table} Values in the auxiliary field spatial database for MomentTensorForce. +:name: tab:source:momenttensorforce:auxiliary +| Subfield | Components (2D) | Components (3D) | +|:-------------------|:---------------------------|:-------------------------------------| +| `moment_tensor` | xx, yy, xy, zz | xx, yy, zz, xy, yz, xz | +| `time_delay` | -- | -- | +``` + +## Source Points File + +The locations of point sources are specified in a text file. +The file contains the coordinates of each source point along with an optional name identifier. + +```{code-block} text +--- +caption: Example source points file format. +--- +# Comment lines start with # +# x y [z] name +0.0 0.0 source1 +1000.0 500.0 source2 +``` + +:::{seealso} +See [`MomentTensorForce` Component](../../components/sources/MomentTensorForce.md) for the Pyre properties and facilities and configuration examples. +::: + +## Source Time Functions + +The source time function controls the temporal evolution of the moment tensor force. +PyLith supports the following source time functions: + +:`RickerWavelet`: A Ricker wavelet (Mexican hat wavelet) commonly used in seismic modeling. +:`GaussianWavelet`: A Gaussian wavelet. +:`SquareWavelet`: A step function (Heaviside function). +:`TimeHistoryWavelet`: A user-specified time function from a time history database. + +### Ricker Wavelet (`RickerWavelet`) + +The Ricker wavelet, also known as the Mexican hat wavelet, is the negative normalized second derivative of a Gaussian function. +It is commonly used as a source time function in seismic wave propagation studies because it has a well-defined frequency content and compact time duration. + +The Ricker wavelet is defined as: +% +\begin{gather} + S(t) = \left(1 - 2\pi^2 f_0^2 (t-t_d)^2\right) \exp\left(-\pi^2 f_0^2 (t-t_d)^2\right) +\end{gather} +% +where $f_0$ is the center frequency and $t_d$ is the time delay. + +```{table} Values in the auxiliary field spatial database for RickerWavelet. +:name: tab:source:rickerwavelet:auxiliary +| Subfield | Description | +|:--------------------|:-----------------------------------------| +| `center_frequency` | Center frequency of the wavelet ($f_0$) | +``` + +:::{seealso} +See [`RickerWavelet` Component](../../components/sources/RickerWavelet.md) for the Pyre properties and facilities and configuration examples. +::: + +### Gaussian Wavelet (`GaussianWavelet`) + +The Gaussian wavelet provides a smooth pulse. +It is defined as: +% +\begin{gather} + S(t) = \frac{1}{2\pi^2 f_0^2} \exp\left(-\pi^2 f_0^2 (t-t_d)^2\right) +\end{gather} +% +where $f_0$ is the center frequency and $t_d$ is the time delay. + +:::{note} +The implementation uses the negative of the second derivative of a Gaussian. +::: + +```{table} Values in the auxiliary field spatial database for GaussianWavelet. +:name: tab:source:gaussianwavelet:auxiliary +| Subfield | Description | +|:--------------------|:-----------------------------------------| +| `center_frequency` | Center frequency of the wavelet ($f_0$) | +``` + +:::{seealso} +See [`GaussianWavelet` Component](../../components/sources/GaussianWavelet.md) for the Pyre properties and facilities and configuration examples. +::: + +### Square Wavelet (`SquareWavelet`) + +The square wavelet is a step function (Heaviside function) that activates the source at the time delay: +% +\begin{gather} + S(t) = \left\{ \begin{array}{cc} + 0 & t < t_d \\ + 1 & t \geq t_d + \end{array}\right. +\end{gather} +% +where $t_d$ is the time delay. + +```{table} Values in the auxiliary field spatial database for SquareWavelet. +:name: tab:source:squarewavelet:auxiliary +| Subfield | Description | +|:--------------------|:-----------------------------------------| +| `center_frequency` | Not used (placeholder for consistency) | +``` + +:::{seealso} +See [`SquareWavelet` Component](../../components/sources/SquareWavelet.md) for the Pyre properties and facilities and configuration examples. +::: + +### Time History Wavelet (`TimeHistoryWavelet`) + +The time history wavelet allows specification of an arbitrary source time function using a time history database. +The time history should contain normalized amplitudes (typically between 0 and 1) as a function of time. + +```{table} Values in the auxiliary field spatial database for TimeHistoryWavelet. +:name: tab:source:timehistorywavelet:auxiliary +| Subfield | Description | +|:---------------------------|:----------------------------------------------| +| `time_history_start_time` | Start time for the time history | +``` + +:::{seealso} +See [`TimeHistoryWavelet` Component](../../components/sources/TimeHistoryWavelet.md) for the Pyre properties and facilities and configuration examples. +::: + +## Example Configuration + +The following example shows how to configure a moment tensor point source with a Ricker wavelet: + +```{code-block} cfg +--- +caption: Example configuration for a moment tensor point source with Ricker wavelet. +--- +[pylithapp.problem] +sources = [source] +sources.source = pylith.sources.MomentTensorForce + +[pylithapp.problem.sources.source] +description = Earthquake source +label_value = 2 + +# Specify source locations +reader.filename = source_sites.txt +reader.coordsys = spatialdata.geocoords.CSCart +reader.coordsys.space_dim = 2 + +# Use Ricker wavelet source time function +source_time_function = pylith.sources.RickerWavelet + +# Source parameters (moment tensor and time delay) +db_auxiliary_field = spatialdata.spatialdb.UniformDB +db_auxiliary_field.description = Source properties +db_auxiliary_field.values = [moment_tensor_xx, moment_tensor_yy, moment_tensor_xy, moment_tensor_zz, time_delay, center_frequency] +db_auxiliary_field.data = [1.0e12*Pa*s, 1.0e12*Pa*s, 0.0*Pa*s, 1.0e12*Pa*s, 0.0*s, 5.0] + +# Discretization of auxiliary subfields +auxiliary_subfields.moment_tensor.basis_order = 0 +auxiliary_subfields.time_delay.basis_order = 0 +source_time_function.auxiliary_subfields.center_frequency.basis_order = 0 +``` + From 3e047e15a11ba54538987ca2c067b428e6605897 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Wed, 21 Jan 2026 21:44:20 +0000 Subject: [PATCH 62/65] Fixed old include --- libsrc/pylith/sources/MomentTensorForce.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/pylith/sources/MomentTensorForce.cc b/libsrc/pylith/sources/MomentTensorForce.cc index 53f6335dc0..acae57cad2 100644 --- a/libsrc/pylith/sources/MomentTensorForce.cc +++ b/libsrc/pylith/sources/MomentTensorForce.cc @@ -36,7 +36,6 @@ #include "pylith/utils/journals.hh" // USES PYLITH_COMPONENT_* #include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys -#include "spatialdata/units/Nondimensional.hh" // USES Nondimensional #include // USES typeid() From 26203b4cc923341cbe862353610a4a73e1ed047a Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 22 Jan 2026 20:49:34 +0000 Subject: [PATCH 63/65] fixes to ensure CI tests work --- portinfo | 124 ++++++++++++++++++++ pylith/Makefile.am | 2 - tests/pytests/sources/TestPointForce.py | 41 ------- tests/pytests/sources/TestWellboreSource.py | 41 ------- tests/pytests/sources/__init__.py | 2 - 5 files changed, 124 insertions(+), 86 deletions(-) create mode 100644 portinfo delete mode 100644 tests/pytests/sources/TestPointForce.py delete mode 100644 tests/pytests/sources/TestWellboreSource.py diff --git a/portinfo b/portinfo new file mode 100644 index 0000000000..801c94f77d --- /dev/null +++ b/portinfo @@ -0,0 +1,124 @@ +/* portinfo. Generated from portinfo.in by configure. */ +/* portinfo.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* define if the compiler supports basic C++14 syntax */ +#define HAVE_CXX14 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `hdf5' library (-lhdf5). */ +#define HAVE_LIBHDF5 1 + +/* Define to 1 if you have the `proj' library (-lproj). */ +#define HAVE_LIBPROJ 1 + +/* Defined if you have NETCDF4 support */ +#define HAVE_NETCDF4 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Define NETCDF4 version */ +#define NETCDF4_VERSION "4.9.3" + +/* Name of package */ +#define PACKAGE "pylith" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "https://geodynamics.org/resources/pylith" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PyLith" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PyLith 5.0.0dev" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "pylith" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "5.0.0dev" + +/* Define PyLith doi */ +#define PYLITH_DOI "10.5281/zenodo.14635926" + +/* Define GIT branch for package source. */ +#define PYLITH_GIT_BRANCH "point_source_merge" + +/* Define date of GIT commit for package source. */ +#define PYLITH_GIT_DATE "2026-01-21 00:51:59 +0000" + +/* Define GIT hash for package source. */ +#define PYLITH_GIT_HASH "b9330e90fe77d0eb38bb26366e587a3053b73286" + +/* Define git revision commit for package source. */ +#define PYLITH_GIT_REVISION "v4.2.0-222-gb9330e90f" + +/* Set to 0 if source is from GIT, 1 otherwise. */ +#define PYLITH_RELEASE_VERSION 0 + +/* Define PyLith version */ +#define PYLITH_VERSION "5.0.0dev" + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "5.0.0dev" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define __FUNCTION_NAME__ to __func__. */ +#define __FUNCTION_NAME__ __PRETTY_FUNCTION__ diff --git a/pylith/Makefile.am b/pylith/Makefile.am index 1eebf9ad1a..dcb8525617 100644 --- a/pylith/Makefile.am +++ b/pylith/Makefile.am @@ -139,8 +139,6 @@ EXTRA_DIST = \ scales/QuasistaticPoroelasticity.py \ scales/QuasistaticElasticity.py \ scales/__init__.py \ - sources/WellboreSource.py \ - sources/SquarePulseSource.py \ sources/SourceTimeFunctionMomentTensorForce.py \ sources/Source.py \ sources/SquareWavelet.py \ diff --git a/tests/pytests/sources/TestPointForce.py b/tests/pytests/sources/TestPointForce.py deleted file mode 100644 index 25004e97d9..0000000000 --- a/tests/pytests/sources/TestPointForce.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env nemesis -# -# ====================================================================== -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2022 University of California, Davis -# -# See LICENSE.md for license information. -# -# ====================================================================== -# -# @file tests/pytests/sources/TestPointForce.py -# -# @brief Unit testing of Python TestPointForce object. - -import unittest - -from pylith.testing.UnitTestApp import TestComponent -from pylith.sources.Source import (PointForce, source) - - -class TestPointForce(TestComponent): - """Unit testing of PointForce object. - """ - _class = PointForce - _factory = source - - -if __name__ == "__main__": - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestPointForce)) - unittest.TextTestRunner(verbosity=2).run(suite) - - -# End of file diff --git a/tests/pytests/sources/TestWellboreSource.py b/tests/pytests/sources/TestWellboreSource.py deleted file mode 100644 index 64e66a6553..0000000000 --- a/tests/pytests/sources/TestWellboreSource.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env nemesis -# -# ====================================================================== -# -# Brad T. Aagaard, U.S. Geological Survey -# Charles A. Williams, GNS Science -# Matthew G. Knepley, University at Buffalo -# -# This code was developed as part of the Computational Infrastructure -# for Geodynamics (http://geodynamics.org). -# -# Copyright (c) 2010-2022 University of California, Davis -# -# See LICENSE.md for license information. -# -# ====================================================================== -# -# @file tests/pytests/sources/TestWellboreSource.py -# -# @brief Unit testing of Python TestWellboreSource object. - -import unittest - -from pylith.testing.UnitTestApp import TestComponent -from pylith.sources.Source import (WellboreSource, source) - - -class TestWellboreSource(TestComponent): - """Unit testing of WellboreSource object. - """ - _class = WellboreSource - _factory = source - - -if __name__ == "__main__": - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestWellboreSource)) - unittest.TextTestRunner(verbosity=2).run(suite) - - -# End of file diff --git a/tests/pytests/sources/__init__.py b/tests/pytests/sources/__init__.py index 38b6d26c09..7911cd671b 100644 --- a/tests/pytests/sources/__init__.py +++ b/tests/pytests/sources/__init__.py @@ -1,4 +1,2 @@ from .TestSource import TestSource -from .TestWellboreSource import TestWellboreSource from .TestMomentTensorForce import TestMomentTensorForce -from .TestPointForce import TestPointForce From cb7867c0ab41af597c47ee9bee47900021e087ba Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 22 Jan 2026 21:40:35 +0000 Subject: [PATCH 64/65] source mms test passes --- libsrc/pylith/sources/Source.cc | 4 +++- .../sources/momenttensor-2d/MomentTensorSource2D.cc | 7 +++++++ .../momenttensor-2d/TestMomentTensorSource.cc | 12 +++++++++++- .../momenttensor-2d/TestMomentTensorSource.hh | 5 +++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libsrc/pylith/sources/Source.cc b/libsrc/pylith/sources/Source.cc index 483d0438ad..9ea57f1385 100644 --- a/libsrc/pylith/sources/Source.cc +++ b/libsrc/pylith/sources/Source.cc @@ -211,12 +211,14 @@ pylith::sources::Source::locateSource(const pylith::topology::Field& solution, PetscIS cellIS; err = DMLabelGetStratumIS(label, labelValue, &cellIS);PYLITH_CHECK_ERROR(err); if (cellIS) { + PetscInt numCells; const PetscInt* cells; + err = ISGetSize(cellIS, &numCells);PYLITH_CHECK_ERROR(err); err = ISGetIndices(cellIS, &cells);PYLITH_CHECK_ERROR(err); for (PetscInt p = 0; p < pcs; ++p) { PetscInt loc; if (_cellNumber[p] < 0) continue; - err = PetscFindInt(_cellNumber[p], pcs, cells, &loc);PYLITH_CHECK_ERROR(err); + err = PetscFindInt(_cellNumber[p], numCells, cells, &loc);PYLITH_CHECK_ERROR(err); assert(loc >= 0); _cellNumber[p] = loc; } diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc index 865227c0dc..5c6ccfbe18 100644 --- a/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorSource2D.cc @@ -278,6 +278,13 @@ class pylith::_MomentTensorSource2D { data->source.setLabelValue(24); data->source.setSubfieldName("velocity"); // Apply source to velocity field for dynamic problems + // Source point coordinates (center of domain) + data->numSourcePoints = 1; + static const PylithReal _sourcePointCoords[2] = {0.0, 0.0}; // Center of domain + data->sourcePointCoords = _sourcePointCoords; + static const char* _sourcePointNames[1] = {"source_point"}; + data->sourcePointNames = _sourcePointNames; + // Boundary conditions static const PylithInt constrainedDOF[2] = {0, 1}; static const PylithInt numConstrained = 2; diff --git a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc index e4bae1d35e..2ad96dccdd 100644 --- a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc +++ b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.cc @@ -96,6 +96,12 @@ pylith::TestMomentTensorSource::_initialize(void) { _data->source.setSourceTimeFunction(&_data->sourceTimeFunction); _data->source.setAuxiliaryFieldDB(&_data->sourceAuxDB); + // Set source point coordinates + if (_data->numSourcePoints > 0 && _data->sourcePointCoords && _data->sourcePointNames) { + _data->source.setPoints(_data->sourcePointCoords, _data->numSourcePoints, _data->spaceDim, + _data->sourcePointNames, _data->numSourcePoints); + } // if + for (size_t i = 0; i < _data->numSourceAuxSubfields; ++i) { const pylith::topology::FieldBase::Discretization& info = _data->sourceAuxDiscretizations[i]; _data->source.setAuxiliarySubfieldDiscretization(_data->sourceAuxSubfields[i], info.basisOrder, info.quadOrder, @@ -180,7 +186,11 @@ pylith::TestMomentTensorSource_Data::TestMomentTensorSource_Data(void) : numSourceAuxSubfields(0), sourceAuxSubfields(NULL), - sourceAuxDiscretizations(NULL) { + sourceAuxDiscretizations(NULL), + + numSourcePoints(0), + sourcePointCoords(NULL), + sourcePointNames(NULL) { auxDB.setDescription("material auxiliary field spatial database"); sourceAuxDB.setDescription("source auxiliary field spatial database"); cs.setSpaceDim(spaceDim); diff --git a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh index 3a02b2275b..ec966a1a50 100644 --- a/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh +++ b/tests/mmstests/sources/momenttensor-2d/TestMomentTensorSource.hh @@ -119,6 +119,11 @@ public: pylith::topology::Field::Discretization const* sourceAuxDiscretizations; ///< Discretizations for source auxiliary subfields. spatialdata::spatialdb::UserFunctionDB sourceAuxDB; ///< Spatial database for source auxiliary field. + // Source point locations. + size_t numSourcePoints; ///< Number of source points. + const PylithReal* sourcePointCoords; ///< Coordinates of source points [numSourcePoints * spaceDim]. + const char* const* sourcePointNames; ///< Names of source points. + }; // TestMomentTensorSource_Data // End of file From 1e8d4e1f29cdb5aebb56721d8a168f404f377df1 Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Thu, 22 Jan 2026 23:08:32 +0000 Subject: [PATCH 65/65] Believed to pass with no failures --- .../sources/momenttensor-2d/MomentTensorUniformStrain2D.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc index d0db6dd874..9b1435c6cb 100644 --- a/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc +++ b/tests/mmstests/sources/momenttensor-2d/MomentTensorUniformStrain2D.cc @@ -301,6 +301,13 @@ class pylith::_MomentTensorUniformStrain2D { data->source.setLabelValue(24); data->source.setSubfieldName("velocity"); // Apply source to velocity field for dynamic problems + // Source point coordinates (center of domain) + data->numSourcePoints = 1; + static const PylithReal _sourcePointCoords[2] = {0.0, 0.0}; // Center of domain + data->sourcePointCoords = _sourcePointCoords; + static const char* _sourcePointNames[1] = {"source_point"}; + data->sourcePointNames = _sourcePointNames; + // Boundary conditions static const PylithInt constrainedDOF[2] = {0, 1}; static const PylithInt numConstrained = 2;