Inserting Category programmatically

Keep track of the return value of wp_insert_term and use it to build your structure. A successful return value will be an array with a term_id key that you can pass into wp_insert_term‘s $args array as parent.

$parent = wp_insert_term('Science', 'category'); // I'll leave out `$args` here
if (is_wp_error($parent)) {
  // insert didn't work! return from your function or error or whatever
  return;
}

// grade 11 category has "Sience" as its parent
$grade11 = wp_insert_term('Grade 11', 'category', ['parent' => $parent['term_id']]);
if (is_wp_error($grade11)) {
  // same as above, something went wrong
  return;
}

// Management has the parent "Grade 11"
wp_insert_term('Management', 'category', ['parent' => $grade11['term_id']]);

As far as only inserting one time, you can hook into after_switch_theme and do your stuff. You’ll probably want to look up your term first to make sure it hasn’t been inserted, or set an option with the inserted term ID on success.

add_action('after_switch_theme', 'wpse206511_switch');
function wpse206511_switch()
{
    if (get_option('wpse206511_term_id')) {
        // already done, bail
        return;
    }

    // category insert code from above

    // set the term ID in an option that you can check later
    // if/when the theme gets activated/deactivated again
    add_option('wpse206511_term_id', $parent['term_id']);
}