const std::vector< std::pair<std::size_t,double> >& DirectConditionGenerator::directWithSurfaceIntegration(MeshLib::Mesh &mesh, const std::string &filename, double scaling)
{
    if (!_direct_values.empty()) {
        ERR(
            "Error in DirectConditionGenerator::directWithSurfaceIntegration()"
            "- Data vector contains outdated values...");
        return _direct_values;
    }

    std::unique_ptr<GeoLib::Raster> raster(
        GeoLib::IO::AsciiRasterInterface::readRaster(filename));
    if (!raster) {
        ERR(
            "Error in DirectConditionGenerator::directWithSurfaceIntegration()"
            "- could not load raster file.");
        return _direct_values;
    }

    MathLib::Vector3 const dir(0.0, 0.0, -1.0);
    double const angle(90);
    std::string const prop_name("OriginalSubsurfaceNodeIDs");
    std::unique_ptr<MeshLib::Mesh> surface_mesh(
        MeshLib::MeshSurfaceExtraction::getMeshSurface(
            mesh, dir, angle, prop_name));

    std::vector<double> node_area_vec =
        MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(*surface_mesh);
    const std::vector<MeshLib::Node*> &surface_nodes(surface_mesh->getNodes());
    const std::size_t nNodes(surface_mesh->getNNodes());
    const double no_data(raster->getHeader().no_data);

    boost::optional<MeshLib::PropertyVector<int> const&> opt_node_id_pv(
        surface_mesh->getProperties().getPropertyVector<int>(prop_name));
    if (!opt_node_id_pv) {
        ERR(
            "Need subsurface node ids, but the property \"%s\" is not "
            "available.",
            prop_name.c_str());
        return _direct_values;
    }

    MeshLib::PropertyVector<int> const& node_id_pv(*opt_node_id_pv);
    _direct_values.reserve(nNodes);
    for (std::size_t i=0; i<nNodes; ++i)
    {
        double val(raster->getValueAtPoint(*surface_nodes[i]));
        val = (val == no_data) ? 0 : ((val*node_area_vec[i])/scaling);
        _direct_values.push_back(std::pair<std::size_t, double>(node_id_pv[i], val));
    }

    return _direct_values;
}
const std::vector< std::pair<std::size_t,double> >& DirectConditionGenerator::directWithSurfaceIntegration(MeshLib::Mesh &mesh, const std::string &filename, double scaling)
{
    if (!_direct_values.empty()) {
        ERR("Error in DirectConditionGenerator::directWithSurfaceIntegration()"
            "- Data vector contains outdated values...");
        return _direct_values;
    }

    std::unique_ptr<GeoLib::Raster> raster(
        FileIO::AsciiRasterInterface::readRaster(filename));
    if (!raster) {
        ERR("Error in DirectConditionGenerator::directWithSurfaceIntegration()"
            "- could not load raster file.");
        return _direct_values;
    }

    MathLib::Vector3 const dir(0.0, 0.0, -1.0);
    double const angle(90);
    std::string const prop_name("bulk_node_ids");
    std::unique_ptr<MeshLib::Mesh> surface_mesh(
        MeshLib::MeshSurfaceExtraction::getMeshSurface(
            mesh, dir, angle, prop_name));

    std::vector<double> node_area_vec =
        MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(*surface_mesh);
    const std::vector<MeshLib::Node*> &surface_nodes(surface_mesh->getNodes());
    const std::size_t nNodes(surface_mesh->getNumberOfNodes());
    const double no_data(raster->getHeader().no_data);

    MeshLib::PropertyVector<int> const* node_id_pv = nullptr;
    try
    {
        node_id_pv = surface_mesh->getProperties().getPropertyVector<int>(
            prop_name, MeshLib::MeshItemType::Node, 1);
    }
    catch (std::runtime_error const& e)
    {
        WARN("%s", e.what());
        return _direct_values;
    }

    _direct_values.reserve(nNodes);
    for (std::size_t i = 0; i < nNodes; ++i)
    {
        double val(raster->getValueAtPoint(*surface_nodes[i]));
        val = (val == no_data) ? 0 : ((val * node_area_vec[i]) / scaling);
        _direct_values.emplace_back((*node_id_pv)[i], val);
    }

    return _direct_values;
}
Beispiel #3
0
int main (int argc, char* argv[])
{
	ApplicationsLib::LogogSetup logog_setup;

	TCLAP::CmdLine cmd("Tool extracts the surface of the given mesh.", ' ',
	                   "0.1");
	TCLAP::ValueArg<std::string> mesh_in(
	    "i", "mesh-input-file",
	    "the name of the file containing the input mesh", true, "",
	    "file name of input mesh");
	cmd.add(mesh_in);
	TCLAP::ValueArg<std::string> mesh_out(
	    "o", "mesh-output-file",
	    "the name of the file the surface mesh should be written to", false, "",
	    "file name of output mesh");
	cmd.add(mesh_out);
	TCLAP::ValueArg<double> x("x", "x-component", "x component of the normal",
	                          false, 0, "floating point value");
	cmd.add(x);
	TCLAP::ValueArg<double> y("y", "y-component", "y component of the normal",
	                          false, 0, "floating point value");
	cmd.add(y);
	TCLAP::ValueArg<double> z("z", "z-component", "z component of the normal",
	                          false, -1.0, "floating point value");
	cmd.add(z);
	TCLAP::ValueArg<double> angle_arg(
	    "a", "angle", "angle between given normal and element normal", false,
	    90, "floating point value");
	cmd.add(angle_arg);

	cmd.parse(argc, argv);

	std::unique_ptr<MeshLib::Mesh const> mesh(
	    MeshLib::IO::readMeshFromFile(mesh_in.getValue()));
	INFO("Mesh read: %u nodes, %u elements.", mesh->getNNodes(), mesh->getNElements());

	// extract surface
	MathLib::Vector3 const dir(x.getValue(), y.getValue(), z.getValue());
	double const angle(angle_arg.getValue());
	std::unique_ptr<MeshLib::Mesh> surface_mesh(
	    MeshLib::MeshSurfaceExtraction::getMeshSurface(
	        *mesh, dir, angle, "OriginalSubsurfaceNodeIDs"));

	std::string out_fname(mesh_out.getValue());
	if (out_fname.empty())
		out_fname = BaseLib::dropFileExtension(mesh_in.getValue()) + "_sfc.vtu";
	MeshLib::IO::writeMeshToFile(*surface_mesh, out_fname);

	return EXIT_SUCCESS;
}
int main (int argc, char* argv[])
{
	ApplicationsLib::LogogSetup logog_setup;

	TCLAP::CmdLine cmd("Computes ids of mesh nodes that are in polygonal "
		"regions and resides on the top surface. The polygonal regions have to "
		"be given in a gml- or gli-file. The found mesh nodes and the associated"
		" area are written as txt and csv data."
		"The documentation is available at https://docs.opengeosys.org/docs/tools/model-preparation/computesurfacenodeidsinpolygonalregion",
		' ',
		"0.1");
	TCLAP::ValueArg<std::string> mesh_in("m", "mesh-input-file",
		"the name of the file containing the input mesh", true,
		"", "file name of input mesh");
	cmd.add(mesh_in);
	TCLAP::ValueArg<std::string> geo_in("g", "geo-file",
		"the name of the gml file containing the polygons", true,
		"", "file name of input geometry");
	cmd.add(geo_in);

	cmd.parse(argc, argv);

	std::unique_ptr<MeshLib::Mesh const> mesh(FileIO::readMeshFromFile(mesh_in.getValue()));
	INFO("Mesh read: %u nodes, %u elements.", mesh->getNNodes(), mesh->getNElements());

	GeoLib::GEOObjects geo_objs;
	FileIO::readGeometryFromFile(geo_in.getValue(), geo_objs);
	std::vector<std::string> geo_names;
	geo_objs.getGeometryNames(geo_names);
	INFO("Geometry \"%s\" read: %u points, %u polylines.",
		geo_names[0].c_str(),
		geo_objs.getPointVec(geo_names[0])->size(),
		geo_objs.getPolylineVec(geo_names[0])->size());

	MathLib::Vector3 const dir(0.0, 0.0, -1.0);
	double angle(90);

	auto computeElementTopSurfaceAreas = [](MeshLib::Mesh const& mesh,
		MathLib::Vector3 const& d, double angle)
	{
		std::unique_ptr<MeshLib::Mesh> surface_mesh(
			MeshLib::MeshSurfaceExtraction::getMeshSurface(mesh, d, angle));
		return MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(
			*surface_mesh.get());
	};

	std::vector<double> areas(computeElementTopSurfaceAreas(*mesh, dir, angle));
	std::vector<GeoLib::Point*> all_sfc_pnts(
		MeshLib::MeshSurfaceExtraction::getSurfaceNodes(*mesh, dir, angle)
	);

	std::for_each(all_sfc_pnts.begin(), all_sfc_pnts.end(), [](GeoLib::Point* p) { (*p)[2] = 0.0; });

	std::vector<MeshLib::Node*> const& mesh_nodes(mesh->getNodes());
	GeoLib::PolylineVec const* ply_vec(
		geo_objs.getPolylineVecObj(geo_names[0])
	);
	std::vector<GeoLib::Polyline*> const& plys(*(ply_vec->getVector()));

	for (std::size_t j(0); j<plys.size(); j++) {
		if (! plys[j]->isClosed()) {
			continue;
		}
		std::string polygon_name;
		ply_vec->getNameOfElement(plys[j], polygon_name);
		if (polygon_name.empty())
			polygon_name = "Polygon-" + std::to_string(j);
		// create Polygon from Polyline
		GeoLib::Polygon const& polygon(*(plys[j]));
		// ids of mesh nodes on surface that are within the given polygon
		std::vector<std::pair<std::size_t, double>> ids_and_areas;
		for (std::size_t k(0); k<all_sfc_pnts.size(); k++) {
			GeoLib::Point const& pnt(*(all_sfc_pnts[k]));
			if (polygon.isPntInPolygon(pnt)) {
				ids_and_areas.push_back(std::make_pair(pnt.getID(), areas[k]));
			}
		}
		if (ids_and_areas.empty()) {
			ERR("Polygonal part of surface \"%s\" doesn't contains nodes. No "
				"output will be generated.", polygon_name.c_str());
			continue;
		}

		std::string const out_path(BaseLib::extractPath(geo_in.getValue()));
		std::string id_and_area_fname(out_path + polygon_name);
		std::string csv_fname(out_path + polygon_name);
		id_and_area_fname += std::to_string(j) + ".txt";
		csv_fname += std::to_string(j) + ".csv";
		INFO("Polygonal part of surface \"%s\" contains %ul nodes. Writting to"
			" files \"%s\" and \"%s\".",
			polygon_name.c_str(),
			ids_and_areas.size(),
			id_and_area_fname.c_str(),
			csv_fname.c_str()
		);
		writeToFile(id_and_area_fname, csv_fname, ids_and_areas, mesh_nodes);
	}

	std::for_each(all_sfc_pnts.begin(), all_sfc_pnts.end(), std::default_delete<GeoLib::Point>());

	return 0;
}
int main (int argc, char* argv[])
{
	ApplicationsLib::LogogSetup logog_setup;

	TCLAP::CmdLine cmd(
		"Creates boundary conditions for mesh nodes along polylines."
		"The documentation is available at https://docs.opengeosys.org/docs/tools/model-preparation/create-boundary-conditions-along-a-polyline",
		' ',
		"0.1");
	TCLAP::ValueArg<bool> gml_arg("", "gml",
		"if switched on write found nodes to file in gml format", false, 0, "bool");
	cmd.add(gml_arg);

	TCLAP::ValueArg<std::string> output_base_fname("o", "output-base-file-name",
		"the base name of the file the output (geometry (gli) and boundary"\
		"condition (bc)) will be written to", true,
		"", "file name");
	cmd.add(output_base_fname);

	TCLAP::ValueArg<std::string> bc_type("t", "type",
		"the process type the boundary condition will be written for "\
		"currently LIQUID_FLOW (primary variable PRESSURE1) and "\
		"GROUNDWATER_FLOW (primary variable HEAD, default) are supported", true,
		"",
		"process type as string (LIQUID_FLOW or GROUNDWATER_FLOW (default))");
	cmd.add(bc_type);

	TCLAP::ValueArg<double> search_length_arg("s", "search-length",
		"The size of the search length. The default value is "
		"std::numeric_limits<double>::epsilon()", false,
		std::numeric_limits<double>::epsilon(), "floating point number");
	cmd.add(search_length_arg);

	TCLAP::ValueArg<std::string> geometry_fname("i", "input-geometry",
		"the name of the file containing the input geometry", true,
		"", "file name");
	cmd.add(geometry_fname);

	TCLAP::ValueArg<std::string> mesh_arg("m", "mesh-file",
		"the name of the file containing the mesh", true,
		"", "file name");
	cmd.add(mesh_arg);

	cmd.parse(argc, argv);

	// *** read mesh
	INFO("Reading mesh \"%s\" ... ", mesh_arg.getValue().c_str());
	MeshLib::Mesh * subsurface_mesh(FileIO::readMeshFromFile(mesh_arg.getValue()));
	INFO("done.");
	INFO("Extracting top surface of mesh \"%s\" ... ",
		mesh_arg.getValue().c_str());
	const MathLib::Vector3 dir(0,0,-1);
	double const angle(90);
	std::unique_ptr<MeshLib::Mesh> surface_mesh(
	    MeshLib::MeshSurfaceExtraction::getMeshSurface(*subsurface_mesh, dir,
	                                                   angle));
	INFO("done.");
	delete subsurface_mesh;
	subsurface_mesh = nullptr;

	// *** read geometry
	GeoLib::GEOObjects geometries;
	FileIO::readGeometryFromFile(geometry_fname.getValue(), geometries);

	std::string geo_name;
	{
		std::vector<std::string> geo_names;
		geometries.getGeometryNames(geo_names);
		geo_name = geo_names[0];
	}

	// *** check if the data is usable
	// *** get vector of polylines
	std::vector<GeoLib::Polyline*> const* plys(geometries.getPolylineVec(geo_name));
	if (!plys) {
		ERR("Could not get vector of polylines out of geometry \"%s\".",
			geo_name.c_str());
		return -1;
	}

	MeshGeoToolsLib::SearchLength search_length_strategy;
	if (search_length_arg.isSet()) {
		search_length_strategy =
			MeshGeoToolsLib::SearchLength(search_length_arg.getValue());
	}

	GeoLib::GEOObjects geometry_sets;
	MeshGeoToolsLib::MeshNodeSearcher mesh_searcher(*surface_mesh,
		search_length_strategy);
	for(std::size_t k(0); k<plys->size(); k++) {
		std::vector<std::size_t> ids
			(mesh_searcher.getMeshNodeIDsAlongPolyline(*((*plys)[k])));
		if (ids.empty())
			continue;
		std::string geo_name("Polyline-"+std::to_string(k));
		convertMeshNodesToGeometry(surface_mesh->getNodes(), ids, geo_name,
			geometry_sets);
	}

	// merge all together
	std::vector<std::string> geo_names;
	geometry_sets.getGeometryNames(geo_names);
	if (geo_names.empty()) {
		ERR("Did not find mesh nodes along polylines.");
		return -1;
	}

	std::string merge_name("AllMeshNodesAlongPolylines");
	if (geometry_sets.mergeGeometries(geo_names, merge_name) == 2)
		merge_name = geo_names[0];

	GeoLib::PointVec const* pnt_vec(geometry_sets.getPointVecObj(merge_name));
	std::vector<GeoLib::Point*> const* merged_pnts(pnt_vec->getVector());

	std::vector<GeoLib::Point> pnts_with_id;
	const std::size_t n_merged_pnts(merged_pnts->size());
	for(std::size_t k(0); k<n_merged_pnts; ++k) {
		pnts_with_id.emplace_back(*((*merged_pnts)[k]), k);
	}

	std::sort(pnts_with_id.begin(), pnts_with_id.end(),
		[](GeoLib::Point const& p0, GeoLib::Point const& p1)
			{ return p0 < p1; }
	);

	double const eps (std::numeric_limits<double>::epsilon());
	auto surface_pnts = std::unique_ptr<std::vector<GeoLib::Point*>>(
	    new std::vector<GeoLib::Point*>);
	std::map<std::string, std::size_t> *name_id_map(
		new std::map<std::string, std::size_t>
	);

	// insert first point
	surface_pnts->push_back(
		new GeoLib::Point(pnts_with_id[0], surface_pnts->size()));
	std::string element_name;
	pnt_vec->getNameOfElementByID(0, element_name);
	name_id_map->insert(
		std::pair<std::string, std::size_t>(element_name,0)
	);
	for (std::size_t k(1); k < n_merged_pnts; ++k) {
		const GeoLib::Point& p0 (pnts_with_id[k-1]);
		const GeoLib::Point& p1 (pnts_with_id[k]);
		if (std::abs (p0[0] - p1[0]) > eps || std::abs (p0[1] - p1[1]) > eps) {
			surface_pnts->push_back(new GeoLib::Point(pnts_with_id[k],
				surface_pnts->size()));
			std::string element_name;
			pnt_vec->getNameOfElementByID(k, element_name);
			name_id_map->insert(
				std::pair<std::string, std::size_t>(element_name,
				surface_pnts->size()-1)
			);
		}
	}

	std::string surface_name(BaseLib::dropFileExtension(mesh_arg.getValue())+"-MeshNodesAlongPolylines");
	geometry_sets.addPointVec(std::move(surface_pnts), surface_name, name_id_map, 1e-6);

	// write the BCs and the merged geometry set to file
	std::string const base_fname(
	    BaseLib::dropFileExtension(output_base_fname.getValue()));
	writeBCsAndGeometry(geometry_sets, surface_name, base_fname,
	                    bc_type.getValue(), gml_arg.getValue());
	return 0;
}
Beispiel #6
0
int main(int argc, char* argv[])
{
    ApplicationsLib::LogogSetup logo_setup;

    TCLAP::CmdLine cmd(
        "Integrates the given element property and outputs an OGS-5 direct "
        "Neumann boundary condition. The mesh has to contain a property "
        "'bulk_node_ids' that stores the original subsurface "
        "mesh node ids. Such surface meshes can be created using the OGS-6 "
        "tool ExtractSurface.\n\n"
        "OpenGeoSys-6 software, version " +
            BaseLib::BuildInfo::git_describe +
            ".\n"
            "Copyright (c) 2012-2019, OpenGeoSys Community "
            "(http://www.opengeosys.org)",
        ' ', BaseLib::BuildInfo::git_describe);

    TCLAP::ValueArg<std::string> in_mesh("i",
                                         "in-mesh",
                                         "the surface mesh that has an element "
                                         "property for the Neumann "
                                         "boundary condition",
                                         true,
                                         "",
                                         "filename for surface mesh input");
    cmd.add(in_mesh);

    TCLAP::ValueArg<std::string> property_in_arg(
        "p",
        "property-in-name",
        "name of an element property used for the computation of the "
        "Neumann boundary condition",
        true,
        "",
        "string (property name)");
    cmd.add(property_in_arg);

    TCLAP::ValueArg<std::string> property_out_arg(
        "",
        "property-out-name",
        "name of the node based property used for the output of the "
        "Neumann boundary condition",
        true,
        "",
        "string (property name)");
    cmd.add(property_out_arg);

    TCLAP::ValueArg<std::string> result_file(
        "o",
        "result-out",
        "the file name the result will be written to ",
        true,
        "",
        "output file name");
    cmd.add(result_file);
    cmd.parse( argc, argv );

    // read surface mesh
    std::unique_ptr<MeshLib::Mesh> surface_mesh(
        MeshLib::IO::readMeshFromFile(in_mesh.getValue()));

    auto const* const node_id_pv =
        [&]() -> MeshLib::PropertyVector<std::size_t>* {
        try
        {
            return surface_mesh->getProperties().getPropertyVector<std::size_t>(
                "bulk_node_ids", MeshLib::MeshItemType::Node, 1);
        }
        catch (std::runtime_error const& e)
        {
            WARN("%s", e.what());
            return nullptr;
        }
    }();
    if (!node_id_pv)
        return EXIT_FAILURE;

    std::vector<double> integrated_values = getSurfaceIntegratedValuesForNodes(
        *surface_mesh, property_in_arg.getValue());
    std::vector<std::pair<std::size_t, double>> direct_values;
    direct_values.reserve(surface_mesh->getNumberOfNodes());

    for (auto const* node : surface_mesh->getNodes())
    {
        auto const id(node->getID());
        auto const subsurface_node_id((*node_id_pv)[id]);
        auto const val(integrated_values[id]);
        direct_values.push_back(std::make_pair(subsurface_node_id, val));
    }

    auto* const pv =
        surface_mesh->getProperties().createNewPropertyVector<double>(
            property_out_arg.getValue(), MeshLib::MeshItemType::Node, 1);
    pv->resize(surface_mesh->getNodes().size());
    for (std::size_t k(0); k < surface_mesh->getNodes().size(); ++k)
    {
        (*pv)[k] = direct_values[k].second;
    }

    MeshLib::IO::writeMeshToFile(*surface_mesh, result_file.getValue());

    std::ofstream result_out(result_file.getValue() + ".txt");
    result_out.precision(std::numeric_limits<double>::digits10);
    for (auto const& p : direct_values)
        result_out << p.first << " " << p.second << "\n";

    return EXIT_SUCCESS;
}
int main (int argc, char* argv[])
{
    ApplicationsLib::LogogSetup logog_setup;

    TCLAP::CmdLine cmd("The tool computes the area per node of the surface mesh"
        " and writes the information as txt and csv data.", ' ', "0.1");
    TCLAP::ValueArg<std::string> mesh_in("i", "mesh-input-file",
        "the name of the file containing the input mesh", true,
        "", "file name of input mesh");
    cmd.add(mesh_in);
    TCLAP::ValueArg<std::string> id_prop_name("", "id-prop-name",
        "the name of the property containing the id information", false,
        "OriginalSubsurfaceNodeIDs", "property name");
    cmd.add(id_prop_name);
    TCLAP::ValueArg<std::string> out_base_fname("p", "output-base-name",
        "the path and base file name the output will be written to", false,
        "", "output path and base name as one string");
    cmd.add(out_base_fname);

    cmd.parse(argc, argv);

    std::unique_ptr<MeshLib::Mesh> surface_mesh(
        MeshLib::IO::readMeshFromFile(mesh_in.getValue()));
    INFO("Mesh read: %u nodes, %u elements.", surface_mesh->getNNodes(),
         surface_mesh->getNElements());
    // ToDo check if mesh is read correct and if the mesh is a surface mesh

    // check if a node property containing the subsurface ids is available
    boost::optional<MeshLib::PropertyVector<std::size_t> const&> orig_node_ids(
        surface_mesh->getProperties().getPropertyVector<std::size_t>(
            id_prop_name.getValue()));
    // if the node property is not available generate it
    if (!orig_node_ids) {
        boost::optional<MeshLib::PropertyVector<std::size_t>&> node_ids(
            surface_mesh->getProperties().createNewPropertyVector<std::size_t>(
                id_prop_name.getValue(), MeshLib::MeshItemType::Node, 1));
        if (!node_ids) {
            ERR("Fatal error: could not create property.");
            return EXIT_FAILURE;
        }
        node_ids->resize(surface_mesh->getNNodes());
        std::iota(node_ids->begin(), node_ids->end(), 0);
        orig_node_ids = node_ids;
    }

    std::vector<double> areas(
        MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(*surface_mesh));

    // pack area and node id together
    std::vector<std::pair<std::size_t, double>> ids_and_areas;
    std::transform(orig_node_ids->cbegin(), orig_node_ids->cend(),
                   areas.cbegin(), std::back_inserter(ids_and_areas),
                   std::make_pair<std::size_t const&, double const&>);

    // generate file names for output
    std::string path(out_base_fname.getValue());
    if (path.empty())
        path = BaseLib::dropFileExtension(mesh_in.getValue());
    std::string const id_and_area_fname(path+".txt");
    std::string const csv_fname(path+".csv");

    writeToFile(id_and_area_fname, csv_fname, ids_and_areas,
                surface_mesh->getNodes());

    return EXIT_SUCCESS;
}