void LiquidFlowProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { ProcessLib::ProcessVariable const& pv = getProcessVariables()[0]; ProcessLib::createLocalAssemblers<LiquidFlowLocalAssembler>( mesh.getDimension(), mesh.getElements(), dof_table, pv.getShapeFunctionOrder(), _local_assemblers, mesh.isAxiallySymmetric(), integration_order, _gravitational_axis_id, _gravitational_acceleration, _material_properties); _secondary_variables.addSecondaryVariable( "darcy_velocity_x", 1, makeExtrapolator( getExtrapolator(), _local_assemblers, &LiquidFlowLocalAssemblerInterface::getIntPtDarcyVelocityX)); if (mesh.getDimension() > 1) { _secondary_variables.addSecondaryVariable( "darcy_velocity_y", 1, makeExtrapolator( getExtrapolator(), _local_assemblers, &LiquidFlowLocalAssemblerInterface::getIntPtDarcyVelocityY)); } if (mesh.getDimension() > 2) { _secondary_variables.addSecondaryVariable( "darcy_velocity_z", 1, makeExtrapolator( getExtrapolator(), _local_assemblers, &LiquidFlowLocalAssemblerInterface::getIntPtDarcyVelocityZ)); } }
void RichardsComponentTransportProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { const int monolithic_process_id = 0; ProcessLib::ProcessVariable const& pv = getProcessVariables(monolithic_process_id)[0]; ProcessLib::createLocalAssemblers<LocalAssemblerData>( mesh.getDimension(), mesh.getElements(), dof_table, pv.getShapeFunctionOrder(), _local_assemblers, mesh.isAxiallySymmetric(), integration_order, _process_data); _secondary_variables.addSecondaryVariable( "darcy_velocity", makeExtrapolator(mesh.getDimension(), getExtrapolator(), _local_assemblers, &RichardsComponentTransportLocalAssemblerInterface:: getIntPtDarcyVelocity)); _secondary_variables.addSecondaryVariable( "saturation", makeExtrapolator(1, getExtrapolator(), _local_assemblers, &RichardsComponentTransportLocalAssemblerInterface:: getIntPtSaturation)); }
void HTProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { // For the staggered scheme, both processes are assumed to use the same // element order. Therefore the order of shape function can be fetched from // any set of the sets of process variables of the coupled processes. Here, // we take the one from the first process by setting process_id = 0. const int process_id = 0; ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; if (_use_monolithic_scheme) { ProcessLib::createLocalAssemblers<MonolithicHTFEM>( mesh.getDimension(), mesh.getElements(), dof_table, pv.getShapeFunctionOrder(), _local_assemblers, mesh.isAxiallySymmetric(), integration_order, *_material_properties); } else { ProcessLib::createLocalAssemblers<StaggeredHTFEM>( mesh.getDimension(), mesh.getElements(), dof_table, pv.getShapeFunctionOrder(), _local_assemblers, mesh.isAxiallySymmetric(), integration_order, *_material_properties, _heat_transport_process_id, _hydraulic_process_id); } _secondary_variables.addSecondaryVariable( "darcy_velocity", makeExtrapolator(mesh.getDimension(), getExtrapolator(), _local_assemblers, &HTLocalAssemblerInterface::getIntPtDarcyVelocity)); }
bool convertMeshToGeo(const MeshLib::Mesh &mesh, GeoLib::GEOObjects &geo_objects, double eps) { if (mesh.getDimension() != 2) { ERR ("Mesh to geometry conversion is only working for 2D meshes."); return false; } // nodes to points conversion std::string mesh_name(mesh.getName()); { auto points = std::make_unique<std::vector<GeoLib::Point*>>(); points->reserve(mesh.getNumberOfNodes()); for (auto node_ptr : mesh.getNodes()) points->push_back(new GeoLib::Point(*node_ptr, node_ptr->getID())); geo_objects.addPointVec(std::move(points), mesh_name, nullptr, eps); } const std::vector<std::size_t> id_map (geo_objects.getPointVecObj(mesh_name)->getIDMap()); // elements to surface triangles conversion std::string const mat_name ("MaterialIDs"); auto bounds (MeshInformation::getValueBounds<int>(mesh, mat_name)); const unsigned nMatGroups(bounds.second-bounds.first+1); auto sfcs = std::make_unique<std::vector<GeoLib::Surface*>>(); sfcs->reserve(nMatGroups); auto const& points = *geo_objects.getPointVec(mesh_name); for (unsigned i=0; i<nMatGroups; ++i) sfcs->push_back(new GeoLib::Surface(points)); const std::vector<MeshLib::Element*> &elements = mesh.getElements(); const std::size_t nElems (mesh.getNumberOfElements()); MeshLib::PropertyVector<int> const*const materialIds = mesh.getProperties().existsPropertyVector<int>("MaterialIDs") ? mesh.getProperties().getPropertyVector<int>("MaterialIDs") : nullptr; for (unsigned i=0; i<nElems; ++i) { auto surfaceId = !materialIds ? 0 : ((*materialIds)[i] - bounds.first); MeshLib::Element* e (elements[i]); if (e->getGeomType() == MeshElemType::TRIANGLE) (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(1)], id_map[e->getNodeIndex(2)]); if (e->getGeomType() == MeshElemType::QUAD) { (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(1)], id_map[e->getNodeIndex(2)]); (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(2)], id_map[e->getNodeIndex(3)]); } // all other element types are ignored (i.e. lines) } std::for_each(sfcs->begin(), sfcs->end(), [](GeoLib::Surface* sfc){ if (sfc->getNumberOfTriangles()==0) delete sfc; sfc = nullptr;}); auto sfcs_end = std::remove(sfcs->begin(), sfcs->end(), nullptr); sfcs->erase(sfcs_end, sfcs->end()); geo_objects.addSurfaceVec(std::move(sfcs), mesh_name); return true; }
void HeatTransportBHEProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { // Quick access map to BHE's through element ids. std::unordered_map<std::size_t, BHE::BHETypes*> element_to_bhe_map; int const n_BHEs = _process_data._vec_BHE_property.size(); for (int i = 0; i < n_BHEs; i++) { auto const& bhe_elements = _bheMeshData.BHE_elements[i]; for (auto const& e : bhe_elements) { element_to_bhe_map[e->getID()] = &_process_data._vec_BHE_property[i]; } } assert(mesh.getDimension() == 3); ProcessLib::HeatTransportBHE::createLocalAssemblers< HeatTransportBHELocalAssemblerSoil, HeatTransportBHELocalAssemblerBHE>( mesh.getElements(), dof_table, _local_assemblers, element_to_bhe_map, mesh.isAxiallySymmetric(), integration_order, _process_data); // Create BHE boundary conditions for each of the BHEs createBHEBoundaryConditionTopBottom(_bheMeshData.BHE_nodes); }
std::unique_ptr<PythonBoundaryCondition> createPythonBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& boundary_mesh, NumLib::LocalToGlobalIndexMap const& dof_table, std::size_t bulk_mesh_id, int const variable_id, int const component_id, unsigned const integration_order, unsigned const shapefunction_order, unsigned const global_dim) { //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Python"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Python__bc_object} auto const bc_object = config.getConfigParameter<std::string>("bc_object"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Python__flush_stdout} auto const flush_stdout = config.getConfigParameter("flush_stdout", false); // Evaluate Python code in scope of main module pybind11::object scope = pybind11::module::import("__main__").attr("__dict__"); if (!scope.contains(bc_object)) OGS_FATAL( "Function `%s' is not defined in the python script file, or there " "was no python script file specified.", bc_object.c_str()); auto* bc = scope[bc_object.c_str()] .cast<PythonBoundaryConditionPythonSideInterface*>(); if (variable_id >= static_cast<int>(dof_table.getNumberOfVariables()) || component_id >= dof_table.getNumberOfVariableComponents(variable_id)) { OGS_FATAL( "Variable id or component id too high. Actual values: (%d, %d), " "maximum values: (%d, %d).", variable_id, component_id, dof_table.getNumberOfVariables(), dof_table.getNumberOfVariableComponents(variable_id)); } // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (boundary_mesh.getDimension() == 0 && boundary_mesh.getNumberOfNodes() == 0 && boundary_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<PythonBoundaryCondition>( PythonBoundaryConditionData{ bc, dof_table, bulk_mesh_id, dof_table.getGlobalComponent(variable_id, component_id), boundary_mesh}, integration_order, shapefunction_order, global_dim, flush_stdout); }
std::vector<GeoLib::PointWithID*> MshEditor::getSurfaceNodes(const MeshLib::Mesh &mesh, const double *dir) { INFO ("Extracting surface nodes..."); const std::vector<MeshLib::Element*> all_elements (mesh.getElements()); const std::vector<MeshLib::Node*> all_nodes (mesh.getNodes()); std::vector<MeshLib::Element*> sfc_elements; get2DSurfaceElements(all_elements, sfc_elements, dir, mesh.getDimension()); std::vector<MeshLib::Node*> sfc_nodes; std::vector<unsigned> node_id_map(mesh.getNNodes()); get2DSurfaceNodes(all_nodes, sfc_nodes, sfc_elements, node_id_map); const unsigned nElements (sfc_elements.size()); for (unsigned i=0; i<nElements; ++i) delete sfc_elements[i]; const size_t nNodes (sfc_nodes.size()); std::vector<GeoLib::PointWithID*> surface_pnts(nNodes); for (unsigned i=0; i<nNodes; ++i) { surface_pnts[i] = new GeoLib::PointWithID(sfc_nodes[i]->getCoords(), sfc_nodes[i]->getID()); delete sfc_nodes[i]; } return surface_pnts; }
bool MeshLayerMapper::layerMapping(MeshLib::Mesh &new_mesh, GeoLib::Raster const& raster, double noDataReplacementValue = 0.0) { if (new_mesh.getDimension() != 2) { ERR("MshLayerMapper::layerMapping() - requires 2D mesh"); return false; } GeoLib::RasterHeader const& header (raster.getHeader()); const double x0(header.origin[0]); const double y0(header.origin[1]); const double delta(header.cell_size); const std::pair<double, double> xDim(x0, x0 + header.n_cols * delta); // extension in x-dimension const std::pair<double, double> yDim(y0, y0 + header.n_rows * delta); // extension in y-dimension const std::size_t nNodes (new_mesh.getNumberOfNodes()); const std::vector<MeshLib::Node*> &nodes = new_mesh.getNodes(); for (unsigned i = 0; i < nNodes; ++i) { if (!raster.isPntOnRaster(*nodes[i])) { // use either default value or elevation from layer above nodes[i]->updateCoordinates((*nodes[i])[0], (*nodes[i])[1], noDataReplacementValue); continue; } double elevation (raster.interpolateValueAtPoint(*nodes[i])); if (std::abs(elevation - header.no_data) < std::numeric_limits<double>::epsilon()) elevation = noDataReplacementValue; nodes[i]->updateCoordinates((*nodes[i])[0], (*nodes[i])[1], elevation); } return true; }
std::unique_ptr<DirichletBoundaryCondition> createDirichletBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh, NumLib::LocalToGlobalIndexMap const& dof_table_bulk, int const variable_id, int const component_id, const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters) { DBUG("Constructing DirichletBoundaryCondition from config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Dirichlet"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Dirichlet__parameter} auto const param_name = config.getConfigParameter<std::string>("parameter"); DBUG("Using parameter %s", param_name.c_str()); auto& param = findParameter<double>(param_name, parameters, 1); // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (bc_mesh.getDimension() == 0 && bc_mesh.getNumberOfNodes() == 0 && bc_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<DirichletBoundaryCondition>( param, bc_mesh, dof_table_bulk, variable_id, component_id); }
void MeshSurfaceExtraction::getSurfaceAreaForNodes(const MeshLib::Mesh &mesh, std::vector<double> &node_area_vec) { if (mesh.getDimension() == 2) { double total_area (0); // for each node, a vector containing all the element idget every element const std::vector<MeshLib::Node*> &nodes = mesh.getNodes(); const size_t nNodes ( mesh.getNNodes() ); node_area_vec.reserve(nNodes); for (size_t n=0; n<nNodes; ++n) { double node_area (0); std::vector<MeshLib::Element*> conn_elems = nodes[n]->getElements(); const size_t nConnElems (conn_elems.size()); for (size_t i=0; i<nConnElems; ++i) { const MeshLib::Element* elem (conn_elems[i]); const unsigned nElemParts = (elem->getGeomType() == MeshElemType::TRIANGLE) ? 3 : 4; const double area = conn_elems[i]->getContent() / nElemParts; node_area += area; total_area += area; } node_area_vec.push_back(node_area); } INFO ("Total surface Area: %f", total_area); } else ERR ("Error in MeshSurfaceExtraction::getSurfaceAreaForNodes() - Given mesh is no surface mesh (dimension != 2)."); }
SmallDeformationNonlocalProcess<DisplacementDim>:: SmallDeformationNonlocalProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters, unsigned const integration_order, std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&& process_variables, SmallDeformationNonlocalProcessData<DisplacementDim>&& process_data, SecondaryVariableCollection&& secondary_variables, NumLib::NamedFunctionCaller&& named_function_caller) : Process(mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller)), _process_data(std::move(process_data)) { _nodal_forces = MeshLib::getOrCreateMeshProperty<double>( mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim); _integration_point_writer.emplace_back( std::make_unique<SigmaIntegrationPointWriter>( static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/, integration_order, [this]() { // Result containing integration point data for each local // assembler. std::vector<std::vector<double>> result; result.resize(_local_assemblers.size()); for (std::size_t i = 0; i < _local_assemblers.size(); ++i) { auto const& local_asm = *_local_assemblers[i]; result[i] = local_asm.getSigma(); } return result; })); _integration_point_writer.emplace_back( std::make_unique<KappaDIntegrationPointWriter>( integration_order, [this]() { // Result containing integration point data for each local // assembler. std::vector<std::vector<double>> result; result.resize(_local_assemblers.size()); for (std::size_t i = 0; i < _local_assemblers.size(); ++i) { auto const& local_asm = *_local_assemblers[i]; result[i] = local_asm.getKappaD(); } return result; })); }
void TESProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { ProcessLib::createLocalAssemblers<TESLocalAssembler>( mesh.getDimension(), mesh.getElements(), dof_table, _local_assemblers, mesh.isAxiallySymmetric(), integration_order, _assembly_params); initializeSecondaryVariables(); }
bool MeshLayerMapper::mapToStaticValue(MeshLib::Mesh &mesh, double value) { if (mesh.getDimension() != 2) { ERR("MshLayerMapper::mapToStaticValue() - requires 2D mesh"); return false; } std::vector<MeshLib::Node*> const& nodes (mesh.getNodes()); for (MeshLib::Node* node : nodes) node->updateCoordinates((*node)[0], (*node)[1], value); return true; }
VolumetricSourceTerm::VolumetricSourceTerm( MeshLib::Mesh const& source_term_mesh, std::unique_ptr<NumLib::LocalToGlobalIndexMap> source_term_dof_table, unsigned const integration_order, unsigned const shapefunction_order, Parameter<double> const& volumetric_source_term) : SourceTerm(std::move(source_term_dof_table)), _volumetric_source_term(volumetric_source_term) { ProcessLib::createLocalAssemblers<VolumetricSourceTermLocalAssembler>( source_term_mesh.getDimension(), source_term_mesh.getElements(), *_source_term_dof_table, shapefunction_order, _local_assemblers, source_term_mesh.isAxiallySymmetric(), integration_order, _volumetric_source_term); }
bool LayeredMeshGenerator::createLayers(MeshLib::Mesh const& mesh, std::vector<std::string> const& raster_paths, double minimum_thickness, double noDataReplacementValue) { if (mesh.getDimension() != 2 || !allRastersExist(raster_paths)) return false; std::vector<GeoLib::Raster const*> rasters; rasters.reserve(raster_paths.size()); for (auto path = raster_paths.begin(); path != raster_paths.end(); ++path) rasters.push_back(FileIO::AsciiRasterInterface::getRasterFromASCFile(*path)); bool result = createRasterLayers(mesh, rasters, minimum_thickness, noDataReplacementValue); std::for_each(rasters.begin(), rasters.end(), [](GeoLib::Raster const*const raster){ delete raster; }); return result; }
bool MeshLayerMapper::createRasterLayers( MeshLib::Mesh const& mesh, std::vector<GeoLib::Raster const*> const& rasters, double minimum_thickness, double noDataReplacementValue) { const std::size_t nLayers(rasters.size()); if (nLayers < 2 || mesh.getDimension() != 2) { ERR("MeshLayerMapper::createRasterLayers(): A 2D mesh and at least two rasters required as input."); return false; } auto top = std::make_unique<MeshLib::Mesh>(mesh); if (!layerMapping(*top, *rasters.back(), noDataReplacementValue)) return false; auto bottom = std::make_unique<MeshLib::Mesh>(mesh); if (!layerMapping(*bottom, *rasters[0], 0)) { return false; } this->_minimum_thickness = minimum_thickness; std::size_t const nNodes = mesh.getNumberOfNodes(); _nodes.reserve(nLayers * nNodes); // number of triangles in the original mesh std::size_t const nElems (std::count_if(mesh.getElements().begin(), mesh.getElements().end(), [](MeshLib::Element const* elem) { return (elem->getGeomType() == MeshLib::MeshElemType::TRIANGLE);})); _elements.reserve(nElems * (nLayers-1)); _materials.reserve(nElems * (nLayers-1)); // add bottom layer std::vector<MeshLib::Node*> const& nodes = bottom->getNodes(); for (MeshLib::Node* node : nodes) _nodes.push_back(new MeshLib::Node(*node)); // add the other layers for (std::size_t i=0; i<nLayers-1; ++i) addLayerToMesh(*top, i, *rasters[i+1]); return true; }
bool LayeredVolume::createRasterLayers(const MeshLib::Mesh &mesh, const std::vector<GeoLib::Raster const*> &rasters, double minimum_thickness, double noDataReplacementValue) { if (mesh.getDimension() != 2) return false; _elevation_epsilon = calcEpsilon(*rasters[0], *rasters.back()); if (_elevation_epsilon <= 0) return false; // remove line elements, only tri + quad remain MeshLib::ElementSearch ex(mesh); ex.searchByElementType(MeshLib::MeshElemType::LINE); MeshLib::Mesh* top (removeElements(mesh, ex.getSearchedElementIDs(), "MeshLayer")); if (top==nullptr) top = new MeshLib::Mesh(mesh); if (!MeshLib::MeshLayerMapper::layerMapping(*top, *rasters.back(), noDataReplacementValue)) return false; MeshLib::Mesh* bottom (new MeshLib::Mesh(*top)); if (!MeshLib::MeshLayerMapper::layerMapping(*bottom, *rasters[0], 0)) { delete top; return false; } this->_minimum_thickness = minimum_thickness; _nodes = MeshLib::copyNodeVector(bottom->getNodes()); _elements = MeshLib::copyElementVector(bottom->getElements(), _nodes); delete bottom; // map each layer and attach to subsurface mesh const std::size_t nRasters (rasters.size()); for (std::size_t i=1; i<nRasters; ++i) this->addLayerToMesh(*top, i, *rasters[i]); // close boundaries between layers this->addLayerBoundaries(*top, nRasters); this->removeCongruentElements(nRasters, top->getNElements()); delete top; return true; }
/// Returns a vector of values where each value is associated with a /// particular node. Since a node is part of elements, it is possible to /// assign an area per element to this node. Each value of the return vector /// is the sum of the assigned area (per element) multiplied by the property /// value of the element. /// @param mesh a surface mesh containing a property \c prop_name assigned /// to cells /// @param prop_name name of the cell based property within the \c mesh /// @return vector of integration values associated to the surface mesh nodes std::vector<double> getSurfaceIntegratedValuesForNodes( const MeshLib::Mesh& mesh, std::string const& prop_name) { if (mesh.getDimension() != 2) { ERR("Error in " "MeshSurfaceExtraction::getSurfaceIntegratedValuesForNodes() - " "Given mesh is no surface mesh (dimension != 2)."); return std::vector<double>(); } if (!mesh.getProperties().existsPropertyVector<double>(prop_name)) { ERR("Need element property, but the property '%s' is not " "available.", prop_name.c_str()); return std::vector<double>(); } auto const* const elem_pv = mesh.getProperties().getPropertyVector<double>( prop_name, MeshLib::MeshItemType::Cell, 1); std::vector<double> integrated_node_area_vec; double total_area(0); for (auto const* node : mesh.getNodes()) { double node_area(0); double integrated_node_area(0); for (auto const& connected_elem : node->getElements()) { double const area = connected_elem->getContent() / connected_elem->getNumberOfBaseNodes(); node_area += area; integrated_node_area += area * (*elem_pv)[connected_elem->getID()]; total_area += area; } integrated_node_area_vec.push_back(integrated_node_area); } INFO ("Total surface area: %g", total_area); return integrated_node_area_vec; }
ExtrapolationTestProcess(MeshLib::Mesh const& mesh, unsigned const integration_order) : _integration_order(integration_order), _mesh_subset_all_nodes(mesh, mesh.getNodes()) { std::vector<MeshLib::MeshSubset> all_mesh_subsets{ _mesh_subset_all_nodes}; _dof_table = std::make_unique<NumLib::LocalToGlobalIndexMap>( std::move(all_mesh_subsets), NumLib::ComponentOrder::BY_COMPONENT); // Passing _dof_table works, because this process has only one variable // and the variable has exactly one component. _extrapolator = std::make_unique<ExtrapolatorImplementation>(*_dof_table); // createAssemblers(mesh); ProcessLib::createLocalAssemblers<LocalAssemblerData>( mesh.getDimension(), mesh.getElements(), *_dof_table, 1, _local_assemblers, mesh.isAxiallySymmetric(), _integration_order); }
std::unique_ptr<RobinBoundaryCondition> createRobinBoundaryCondition( BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh, NumLib::LocalToGlobalIndexMap const& dof_table, int const variable_id, int const component_id, unsigned const integration_order, unsigned const shapefunction_order, unsigned const global_dim, std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters) { DBUG("Constructing RobinBcConfig from config."); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type} config.checkConfigParameter("type", "Robin"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Robin__alpha} auto const alpha_name = config.getConfigParameter<std::string>("alpha"); //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__Robin__u_0} auto const u_0_name = config.getConfigParameter<std::string>("u_0"); auto const& alpha = ParameterLib::findParameter<double>(alpha_name, parameters, 1); auto const& u_0 = ParameterLib::findParameter<double>(u_0_name, parameters, 1); // In case of partitioned mesh the boundary could be empty, i.e. there is no // boundary condition. #ifdef USE_PETSC // This can be extracted to createBoundaryCondition() but then the config // parameters are not read and will cause an error. // TODO (naumov): Add a function to ConfigTree for skipping the tags of the // subtree and move the code up in createBoundaryCondition(). if (bc_mesh.getDimension() == 0 && bc_mesh.getNumberOfNodes() == 0 && bc_mesh.getNumberOfElements() == 0) { return nullptr; } #endif // USE_PETSC return std::make_unique<RobinBoundaryCondition>( integration_order, shapefunction_order, dof_table, variable_id, component_id, global_dim, bc_mesh, RobinBoundaryConditionData{alpha, u_0}); }
std::vector<GeoLib::Point*> MeshSurfaceExtraction::getSurfaceNodes(const MeshLib::Mesh &mesh, const MathLib::Vector3 &dir, double angle) { INFO ("Extracting surface nodes..."); std::vector<MeshLib::Element*> sfc_elements; get2DSurfaceElements(mesh.getElements(), sfc_elements, dir, angle, mesh.getDimension()); std::vector<MeshLib::Node*> sfc_nodes; std::vector<std::size_t> node_id_map(mesh.getNNodes()); get2DSurfaceNodes(sfc_nodes, mesh.getNNodes(), sfc_elements, node_id_map); for (auto e : sfc_elements) delete e; const std::size_t nNodes (sfc_nodes.size()); std::vector<GeoLib::Point*> surface_pnts(nNodes); for (std::size_t i=0; i<nNodes; ++i) { surface_pnts[i] = new GeoLib::Point(*(sfc_nodes[i]), sfc_nodes[i]->getID()); delete sfc_nodes[i]; } return surface_pnts; }
unsigned MeshValidation::detectHoles(MeshLib::Mesh const& mesh) { if (mesh.getDimension() == 1) return 0; MeshLib::Mesh* boundary_mesh (MeshSurfaceExtraction::getMeshBoundary(mesh)); std::vector<MeshLib::Element*> const& elements (boundary_mesh->getElements()); std::vector<unsigned> sfc_idx (elements.size(), std::numeric_limits<unsigned>::max()); unsigned current_surface_id (0); std::vector<unsigned>::const_iterator it = sfc_idx.cbegin(); while (it != sfc_idx.cend()) { std::size_t const idx = static_cast<std::size_t>(std::distance(sfc_idx.cbegin(), it)); trackSurface(elements[idx], sfc_idx, current_surface_id++); it = std::find(sfc_idx.cbegin(), sfc_idx.cend(), std::numeric_limits<unsigned>::max()); } delete boundary_mesh; // Subtract "1" from the number of surfaces found to get the number of holes. return (--current_surface_id); }
SurfaceFlux::SurfaceFlux( MeshLib::Mesh& boundary_mesh, std::size_t bulk_property_number_of_components, unsigned const integration_order) { DBUG("Create local balance assemblers."); // Populate the vector of local assemblers. _local_assemblers.resize(boundary_mesh.getElements().size()); // needed to create dof table auto mesh_subset_all_nodes = std::make_unique<MeshLib::MeshSubset>( boundary_mesh, boundary_mesh.getNodes()); // Collect the mesh subsets in a vector. std::vector<MeshLib::MeshSubset> all_mesh_subsets; std::generate_n(std::back_inserter(all_mesh_subsets), bulk_property_number_of_components, [&]() { return *mesh_subset_all_nodes; }); // needed for creation of local assemblers auto dof_table = std::make_unique<NumLib::LocalToGlobalIndexMap const>( std::move(all_mesh_subsets), NumLib::ComponentOrder::BY_LOCATION); auto const bulk_element_ids = boundary_mesh.getProperties().template getPropertyVector<std::size_t>( "bulk_element_ids", MeshLib::MeshItemType::Cell, 1); auto const bulk_face_ids = boundary_mesh.getProperties().template getPropertyVector<std::size_t>( "bulk_face_ids", MeshLib::MeshItemType::Cell, 1); ProcessLib::createLocalAssemblers<SurfaceFluxLocalAssembler>( boundary_mesh.getDimension() + 1, // or bulk_mesh.getDimension()? boundary_mesh.getElements(), *dof_table, 1, _local_assemblers, boundary_mesh.isAxiallySymmetric(), integration_order, *bulk_element_ids, *bulk_face_ids); }
ThermoMechanicsProcess<DisplacementDim>::ThermoMechanicsProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&& process_variables, ThermoMechanicsProcessData<DisplacementDim>&& process_data, SecondaryVariableCollection&& secondary_variables, NumLib::NamedFunctionCaller&& named_function_caller, bool const use_monolithic_scheme) : Process(mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), use_monolithic_scheme), _process_data(std::move(process_data)) { _integration_point_writer.emplace_back( std::make_unique<SigmaIntegrationPointWriter>( static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/, 2 /*integration order*/, [this]() { // Result containing integration point data for each local // assembler. std::vector<std::vector<double>> result; result.resize(_local_assemblers.size()); for (std::size_t i = 0; i < _local_assemblers.size(); ++i) { auto const& local_asm = *_local_assemblers[i]; result[i] = local_asm.getSigma(); } return result; })); }
std::unique_ptr<Process> createLiquidFlowProcess( MeshLib::Mesh& mesh, std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler, std::vector<ProcessVariable> const& variables, std::vector<std::unique_ptr<ParameterBase>> const& parameters, unsigned const integration_order, BaseLib::ConfigTree const& config) { //! \ogs_file_param{process__type} config.checkConfigParameter("type", "LIQUID_FLOW"); DBUG("Create LiquidFlowProcess."); // Process variable. auto process_variables = findProcessVariables( variables, config, {//! \ogs_file_param_special{process__LIQUID_FLOW__process_variables__process_variable} "process_variable"}); SecondaryVariableCollection secondary_variables; NumLib::NamedFunctionCaller named_function_caller({"LiquidFlow_pressure"}); ProcessLib::parseSecondaryVariables(config, secondary_variables, named_function_caller); // Get the gravity vector for the Darcy velocity //! \ogs_file_param{process__LIQUID_FLOW__darcy_gravity} auto const& darcy_g_config = config.getConfigSubtree("darcy_gravity"); const int gravity_axis_id_input = //! \ogs_file_param_special{process__LIQUID_FLOW__darcy_gravity_axis_id} darcy_g_config.getConfigParameter<int>("axis_id"); assert(gravity_axis_id_input < static_cast<int>(mesh.getDimension())); const double g = //! \ogs_file_param_special{process__LIQUID_FLOW__darcy_gravity_g} darcy_g_config.getConfigParameter<double>("g"); assert(g >= 0.); const int gravity_axis_id = (g == 0.) ? -1 : gravity_axis_id_input; //! \ogs_file_param{process__LIQUID_FLOW__material_property} auto const& mat_config = config.getConfigSubtree("material_property"); auto const& mat_ids = mesh.getProperties().getPropertyVector<int>("MaterialIDs"); if (mat_ids) { INFO("The liquid flow is in heterogeneous porous media."); const bool has_material_ids = true; return std::unique_ptr<Process>{new LiquidFlowProcess{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), *mat_ids, has_material_ids, gravity_axis_id, g, mat_config}}; } else { INFO("The liquid flow is in homogeneous porous media."); MeshLib::Properties dummy_property; // For a reference argument of LiquidFlowProcess(...). auto const& dummy_property_vector = dummy_property.createNewPropertyVector<int>( "MaterialIDs", MeshLib::MeshItemType::Cell, 1); // Since dummy_property_vector is only visible in this function, // the following constant, has_material_ids, is employed to indicate // that material_ids does not exist. const bool has_material_ids = false; return std::unique_ptr<Process>{new LiquidFlowProcess{ mesh, std::move(jacobian_assembler), parameters, integration_order, std::move(process_variables), std::move(secondary_variables), std::move(named_function_caller), *dummy_property_vector, has_material_ids, gravity_axis_id, g, mat_config}}; } }
void getFractureMatrixDataInMesh( MeshLib::Mesh const& mesh, std::vector<MeshLib::Element*>& vec_matrix_elements, std::vector<MeshLib::Element*>& vec_fracture_elements, std::vector<MeshLib::Element*>& vec_fracture_matrix_elements, std::vector<MeshLib::Node*>& vec_fracture_nodes ) { IsCrackTip isCrackTip(mesh); // get vectors of matrix elements and fracture elements vec_matrix_elements.reserve(mesh.getNumberOfElements()); for (MeshLib::Element* e : mesh.getElements()) { if (e->getDimension() == mesh.getDimension()) vec_matrix_elements.push_back(e); else vec_fracture_elements.push_back(e); } DBUG("-> found total %d matrix elements and %d fracture elements", vec_matrix_elements.size(), vec_fracture_elements.size()); // get a vector of fracture nodes for (MeshLib::Element* e : vec_fracture_elements) { for (unsigned i=0; i<e->getNumberOfNodes(); i++) { if (isCrackTip(*e->getNode(i))) continue; vec_fracture_nodes.push_back(const_cast<MeshLib::Node*>(e->getNode(i))); } } std::sort(vec_fracture_nodes.begin(), vec_fracture_nodes.end(), [](MeshLib::Node* node1, MeshLib::Node* node2) { return (node1->getID() < node2->getID()); } ); vec_fracture_nodes.erase( std::unique(vec_fracture_nodes.begin(), vec_fracture_nodes.end()), vec_fracture_nodes.end()); DBUG("-> found %d nodes on the fracture", vec_fracture_nodes.size()); // create a vector fracture elements and connected matrix elements, // which are passed to a DoF table // first, collect matrix elements for (MeshLib::Element *e : vec_fracture_elements) { for (unsigned i=0; i<e->getNumberOfBaseNodes(); i++) { MeshLib::Node const* node = e->getNode(i); if (isCrackTip(*node)) continue; for (unsigned j=0; j<node->getNumberOfElements(); j++) { // only matrix elements if (node->getElement(j)->getDimension() == mesh.getDimension()-1) continue; vec_fracture_matrix_elements.push_back(const_cast<MeshLib::Element*>(node->getElement(j))); } } } std::sort(vec_fracture_matrix_elements.begin(), vec_fracture_matrix_elements.end(), [](MeshLib::Element* p1, MeshLib::Element* p2) { return (p1->getID() < p2->getID()); } ); vec_fracture_matrix_elements.erase( std::unique(vec_fracture_matrix_elements.begin(), vec_fracture_matrix_elements.end()), vec_fracture_matrix_elements.end()); // second, append fracture elements vec_fracture_matrix_elements.insert( vec_fracture_matrix_elements.end(), vec_fracture_elements.begin(), vec_fracture_elements.end()); }
PostProcessTool::PostProcessTool( MeshLib::Mesh const& org_mesh, std::vector<MeshLib::Node*> const& vec_fracture_nodes, std::vector<MeshLib::Element*> const& vec_fracutre_matrix_elements) :_org_mesh(org_mesh) { if (!org_mesh.getProperties().hasPropertyVector("displacement") || !org_mesh.getProperties().hasPropertyVector("displacement_jump1") || !org_mesh.getProperties().hasPropertyVector("levelset1") ) { OGS_FATAL("The given mesh does not have relevant properties"); } // clone nodes and elements std::vector<MeshLib::Node*> new_nodes(MeshLib::copyNodeVector(org_mesh.getNodes())); std::vector<MeshLib::Element*> new_eles( MeshLib::copyElementVector(org_mesh.getElements(), new_nodes)); // duplicate fracture nodes for (auto const* org_node : vec_fracture_nodes) { auto duplicated_node = new MeshLib::Node(org_node->getCoords(), new_nodes.size()); new_nodes.push_back(duplicated_node); _map_dup_newNodeIDs[org_node->getID()] = duplicated_node->getID(); } // split elements using the new duplicated nodes auto prop_levelset = org_mesh.getProperties().getPropertyVector<double>("levelset1"); for (auto const* org_e : vec_fracutre_matrix_elements) { // only matrix elements if (org_e->getDimension() != org_mesh.getDimension()) continue; auto const eid = org_e->getID(); // keep original if the element has levelset=0 if ((*prop_levelset)[eid] == 0) continue; // replace fracture nodes with duplicated ones MeshLib::Element* e = new_eles[eid]; for (unsigned i=0; i<e->getNumberOfNodes(); i++) { // only fracture nodes auto itr = _map_dup_newNodeIDs.find(e->getNodeIndex(i)); if (itr == _map_dup_newNodeIDs.end()) continue; // check if a node belongs to the particular fracture group auto itr2 = std::find_if(vec_fracture_nodes.begin(), vec_fracture_nodes.end(), [&](MeshLib::Node const*node) { return node->getID()==e->getNodeIndex(i);}); if (itr2 == vec_fracture_nodes.end()) continue; e->setNode(i, new_nodes[itr->second]); } } // new mesh _output_mesh.reset(new MeshLib::Mesh(org_mesh.getName(), new_nodes, new_eles)); createProperties<int>(); createProperties<double>(); copyProperties<int>(); copyProperties<double>(); calculateTotalDisplacement(); }
void TESProcess::initializeConcreteProcess( NumLib::LocalToGlobalIndexMap const& dof_table, MeshLib::Mesh const& mesh, unsigned const integration_order) { DBUG("Create global assembler."); _global_assembler.reset(new GlobalAssembler(dof_table)); ProcessLib::createLocalAssemblers<TESLocalAssembler>( mesh.getDimension(), mesh.getElements(), dof_table, integration_order, _local_assemblers, _assembly_params); // TODO move the two data members somewhere else. // for extrapolation of secondary variables std::vector<std::unique_ptr<MeshLib::MeshSubsets>> all_mesh_subsets_single_component; all_mesh_subsets_single_component.emplace_back( new MeshLib::MeshSubsets(this->_mesh_subset_all_nodes.get())); _local_to_global_index_map_single_component.reset( new NumLib::LocalToGlobalIndexMap( std::move(all_mesh_subsets_single_component), // by location order is needed for output NumLib::ComponentOrder::BY_LOCATION)); { auto const& l = *_local_to_global_index_map_single_component; _extrapolator.reset(new ExtrapolatorImplementation( MathLib::MatrixSpecifications(l.dofSizeWithoutGhosts(), l.dofSizeWithoutGhosts(), &l.getGhostIndices(), nullptr), l)); } // secondary variables auto add2nd = [&](std::string const& var_name, unsigned const n_components, SecondaryVariableFunctions&& fcts) { this->_secondary_variables.addSecondaryVariable(var_name, n_components, std::move(fcts)); }; auto makeEx = [&](TESIntPtVariables var) -> SecondaryVariableFunctions { return ProcessLib::makeExtrapolator(var, *_extrapolator, _local_assemblers); }; add2nd("solid_density", 1, makeEx(TESIntPtVariables::SOLID_DENSITY)); add2nd("reaction_rate", 1, makeEx(TESIntPtVariables::REACTION_RATE)); add2nd("velocity_x", 1, makeEx(TESIntPtVariables::VELOCITY_X)); if (mesh.getDimension() >= 2) add2nd("velocity_y", 1, makeEx(TESIntPtVariables::VELOCITY_Y)); if (mesh.getDimension() >= 3) add2nd("velocity_z", 1, makeEx(TESIntPtVariables::VELOCITY_Z)); add2nd("loading", 1, makeEx(TESIntPtVariables::LOADING)); add2nd("reaction_damping_factor", 1, makeEx(TESIntPtVariables::REACTION_DAMPING_FACTOR)); namespace PH = std::placeholders; using Self = TESProcess; add2nd("vapour_partial_pressure", 1, {std::bind(&Self::computeVapourPartialPressure, this, PH::_1, PH::_2, PH::_3), nullptr}); add2nd("relative_humidity", 1, {std::bind(&Self::computeRelativeHumidity, this, PH::_1, PH::_2, PH::_3), nullptr}); add2nd("equilibrium_loading", 1, {std::bind(&Self::computeEquilibriumLoading, this, PH::_1, PH::_2, PH::_3), nullptr}); }
TESProcess::TESProcess( MeshLib::Mesh& mesh, Process::NonlinearSolver& nonlinear_solver, std::unique_ptr<Process::TimeDiscretization>&& time_discretization, std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables, SecondaryVariableCollection&& secondary_variables, ProcessOutput&& process_output, const BaseLib::ConfigTree& config) : Process( mesh, nonlinear_solver, std::move(time_discretization), std::move(process_variables), std::move(secondary_variables), std::move(process_output)) { DBUG("Create TESProcess."); // physical parameters for local assembly { std::vector<std::pair<std::string, double*>> params{ {"fluid_specific_heat_source", &_assembly_params.fluid_specific_heat_source}, {"fluid_specific_isobaric_heat_capacity", &_assembly_params.cpG}, {"solid_specific_heat_source", &_assembly_params.solid_specific_heat_source}, {"solid_heat_conductivity", &_assembly_params.solid_heat_cond}, {"solid_specific_isobaric_heat_capacity", &_assembly_params.cpS}, {"tortuosity", &_assembly_params.tortuosity}, {"diffusion_coefficient", &_assembly_params.diffusion_coefficient_component}, {"porosity", &_assembly_params.poro}, {"solid_density_dry", &_assembly_params.rho_SR_dry}, {"solid_density_initial", &_assembly_params.initial_solid_density}}; for (auto const& p : params) { if (auto const par = config.getConfigParameterOptional<double>(p.first)) { DBUG("setting parameter `%s' to value `%g'", p.first.c_str(), *par); *p.second = *par; } } } // characteristic values of primary variables { std::vector<std::pair<std::string, Trafo*>> const params{ {"characteristic_pressure", &_assembly_params.trafo_p}, {"characteristic_temperature", &_assembly_params.trafo_T}, {"characteristic_vapour_mass_fraction", &_assembly_params.trafo_x}}; for (auto const& p : params) { if (auto const par = config.getConfigParameterOptional<double>(p.first)) { INFO("setting parameter `%s' to value `%g'", p.first.c_str(), *par); *p.second = Trafo{*par}; } } } // permeability if (auto par = config.getConfigParameterOptional<double>("solid_hydraulic_permeability")) { DBUG( "setting parameter `solid_hydraulic_permeability' to isotropic " "value `%g'", *par); const auto dim = mesh.getDimension(); _assembly_params.solid_perm_tensor = Eigen::MatrixXd::Identity(dim, dim) * (*par); } // reactive system _assembly_params.react_sys = Adsorption::AdsorptionReaction::newInstance( config.getConfigSubtree("reactive_system")); // debug output if (auto const param = config.getConfigParameterOptional<bool>("output_element_matrices")) { DBUG("output_element_matrices: %s", (*param) ? "true" : "false"); _assembly_params.output_element_matrices = *param; } // TODO somewhere else /* if (auto const param = config.getConfigParameterOptional<bool>("output_global_matrix")) { DBUG("output_global_matrix: %s", (*param) ? "true" : "false"); this->_process_output.output_global_matrix = *param; } */ }
int main (int argc, char* argv[]) { LOGOG_INITIALIZE(); logog::Cout* logog_cout (new logog::Cout); BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter); logog_cout->SetFormatter(*custom_format); TCLAP::CmdLine cmd("Add EMI data as a scalar cell array to a 2d mesh.", ' ', "0.1"); // I/O params TCLAP::ValueArg<std::string> poly_out("o", "polydata-output-file", "the name of the file the data will be written to", true, "", "file name of polydata file"); cmd.add(poly_out); TCLAP::ValueArg<std::string> csv_in("i", "csv-input-file", "csv-file containing EMI data", true, "", "name of the csv input file"); cmd.add(csv_in); TCLAP::ValueArg<std::string> dem_in("s", "DEM-file", "Surface DEM for mapping ERT data", false, "", "file name of the Surface DEM"); cmd.add(dem_in); cmd.parse(argc, argv); MeshLib::Mesh* mesh (nullptr); if (dem_in.isSet()) { mesh = FileIO::VtuInterface::readVTUFile(dem_in.getValue()); if (mesh == nullptr) { ERR ("Error reading mesh file."); return -2; } if (mesh->getDimension() != 2) { ERR ("This utility can handle only 2d meshes at this point."); delete mesh; return -3; } INFO("Surface mesh read: %d nodes, %d elements.", mesh->getNNodes(), mesh->getNElements()); } GeoLib::GEOObjects geo_objects; FileIO::XmlGmlInterface xml(geo_objects); //std::vector<GeoLib::Polyline*> *lines = new std::vector<GeoLib::Polyline*>; std::array<char, 2> dipol = {{ 'H', 'V' }}; std::array<char,3> const regions = {{'A', 'B', 'C'}}; for (std::size_t j=0; j<dipol.size(); ++j) { std::vector<GeoLib::Point*> *points = new std::vector<GeoLib::Point*>; for (std::size_t i=0; i<regions.size(); ++i) { //std::size_t const start_idx (points->size()); getPointsFromFile(*points, csv_in.getValue(), dipol[j], regions[i]); //std::size_t const end_idx (points->size()); //GeoLib::Polyline* line = new GeoLib::Polyline(*points); //for (std::size_t j=start_idx; j<end_idx; ++j) // line->addPoint(j); //lines->push_back(line); } std::string geo_name (std::string("EMI Data ").append(1,dipol[j])); geo_objects.addPointVec(points, geo_name); //geo_objects.addPolylineVec(lines, geo_name); if (mesh != nullptr) { GeoMapper mapper(geo_objects, geo_name); mapper.mapOnMesh(mesh); } xml.setNameForExport(geo_name); std::string const output_name = poly_out.getValue() + "_" + dipol[j] + ".gml"; xml.writeToFile(output_name); std::vector<double> emi; for (std::size_t i=0; i<regions.size(); ++i) getMeasurements(emi, csv_in.getValue(), dipol[j], regions[i]); writeMeasurementsToFile(emi, poly_out.getValue(), dipol[j]); std::for_each(points->begin(), points->end(), std::default_delete<GeoLib::Point>()); delete points; } delete mesh; delete custom_format; delete logog_cout; LOGOG_SHUTDOWN(); return 0; }