Our team is working on software that does a lot of calculations, inputs are quite immense structures and outputs are calculated data for the GUI (around 10 tables, warnings, and other messages produced deep in the code). I think neither the input data structures can be smaller, nor the outputs. The generated output to the GUI and for example warning messages are being sent from the place where they have occurred. I think it's not a good idea to put them into the output structures, they would create outputs very hard to test and data would have to go unnecessarily through many layers of code. On the other hand, I hate having these side effects. Is there any architectural approach how to deal with these side effects?
There is no silver bullet to solve your issue.
That does not mean it cannot be solved, though "solved" is probably be the wrong term. A better description is IMHO "it can be managed", since there is not just one solution, but only a set of techniques and practices your team can apply.
Without claiming of being exhaustive:
Try to split your system into separate, individual components where each one has a strictly defined input and output. Implement a clear data flow between the different components of your system. Visualize the flow using diagrams, and model precisely what input goes into a certain calculation, and what output comes out (including the warning messages).
Warning messages which are only for the purpose of logging should be fed into a separate stream or output channel, which does not have any real influence on the flow of control. What kind of channel or channels you need is nothing I can tell you from this 100,000 feet view, for this you have to provide some more details.
Warnings or error messages in a batch process which refer to certain input records should either be directly included in the output for the specific record, or keep a machine-readable reference to their input. That will allow you to either sort the records out, handle them in a special manner or process them later.
Your team should gather some expertise in functional programming, immutable data structures and techniques like map-reduce.
This is all which comes into my mind right now, I guess I have missed a few things, but I think you get the general idea - your team needs a tool box, not just "one ring to rule them all".