Commit 1536ebca authored by Marco Bomben's avatar Marco Bomben Committed by Simon Spannagel
Browse files

1st working version of SilvacoParser

(cherry picked from commit 0f508ae4)
parent ae599251
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ ADD_EXECUTABLE(
    MeshConverter.cpp
    MeshParser.cpp
    parsers/DFISEParser.cpp
    parsers/SilvacoParser.cpp
    ${ALLPIX_SRC}/core/utils/log.cpp
    ${ALLPIX_SRC}/core/utils/text.cpp
    ${ALLPIX_SRC}/core/utils/unit.cpp
+4 −1
Original line number Diff line number Diff line
@@ -7,9 +7,11 @@ using namespace mesh_converter;
std::shared_ptr<MeshParser> MeshParser::factory(const allpix::Configuration& config) {
    auto parser = config.get<std::string>("parser", "df-ise");
    std::transform(parser.begin(), parser.end(), parser.begin(), ::tolower);

    LOG(DEBUG) << "Parser \"" << parser  << "\"\n";
    if(parser == "df-ise" || parser == "dfise") {
        return std::make_shared<DFISEParser>();
    } else if(parser == "silvaco" || parser == "Silvaco") {
        return std::make_shared<SilvacoParser>();
    } else {
        throw allpix::InvalidValueError(config, "parser", "Unknown parser type");
    }
@@ -70,6 +72,7 @@ MeshParser::getField(const std::string& file, const std::string& observable, con
    for(const auto& region : regions) {
        if(field_map_[file].find(region) != field_map_[file].end() &&
           field_map_[file][region].find(observable) != field_map_[file][region].end()) {
            LOG(DEBUG) << "Region \"" << region  << "\"\n";
            field.insert(
                field.end(), field_map_[file][region][observable].begin(), field_map_[file][region][observable].end());
        } else {
+1 −0
Original line number Diff line number Diff line
@@ -59,5 +59,6 @@ namespace mesh_converter {
} // namespace mesh_converter

#include "parsers/DFISEParser.hpp"
#include "parsers/SilvacoParser.hpp"

#endif // ALLPIX_MESHPARSER_H
+225 −0
Original line number Diff line number Diff line
/**
 * @file
 *
 * @copyright Copyright (c) 2017-2022 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 * SPDX-License-Identifier: MIT
 */

#include "SilvacoParser.hpp"

#include <cassert>
#include <cstdlib>
#include <exception>
#include <fstream>
#include <iostream>
#include <regex>
#include <set>
#include <string>
#include <sstream>
#include "TFile.h"
#include "TTree.h"

#include "core/utils/log.h"
#include "core/utils/text.h"

using namespace mesh_converter;

MeshMap SilvacoParser::read_meshes(const std::string& file_name) {
    /*// changing file extension
    std::string original_file_name = file_name; // save a copy just in case
    std::string silvaco_extension = "dat";
    string::size_type i = file_name.rfind('.', file_name.length());

   if (i != string::npos) {
      file_name.replace(i+1, silvaco_extension.length(), silvaco_extension);
   }
   */
 
    std::ifstream file(file_name);
    if(!file) {
        throw std::runtime_error("file cannot be accessed");
    }

    // Get the total number of lines to parse and reset file to the start:
    auto num_lines = std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n');
    file.clear();
    file.seekg(0, std::ios::beg);
    LOG(DEBUG) << "Grid file contains " << num_lines << " lines to parse";


    std::vector<Point> vertices;

    std::string region = "Silicon";
    long unsigned int dimension = 1;
    long unsigned int columns_count = 0;
    long long num_lines_parsed = 0;
    while(!file.eof()) {
        std::string line;
        std::getline(file, line);

        // Log the parsing progress:
        if(num_lines > 0 && num_lines_parsed % 1000 == 0) {
            LOG_PROGRESS(STATUS, "gridlines") << "Parsing grid file: " << (100 * num_lines_parsed / num_lines) << "%";
        }
        num_lines_parsed++;

        line = allpix::trim(line);
        if(line.empty()) {
            continue;
        }

        // Determining number of columns by counting fields in first line
        if ( num_lines_parsed == 1 ) {
            std::istringstream iss;
            iss.str(line);
            double val;
            while ( iss >> val ) {
                columns_count++;
            }
            iss.clear();
        }
        dimension = columns_count;
 

        // Handle data
        std::stringstream sstr(line);
        // Read vertex points
        if(dimension == 3) {
            double x = 0, y = 0, z = 0;
                while(sstr >> x >> y >> z) {
                    vertices.emplace_back(x, y, z);
                }
        }
        if(dimension == 2) {
            double y = 0, z = 0;
            while(sstr >> y >> z) {
                vertices.emplace_back(y, z);
            }
        }
        
    }
    LOG_PROGRESS(STATUS, "gridlines") << "Parsing grid file: done.";


    

    std::map<std::string, std::vector<Point>> ret_map;
        // std::vector<Point> ret_vector; // same thing as vertices for Silvaco

        ret_map[region] = vertices;

    return ret_map;
}

FieldMap SilvacoParser::read_fields(const std::string& file_name) {
    std::ifstream file(file_name);
    if(!file) {
        throw std::runtime_error("file cannot be accessed");
    }

    // Get the total number of lines to parse and reset file to the start:
    auto num_lines = std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n');
    file.clear();
    file.seekg(0, std::ios::beg);
    LOG(DEBUG) << "Field data file contains " << num_lines << " lines to parse";


    // std::map<std::string, std::vector<Point>> region_electric_field_map;
    std::map<std::string, std::map<std::string, std::vector<Point>>> region_electric_field_map;
    std::vector<double> region_electric_field_num;

    std::string region = "Silicon";
    std::string observable;
    long unsigned int dimension = 1;
    long long num_lines_parsed = 0;
    long unsigned int columns_count = 0;
    while(!file.eof()) {
        std::string line;
        std::getline(file, line);
        line = allpix::trim(line);

        // Log the parsing progress:
        if(num_lines > 0 && num_lines_parsed % 1000 == 0) {
            LOG_PROGRESS(STATUS, "fieldlines") << "Parsing field data file: " << (100 * num_lines_parsed / num_lines) << "%";
        }
        num_lines_parsed++;

        if(line.empty()) {
            continue;
        }

        // Determining number of columns by counting fields in first line
        if ( num_lines_parsed == 1 ) {
            std::istringstream iss;
            iss.str(line);
            double val;
            while ( iss >> val ) {
                columns_count++;
            }
            dimension = columns_count;
            
            // Determining data type from dimensions
            // dimension == 1 -> Scalar potential
            // dimension == 2 -> 2D electric field
            // dimension == 3 -> 3D electric field
            if ( dimension == 1 ) {
                observable = "ElectrostaticPotential";
            } else if ( dimension == 2 ) {
                observable = "ElectricField";
            } else if ( dimension == 3 ) {
                observable = "ElectricField";
            } else {
                throw std::runtime_error("incorrect dimension of observable");
            }
            
            iss.clear();
        }
 



        // Handle data
        std::stringstream sstr(line);
        double num = NAN;
        while(sstr >> num) {
            region_electric_field_num.push_back(num);
        }
    
        if( dimension == 1 ) {
            for(size_t i = 0; i < region_electric_field_num.size(); i += 1) {
                auto x = region_electric_field_num[i];
                region_electric_field_map[region][observable].emplace_back(x, 0, 0);
            }

            region_electric_field_num.clear();
        }


        if(dimension == 3) {
            for(size_t i = 0; i < region_electric_field_num.size(); i += 3) {
                auto x = region_electric_field_num[i];
                auto y = region_electric_field_num[i + 1];
                auto z = region_electric_field_num[i + 2];
                region_electric_field_map[region][observable].emplace_back(x, y, z);
            }
        }

        if(dimension == 2) {
            for(size_t i = 0; i < region_electric_field_num.size(); i += 2) {
                auto x = region_electric_field_num[i];
                auto y = region_electric_field_num[i + 1];
                region_electric_field_map[region][observable].emplace_back(0, x, y);
             }
        }

        region_electric_field_num.clear();
    }


    LOG_PROGRESS(STATUS, "fieldlines") << "Parsing field data file: done.";

    return region_electric_field_map;
}
+53 −0
Original line number Diff line number Diff line
/**
 * @file
 *
 * @copyright Copyright (c) 2017-2022 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 * SPDX-License-Identifier: MIT
 */

#ifndef ALLPIX_MESHPARSER_SILVACO_H
#define ALLPIX_MESHPARSER_SILVACO_H

#include "../MeshParser.hpp"

#include <iostream>
#include <map>
#include <vector>

namespace mesh_converter {

    class SilvacoParser : public MeshParser {
        // Sections to read in extracted files
        enum class DFSection {
            NONE = 0,
            IGNORED,
            HEADER,
            INFO,
            REGION,
            COORDINATES,
            VERTICES,
            EDGES,
            FACES,
            ELEMENTS,

            DONOR_CONCENTRATION,
            DOPING_CONCENTRATION,
            ACCEPTOR_CONCENTRATION,
            ELECTRIC_FIELD,
            ELECTROSTATIC_POTENTIAL,
            VALUES
        };

    private:
        // Read the grid
        MeshMap read_meshes(const std::string& file_name) override;

        // Read the electric field
        FieldMap read_fields(const std::string& file_name) override;
    };
} // namespace mesh_converter

#endif // ALLPIX_MESHPARSER_SILVACO_H