3d printing is an ideal application for boolean modeling, it works much better than trying to work with a single large subsurf model: Many objects with variable need for detail, the need for a manifold model, no need for texturing, and no need to bevel the edges after combining the objects (because of the resolution limit of printing). Be careful: Simply applying a subsurface modifier doesn't necessarily make the model look better. For example you actually want the rivets to have a sharp edge to the surface to look more realistic. And subsurf causes artifacts with n-gons, like the rides in your cylinder faces.
Here's what I would do for your model (I can't show pictures, I'm on my slow laptop and blender crashed when opening your file, likely because of the huge amount of vertices caused by your level 6 subdiv):
- Turn down the subdiv on your model to make blender lag less (and put the "render" subdivs to zero (= as many as "view"), I'm not sure which of the 2 gets chosen on file export)
- Enable the addon "bool tools" in preferences, it comes preinstalled with blender
- Model your main subway hull with very little detail, something like 6 vertices across the whole width, and only a single face thick. This way you can easily adjust the shape later on. Add a subdiv modifier and a solidify (be careful that the curves aren't too sharp so the solidify doesn't create non-manifold geometry). You can use a mirror modifier, but you can also just work on one side and in the end delete the other and mirror destructively for perfect symmetry
- Model the window, use less detail than in your model and let a subdivision surface modifier do the smoothing. It is best to model the window flat on the ground extrude vertically via modifier, and move it into place later, this makes placing the rivets easier and allows duplication of the window so you only have to model it once
- Model a single rivet. Use a cylinder with much less vertices, e.g. 8, and let a subsurf do the smoothing. Extrude the central n-gon without moving and scale it smaller, so you don't get the ridge artifacts from the subsurf
- Place rivets along the window. Duplicate your rivets instead of copying, so you can still easily make changes affecting every rivet. There are many ways to do this, if you wanna be fancy you can use an array and a curve modifier to automatically add them with a certain distance between, but you can also just manually alt-d duplicate a rivet, left click on a place on the window, and shift-s snap selected to cursor. If you do it that way be careful that the rivets intersect the window before you add the booleans
- Boolean union the rivets to the window: Select all the rivets, and select the window as active object, then use the lower boolean-union button from the bool-tools addon in the left toolshelf, to add boolean modifiers for all rivet objects.
- Place the window on the main model, intersecting it. Model a rough stencil object inside the window and going outside the main model on both sides, select it, then the main model and use the boolean difference from bool-tool. Then select the window object, then the main model, and use the union button from bool-tool.
- Model the lights the same way, first a boolean difference with the main model, then a boolean union.
- You can easily add more rivets anywhere on the main model with duplication and then boolean union.
When you model this way you can change the subdivision level depending on the needed detail: e.g. the main frame will need more subdivs than the little rivets. And the main problems of boolean modeling, restrictions on beveling and ugly geometry for unwrapping, texturing, and subsurfing, dont matter for your use case.