Exemple #1
0
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));
}
Exemple #3
0
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));
}
Exemple #4
0
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);
}
Exemple #7
0
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;
}
Exemple #8
0
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;
            }));
}
Exemple #12
0
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();
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #16
0
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;
}
Exemple #17
0
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;
}
Exemple #18
0
/// 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;
}
Exemple #19
0
    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;
}
Exemple #22
0
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);
}
Exemple #23
0
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;
            }));
}
Exemple #25
0
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}};
    }
}
Exemple #26
0
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());
}
Exemple #27
0
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();
}
Exemple #28
0
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});
}
Exemple #29
0
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;
}