diff --git a/applications/OptimizationApplication/python_scripts/processes/optimization_problem_vtu_output_process.py b/applications/OptimizationApplication/python_scripts/processes/optimization_problem_vtu_output_process.py index af836c71ce35..957e28ce6c41 100644 --- a/applications/OptimizationApplication/python_scripts/processes/optimization_problem_vtu_output_process.py +++ b/applications/OptimizationApplication/python_scripts/processes/optimization_problem_vtu_output_process.py @@ -75,7 +75,7 @@ def __init__(self, parameters: 'dict[str, Any]', model_part: Kratos.ModelPart, o else: self.output_path = Path(".") - self.vtu_output: Kratos.Future.VtuOutput = Kratos.Future.VtuOutput(model_part, parameters["configuration"], parameters["writer_format"], parameters["precision"], output_sub_model_parts=True, echo_level=parameters["echo_level"], write_ids=parameters["write_ids"]) + self.vtu_output: Kratos.VtuOutput = Kratos.VtuOutput(model_part, parameters["is_initial_configuration"], parameters["writer_format"], parameters["precision"], output_sub_model_parts=True, echo_level=parameters["echo_level"], write_ids=parameters["write_ids"]) self.list_of_tensor_adaptor_data: 'list[TensorAdaptorData]' = [] def AddTensorAdaptorData(self, tensor_adaptor_data: TensorAdaptorData) -> bool: @@ -128,20 +128,17 @@ def __init__(self, model: Kratos.Model, parameters: Kratos.Parameters, optimizat self.write_ids = parameters["write_ids"].GetBool() file_format = parameters["file_format"].GetString() if file_format == "ascii": - self.writer_format = Kratos.Future.VtuOutput.ASCII + self.writer_format = Kratos.VtuOutput.ASCII elif file_format == "binary": - self.writer_format = Kratos.Future.VtuOutput.BINARY + self.writer_format = Kratos.VtuOutput.BINARY elif file_format == "raw": - self.writer_format = Kratos.Future.VtuOutput.RAW + self.writer_format = Kratos.VtuOutput.RAW elif file_format == "compressed_raw": - self.writer_format = Kratos.Future.VtuOutput.COMPRESSED_RAW + self.writer_format = Kratos.VtuOutput.COMPRESSED_RAW else: raise RuntimeError(f"Only supports \"ascii\", \"binary\", \"raw\", and \"compressed_raw\" file_format. [ provided file_format = \"{file_format}\" ].") - if parameters["write_deformed_configuration"].GetBool(): - self.configuration = Kratos.Configuration.Current - else: - self.configuration = Kratos.Configuration.Initial + self.is_initial_configuration = not parameters["write_deformed_configuration"].GetBool() self.list_of_component_names = parameters["list_of_output_components"].GetStringArray() self.list_of_tensor_adaptor_vtu_outputs: 'list[TensorAdaptorVtuOutput]' = [] @@ -194,7 +191,7 @@ def _AddContainerTensorAdaptor(self, tensor_adaptor_data: TensorAdaptorData): if not found_vtu_output: vtu_parameters = { "output_file_name_prefix": self.file_name, - "configuration": self.configuration, + "is_initial_configuration": self.is_initial_configuration, "writer_format": self.writer_format, "precision": self.output_precision, "save_output_files_in_folder": self.save_output_files_in_folder, diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_constant.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_constant.vtu index a86b2420840e..79fa9ef1662b 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_constant.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_constant.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -2.954690e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.076218e-01 6.730670e-02 -2.698146e-01 -3.684091e-01 3.682268e-02 -3.210687e-01 -2.152692e-01 1.696515e-01 -8.165576e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.201263e-01 2.427572e-01 -1.393353e-01 -2.057058e-01 1.764073e-01 -2.991886e-02 -3.652212e-01 4.020307e-02 -2.923024e-01 -6.213435e-02 2.469612e-01 1.230270e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 8.486384e-02 2.546585e-01 7.102194e-02 -1.981571e-01 1.665123e-01 -3.725551e-02 -3.157286e-02 2.356577e-01 1.753316e-01 -3.578146e-01 3.830592e-02 -1.995909e-01 1.408093e-01 2.447731e-01 -5.000000e-01 2.542415e-01 2.301170e-01 -3.392484e-01 2.635720e-01 2.484821e-01 3.289313e-01 -5.000000e-01 0.000000e+00 1.686987e-01 -2.344447e-02 1.899916e-01 2.752834e-01 -1.876647e-01 1.105251e-01 4.651544e-02 1.553755e-01 2.299026e-01 -1.946200e-01 3.014690e-01 2.421528e-01 3.789940e-01 -3.494305e-01 3.224430e-02 -7.595017e-02 2.822785e-01 2.385466e-01 -5.000000e-01 3.894072e-01 2.360903e-01 -3.974708e-01 4.025171e-01 2.427420e-01 -2.400169e-01 4.028732e-01 2.438698e-01 3.160794e-02 3.053247e-01 2.304882e-01 3.629834e-01 -1.880867e-02 6.147739e-02 -1.319979e-01 4.029774e-01 2.357441e-01 2.863519e-01 1.357811e-01 1.110552e-01 1.332429e-01 2.834209e-01 1.937152e-01 5.281389e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 2.152277e-01 -3.988510e-01 5.000000e-01 2.008792e-01 -2.211396e-02 4.033233e-01 2.138188e-01 -2.937882e-01 5.000000e-01 2.101694e-01 5.357141e-01 -3.036836e-01 0.000000e+00 -1.873007e-01 5.000000e-01 1.956806e-01 7.894423e-02 4.033102e-01 2.088962e-01 2.533139e-01 2.989023e-01 1.271129e-01 -8.245013e-02 5.000000e-01 1.928728e-01 5.387344e-01 -1.085301e-01 0.000000e+00 1.823984e-01 4.033293e-01 1.680583e-01 2.526017e-02 5.000000e-01 1.922700e-01 3.801274e-01 2.670541e-01 3.722506e-02 1.270189e-01 5.000000e-01 1.712776e-01 5.382499e-01 9.470425e-02 0.000000e+00 2.828839e-01 4.037465e-01 7.916664e-02 2.266649e-01 5.000000e-01 9.571167e-02 5.364034e-01 2.580094e-01 0.000000e+00 4.331546e-01 4.032447e-01 1.492143e-02 3.292619e-01 5.000000e-01 4.987022e-02 5.324171e-01 3.904917e-01 0.000000e+00 4.279950e-01 5.000000e-01 1.038714e-02 5.300883e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_cosine.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_cosine.vtu index 83716bed3169..35842a636f95 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_cosine.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_cosine.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -2.991491e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.100072e-01 4.989820e-02 -2.748267e-01 -3.702636e-01 2.693719e-02 -3.245682e-01 -2.254517e-01 1.489256e-01 -9.196332e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.280630e-01 2.070997e-01 -1.450095e-01 -2.189538e-01 1.749638e-01 -3.659211e-02 -3.673344e-01 3.140215e-02 -2.954990e-01 -7.607154e-02 2.981890e-01 1.182097e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 8.582400e-02 2.638892e-01 7.642142e-02 -2.072924e-01 1.605990e-01 -3.029159e-02 -4.244769e-02 3.105166e-01 1.752558e-01 -3.587013e-01 2.914530e-02 -2.034831e-01 1.411768e-01 3.098708e-01 -5.000000e-01 2.584408e-01 2.268754e-01 -3.414377e-01 2.681899e-01 2.538098e-01 3.217517e-01 -5.000000e-01 0.000000e+00 1.881924e-01 -2.704537e-02 2.105209e-01 2.847983e-01 -1.909550e-01 9.555792e-02 5.526918e-02 1.585090e-01 2.659499e-01 -2.004494e-01 3.050502e-01 2.462800e-01 3.777562e-01 -3.496018e-01 2.333182e-02 -7.851439e-02 2.866093e-01 2.448954e-01 -5.000000e-01 3.910091e-01 1.775422e-01 -3.986135e-01 4.038014e-01 1.891308e-01 -2.450655e-01 4.045503e-01 1.991841e-01 3.197844e-02 3.088370e-01 2.109643e-01 3.780917e-01 -1.709096e-02 5.252044e-02 -1.382457e-01 4.045633e-01 1.948586e-01 3.012772e-01 1.413521e-01 8.940033e-02 1.376671e-01 2.873000e-01 1.737178e-01 5.190268e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 1.375057e-01 -3.996857e-01 5.000000e-01 1.516662e-01 -3.014878e-02 4.045626e-01 1.797287e-01 -2.981346e-01 5.000000e-01 1.575114e-01 5.305128e-01 -3.026884e-01 0.000000e+00 -1.940829e-01 5.000000e-01 1.568791e-01 7.628034e-02 4.045778e-01 1.523165e-01 2.585399e-01 3.025401e-01 8.752896e-02 -8.793837e-02 5.000000e-01 1.464772e-01 5.424553e-01 -1.051667e-01 0.000000e+00 1.804156e-01 4.045889e-01 1.034956e-01 1.770496e-02 5.000000e-01 1.274626e-01 3.844219e-01 2.704743e-01 2.568950e-02 1.220064e-01 5.000000e-01 9.875492e-02 5.442603e-01 9.954487e-02 0.000000e+00 2.818124e-01 4.045666e-01 5.408987e-02 2.244435e-01 5.000000e-01 6.085503e-02 5.366422e-01 2.609213e-01 0.000000e+00 4.292998e-01 4.038212e-01 7.655538e-03 3.248422e-01 5.000000e-01 2.617334e-02 5.283949e-01 3.910444e-01 0.000000e+00 4.238597e-01 5.000000e-01 5.957351e-03 5.212440e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_gaussian.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_gaussian.vtu index acd7ad179240..36b5ef0d6d0b 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_gaussian.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_gaussian.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -3.007196e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.065034e-01 2.461872e-02 -2.788266e-01 -3.689216e-01 1.477026e-02 -3.298575e-01 -2.442489e-01 1.116619e-01 -9.965241e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.489714e-01 1.421952e-01 -1.600906e-01 -2.630415e-01 1.498938e-01 -5.029431e-02 -3.658966e-01 1.499640e-02 -3.247315e-01 -1.807785e-01 4.150662e-01 1.036977e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 1.166647e-01 2.882023e-01 8.467524e-02 -2.516502e-01 1.692512e-01 6.828922e-03 -1.266132e-01 4.580222e-01 1.619512e-01 -3.583053e-01 1.769232e-02 -2.279133e-01 2.380321e-01 4.755744e-01 -5.000000e-01 2.668125e-01 1.566494e-01 -3.445339e-01 2.865280e-01 2.415987e-01 3.082706e-01 -5.000000e-01 0.000000e+00 2.803267e-01 -4.437674e-02 2.656870e-01 3.169091e-01 -2.064629e-01 1.133210e-01 1.261006e-01 2.368107e-01 3.728273e-01 -2.077050e-01 3.145934e-01 1.896257e-01 3.753464e-01 -3.488286e-01 1.742187e-02 -8.583488e-02 2.983067e-01 1.794044e-01 -5.000000e-01 3.916102e-01 1.205986e-01 -3.991628e-01 4.047192e-01 1.628128e-01 -2.484632e-01 4.056065e-01 1.377838e-01 3.023691e-02 3.167875e-01 1.609727e-01 4.056037e-01 -3.865631e-03 3.480217e-02 -1.449796e-01 4.056228e-01 1.213960e-01 3.547500e-01 1.669525e-01 7.360623e-02 1.396955e-01 2.960251e-01 1.419123e-01 5.054796e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 8.278275e-02 -4.000050e-01 5.000000e-01 1.129721e-01 -4.006627e-02 4.055402e-01 1.117794e-01 -2.994376e-01 5.000000e-01 1.028399e-01 5.163163e-01 -3.009242e-01 0.000000e+00 -1.978510e-01 5.000000e-01 9.015215e-02 6.645628e-02 4.052832e-01 1.001378e-01 2.581368e-01 3.060237e-01 5.668889e-02 -9.568121e-02 5.000000e-01 8.112439e-02 5.436701e-01 -1.012313e-01 0.000000e+00 1.700746e-01 4.049768e-01 6.912835e-02 7.405549e-03 5.000000e-01 7.448219e-02 3.901223e-01 2.754510e-01 1.539805e-02 1.109649e-01 5.000000e-01 6.066822e-02 5.339067e-01 1.044745e-01 0.000000e+00 2.696705e-01 4.047104e-01 3.218763e-02 2.124861e-01 5.000000e-01 3.583752e-02 5.186325e-01 2.620677e-01 0.000000e+00 4.134807e-01 4.038251e-01 3.069018e-03 3.109666e-01 5.000000e-01 1.302683e-02 5.094036e-01 3.909688e-01 0.000000e+00 4.082488e-01 5.000000e-01 2.035539e-03 5.052721e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_linear.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_linear.vtu index 2b861cbba03f..d43f7c0ba920 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_linear.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_linear.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -2.984309e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.090632e-01 5.436174e-02 -2.735886e-01 -3.696047e-01 2.910589e-02 -3.235740e-01 -2.208024e-01 1.524587e-01 -9.004908e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.234879e-01 2.117089e-01 -1.434763e-01 -2.131620e-01 1.735417e-01 -3.474472e-02 -3.665349e-01 3.364957e-02 -2.946188e-01 -7.011321e-02 2.808892e-01 1.189132e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 8.611614e-02 2.541727e-01 7.332653e-02 -2.034018e-01 1.608959e-01 -3.334529e-02 -3.762377e-02 2.831589e-01 1.743563e-01 -3.582901e-01 3.103324e-02 -2.032132e-01 1.405015e-01 2.886430e-01 -5.000000e-01 2.568230e-01 2.274291e-01 -3.408521e-01 2.664978e-01 2.487852e-01 3.224208e-01 -5.000000e-01 0.000000e+00 1.795062e-01 -2.522745e-02 2.007827e-01 2.804995e-01 -1.896018e-01 9.840379e-02 5.094643e-02 1.569336e-01 2.532075e-01 -1.998390e-01 3.036144e-01 2.402862e-01 3.772478e-01 -3.494974e-01 2.529894e-02 -7.853827e-02 2.850798e-01 2.369196e-01 -5.000000e-01 3.906297e-01 1.896381e-01 -3.984449e-01 4.034598e-01 1.961450e-01 -2.440077e-01 4.040684e-01 2.045413e-01 3.064587e-02 3.076936e-01 2.110629e-01 3.714932e-01 -1.752072e-02 5.460841e-02 -1.374321e-01 4.041132e-01 1.985617e-01 2.953276e-01 1.396039e-01 9.188527e-02 1.340248e-01 2.860416e-01 1.773893e-01 5.212856e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 1.529200e-01 -3.995081e-01 5.000000e-01 1.656706e-01 -2.887148e-02 4.041420e-01 1.876080e-01 -2.973288e-01 5.000000e-01 1.699102e-01 5.303911e-01 -3.027443e-01 0.000000e+00 -1.924497e-01 5.000000e-01 1.696402e-01 7.610231e-02 4.041857e-01 1.671537e-01 2.552363e-01 3.015882e-01 9.319230e-02 -8.691318e-02 5.000000e-01 1.617716e-01 5.406742e-01 -1.056860e-01 0.000000e+00 1.795923e-01 4.042944e-01 1.140288e-01 1.917062e-02 5.000000e-01 1.462019e-01 3.820607e-01 2.695205e-01 2.801299e-02 1.232378e-01 5.000000e-01 1.109758e-01 5.415876e-01 9.798155e-02 0.000000e+00 2.813950e-01 4.043421e-01 5.985903e-02 2.253657e-01 5.000000e-01 7.030418e-02 5.355878e-01 2.602398e-01 0.000000e+00 4.295031e-01 4.037088e-01 8.804585e-03 3.260202e-01 5.000000e-01 3.112911e-02 5.299791e-01 3.909227e-01 0.000000e+00 4.256232e-01 5.000000e-01 7.006080e-03 5.243080e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_quartic.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_quartic.vtu index 8da26cf239a8..1eef19b848f5 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_quartic.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_quartic.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -3.005306e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.084094e-01 2.904672e-02 -2.781905e-01 -3.702707e-01 1.833036e-02 -3.288798e-01 -2.421803e-01 1.241736e-01 -9.836984e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.429232e-01 1.650544e-01 -1.544300e-01 -2.507383e-01 1.620965e-01 -4.596288e-02 -3.675337e-01 2.014390e-02 -3.092238e-01 -1.458249e-01 3.865500e-01 1.075637e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 1.018206e-01 2.788063e-01 8.602138e-02 -2.347391e-01 1.686538e-01 -5.404185e-03 -9.085495e-02 4.052340e-01 1.690779e-01 -3.591343e-01 2.200021e-02 -2.150380e-01 1.934152e-01 4.413785e-01 -5.000000e-01 2.657863e-01 1.816259e-01 -3.437672e-01 2.829912e-01 2.618104e-01 3.122586e-01 -5.000000e-01 0.000000e+00 2.408036e-01 -3.830894e-02 2.496639e-01 3.070750e-01 -2.011873e-01 1.061233e-01 9.931205e-02 1.965532e-01 3.447156e-01 -2.058705e-01 3.138169e-01 2.185863e-01 3.765714e-01 -3.492675e-01 1.899713e-02 -7.959867e-02 2.976614e-01 2.183210e-01 -5.000000e-01 3.918160e-01 1.355591e-01 -3.990732e-01 4.047109e-01 1.676189e-01 -2.482452e-01 4.057764e-01 1.578931e-01 3.474571e-02 3.155027e-01 1.779249e-01 3.998883e-01 -1.102375e-02 4.102022e-02 -1.431426e-01 4.057045e-01 1.417348e-01 3.405905e-01 1.571028e-01 8.358277e-02 1.450037e-01 2.944865e-01 1.543616e-01 5.092707e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 9.948997e-02 -3.999737e-01 5.000000e-01 1.186840e-01 -3.492869e-02 4.056015e-01 1.284975e-01 -2.993998e-01 5.000000e-01 1.157468e-01 5.226269e-01 -3.017300e-01 0.000000e+00 -1.972658e-01 5.000000e-01 1.062603e-01 7.149767e-02 4.054296e-01 1.126431e-01 2.611577e-01 3.057186e-01 6.658259e-02 -9.307051e-02 5.000000e-01 9.522405e-02 5.432768e-01 -1.025692e-01 0.000000e+00 1.746756e-01 4.051303e-01 7.618045e-02 1.156304e-02 5.000000e-01 8.617040e-02 3.885158e-01 2.739824e-01 1.803284e-02 1.146618e-01 5.000000e-01 6.831860e-02 5.409475e-01 1.042419e-01 0.000000e+00 2.752519e-01 4.048810e-01 3.694911e-02 2.159970e-01 5.000000e-01 4.004667e-02 5.274488e-01 2.624167e-01 0.000000e+00 4.196299e-01 4.039275e-01 4.256082e-03 3.153229e-01 5.000000e-01 1.584339e-02 5.163838e-01 3.911172e-01 0.000000e+00 4.132905e-01 5.000000e-01 3.086396e-03 5.099653e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal.vtu index a86b2420840e..79fa9ef1662b 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -2.954690e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.076218e-01 6.730670e-02 -2.698146e-01 -3.684091e-01 3.682268e-02 -3.210687e-01 -2.152692e-01 1.696515e-01 -8.165576e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.201263e-01 2.427572e-01 -1.393353e-01 -2.057058e-01 1.764073e-01 -2.991886e-02 -3.652212e-01 4.020307e-02 -2.923024e-01 -6.213435e-02 2.469612e-01 1.230270e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 8.486384e-02 2.546585e-01 7.102194e-02 -1.981571e-01 1.665123e-01 -3.725551e-02 -3.157286e-02 2.356577e-01 1.753316e-01 -3.578146e-01 3.830592e-02 -1.995909e-01 1.408093e-01 2.447731e-01 -5.000000e-01 2.542415e-01 2.301170e-01 -3.392484e-01 2.635720e-01 2.484821e-01 3.289313e-01 -5.000000e-01 0.000000e+00 1.686987e-01 -2.344447e-02 1.899916e-01 2.752834e-01 -1.876647e-01 1.105251e-01 4.651544e-02 1.553755e-01 2.299026e-01 -1.946200e-01 3.014690e-01 2.421528e-01 3.789940e-01 -3.494305e-01 3.224430e-02 -7.595017e-02 2.822785e-01 2.385466e-01 -5.000000e-01 3.894072e-01 2.360903e-01 -3.974708e-01 4.025171e-01 2.427420e-01 -2.400169e-01 4.028732e-01 2.438698e-01 3.160794e-02 3.053247e-01 2.304882e-01 3.629834e-01 -1.880867e-02 6.147739e-02 -1.319979e-01 4.029774e-01 2.357441e-01 2.863519e-01 1.357811e-01 1.110552e-01 1.332429e-01 2.834209e-01 1.937152e-01 5.281389e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 2.152277e-01 -3.988510e-01 5.000000e-01 2.008792e-01 -2.211396e-02 4.033233e-01 2.138188e-01 -2.937882e-01 5.000000e-01 2.101694e-01 5.357141e-01 -3.036836e-01 0.000000e+00 -1.873007e-01 5.000000e-01 1.956806e-01 7.894423e-02 4.033102e-01 2.088962e-01 2.533139e-01 2.989023e-01 1.271129e-01 -8.245013e-02 5.000000e-01 1.928728e-01 5.387344e-01 -1.085301e-01 0.000000e+00 1.823984e-01 4.033293e-01 1.680583e-01 2.526017e-02 5.000000e-01 1.922700e-01 3.801274e-01 2.670541e-01 3.722506e-02 1.270189e-01 5.000000e-01 1.712776e-01 5.382499e-01 9.470425e-02 0.000000e+00 2.828839e-01 4.037465e-01 7.916664e-02 2.266649e-01 5.000000e-01 9.571167e-02 5.364034e-01 2.580094e-01 0.000000e+00 4.331546e-01 4.032447e-01 1.492143e-02 3.292619e-01 5.000000e-01 4.987022e-02 5.324171e-01 3.904917e-01 0.000000e+00 4.279950e-01 5.000000e-01 1.038714e-02 5.300883e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal_cloud_mesh.vtu b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal_cloud_mesh.vtu index 94d1c9e76e11..adf18909ec28 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal_cloud_mesh.vtu +++ b/applications/OptimizationApplication/tests/filtering/explicit_filter_reference_sigmoidal_cloud_mesh.vtu @@ -1,19 +1,20 @@ - + + - + - + -5.000000e-01 -5.000000e-01 0.000000e+00 -2.928662e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 -3.196572e-01 9.440912e-02 -2.654477e-01 -3.741035e-01 4.777782e-02 -3.187021e-01 -2.387544e-01 2.155435e-01 -7.001264e-02 -5.000000e-01 0.000000e+00 -5.000000e-01 -1.473493e-01 3.012083e-01 -1.296464e-01 -2.296432e-01 2.291548e-01 -1.636555e-02 -3.710580e-01 5.116060e-02 -2.876728e-01 -8.310409e-02 3.472872e-01 1.411522e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 7.337988e-02 3.385913e-01 9.405021e-02 -2.176542e-01 2.147340e-01 -1.387309e-02 -4.876027e-02 3.427513e-01 1.973531e-01 -3.627544e-01 4.899897e-02 -1.898728e-01 1.345806e-01 3.330873e-01 -5.000000e-01 2.515355e-01 3.270788e-01 -3.359347e-01 2.607184e-01 3.374378e-01 3.540190e-01 -5.000000e-01 0.000000e+00 2.022820e-01 -3.595737e-02 2.655856e-01 3.046035e-01 -2.011431e-01 1.455754e-01 7.198542e-02 1.511903e-01 3.110066e-01 -1.825121e-01 3.004650e-01 3.226735e-01 4.059908e-01 -3.538270e-01 4.439707e-02 -5.823105e-02 2.812785e-01 3.150987e-01 -5.000000e-01 3.891111e-01 3.267258e-01 -3.961261e-01 4.023486e-01 3.307730e-01 -2.304414e-01 4.025753e-01 3.261115e-01 5.498576e-02 3.046761e-01 3.023393e-01 3.991849e-01 -2.817136e-02 8.259695e-02 -1.161994e-01 4.027647e-01 3.141205e-01 3.188636e-01 1.334181e-01 1.420594e-01 1.592942e-01 2.824590e-01 2.610115e-01 5.535213e-01 -5.000000e-01 0.000000e+00 -5.000000e-01 5.000000e-01 3.224182e-01 -3.973126e-01 5.000000e-01 3.209079e-01 -2.104780e-03 4.030529e-01 2.957158e-01 -2.872629e-01 5.000000e-01 3.201875e-01 5.637316e-01 -3.082319e-01 0.000000e+00 -1.724717e-01 5.000000e-01 3.070889e-01 1.034430e-01 4.030980e-01 2.799994e-01 2.825953e-01 2.983075e-01 1.724221e-01 -6.128498e-02 5.000000e-01 2.988654e-01 5.721223e-01 -1.174447e-01 0.000000e+00 2.099742e-01 4.032024e-01 2.264272e-01 5.068848e-02 5.000000e-01 2.867736e-01 4.139670e-01 2.658418e-01 5.427942e-02 1.560699e-01 5.000000e-01 2.487219e-01 5.739391e-01 9.085196e-02 0.000000e+00 3.150009e-01 4.034570e-01 1.325200e-01 2.590307e-01 5.000000e-01 1.760165e-01 5.726293e-01 2.573698e-01 0.000000e+00 4.681638e-01 4.031980e-01 2.200160e-02 3.647395e-01 5.000000e-01 8.505322e-02 5.707811e-01 3.903147e-01 0.000000e+00 4.672538e-01 5.000000e-01 1.991320e-02 5.686700e-01 5.000000e-01 0.000000e+00 - + 56 55 52 47 45 40 37 35 26 53 50 49 42 39 30 55 53 52 45 42 36 26 34 25 50 47 44 39 37 27 40 45 36 40 36 28 49 50 44 49 44 41 52 53 49 52 49 46 44 47 40 44 40 32 26 35 34 30 39 27 30 27 22 36 42 30 36 30 24 27 37 26 27 26 17 56 52 54 28 36 24 28 24 21 46 49 41 46 41 31 22 27 17 22 17 15 17 26 16 41 44 32 41 32 31 32 40 28 32 28 21 24 30 22 24 22 15 52 46 51 51 54 52 25 16 26 21 24 15 15 17 11 46 31 48 48 51 46 16 11 17 43 48 29 11 6 9 29 48 31 29 31 19 19 31 21 29 19 20 20 19 12 29 20 43 12 19 13 20 12 14 13 19 21 13 21 15 12 13 7 14 12 8 20 14 23 9 6 4 7 13 9 8 12 7 23 14 18 23 18 33 11 9 15 15 9 13 14 8 10 14 10 18 20 23 43 4 6 2 9 4 7 7 4 3 3 4 2 7 3 8 8 3 5 8 5 10 5 3 1 0 3 2 0 1 3 33 38 23 23 38 43 31 32 21 - + 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 - + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 diff --git a/applications/OptimizationApplication/tests/filtering/explicit_filters_tests.py b/applications/OptimizationApplication/tests/filtering/explicit_filters_tests.py index c55459f45fb9..c6df1a350c7d 100644 --- a/applications/OptimizationApplication/tests/filtering/explicit_filters_tests.py +++ b/applications/OptimizationApplication/tests/filtering/explicit_filters_tests.py @@ -4,6 +4,7 @@ import KratosMultiphysics as Kratos import KratosMultiphysics.StructuralMechanicsApplication import KratosMultiphysics.OptimizationApplication as KratosOA +from KratosMultiphysics.kratos_utilities import DeleteDirectoryIfExisting, DeleteFileIfExisting from KratosMultiphysics.testing.utilities import ReadModelPart from KratosMultiphysics.compare_two_files_check_process import CompareTwoFilesCheckProcess from KratosMultiphysics.OptimizationApplication.filtering.filter import Factory as FilterFactory @@ -180,7 +181,7 @@ def setUpClass(cls) -> None: cls.filter_data = ComponentDataView("test", cls.optimization_problem) cls.filter_data.SetDataBuffer(1) - cls.vtu_output = Kratos.VtuOutput(cls.model_part, binary_output=Kratos.VtuOutput.ASCII, precision=6) + cls.vtu_output = Kratos.VtuOutput(cls.model_part, output_format=Kratos.VtuOutput.ASCII, precision=6) def setUp(self) -> None: Kratos.TensorAdaptors.NodePositionTensorAdaptor(self.initial_nodal_pos, Kratos.Configuration.Initial, copy=False).StoreData() @@ -281,11 +282,13 @@ def __RunTestCase(self, filter_function_type: str, damping_function_type: str, r "reference_file_name" : "explicit_filter_reference_1.vtu.orig", "output_file_name" : "explicit_filter_reference.vtu", "remove_output_file" : true, - "comparison_type" : "deterministic" + "comparison_type" : "vtu" }""") params["reference_file_name"].SetString(ref_file) - params["output_file_name"].SetString(f"output_{ref_file}") + params["output_file_name"].SetString(f"output_{ref_file[:-4]}/test_elements_0.vtu") CompareTwoFilesCheckProcess(params).Execute() + DeleteDirectoryIfExisting(f"output_{ref_file[:-4]}") + DeleteFileIfExisting(f"output_{ref_file[:-4]}.pvd") if __name__ == "__main__": diff --git a/applications/OptimizationApplication/tests/process_tests/test_optimization_problem_vtu_output_process.py b/applications/OptimizationApplication/tests/process_tests/test_optimization_problem_vtu_output_process.py index 93d960fa4dfa..4ab379052ffd 100644 --- a/applications/OptimizationApplication/tests/process_tests/test_optimization_problem_vtu_output_process.py +++ b/applications/OptimizationApplication/tests/process_tests/test_optimization_problem_vtu_output_process.py @@ -15,7 +15,6 @@ from KratosMultiphysics.compare_two_files_check_process import CompareTwoFilesCheckProcess -@kratos_unittest.skipUnless(hasattr(Kratos, "Future"), "Kratos is not compiled with KRATOS_FUTURE = ON.") class TestOptimizationProblemVtuOutputProcess(kratos_unittest.TestCase): class DummyResponseFunction(ResponseFunction): def __init__(self, response_name: str, model_part: Kratos.ModelPart) -> None: @@ -182,7 +181,7 @@ def test_OptimizationProblemVtuOutputProcess(self): "reference_file_name" : "test_1_orig.vtu", "output_file_name" : "Optimization_Results/test_1/test_1_elements_0.vtu", "remove_output_file" : true, - "comparison_type" : "deterministic" + "comparison_type" : "vtu" }""")).Execute() CompareTwoFilesCheckProcess(Kratos.Parameters(""" @@ -190,7 +189,7 @@ def test_OptimizationProblemVtuOutputProcess(self): "reference_file_name" : "test_2_orig.vtu", "output_file_name" : "Optimization_Results/test_2/test_2_elements_0.vtu", "remove_output_file" : true, - "comparison_type" : "deterministic" + "comparison_type" : "vtu" }""")).Execute() @classmethod diff --git a/kratos/future/input_output/vtu_output.cpp b/kratos/future/input_output/vtu_output.cpp deleted file mode 100644 index d39c067f719e..000000000000 --- a/kratos/future/input_output/vtu_output.cpp +++ /dev/null @@ -1,1743 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -// System includes -#include -#include -#include -#include - -// External includes - -// Project includes -#include "includes/data_communicator.h" -#include "input_output/base_64_encoded_output.h" -#include "input_output/vtk_definitions.h" -#include "tensor_adaptors/flags_tensor_adaptor.h" -#include "tensor_adaptors/historical_variable_tensor_adaptor.h" -#include "tensor_adaptors/node_position_tensor_adaptor.h" -#include "tensor_adaptors/variable_tensor_adaptor.h" -#include "utilities/container_io_utils.h" -#include "utilities/data_type_traits.h" -#include "utilities/parallel_utilities.h" -#include "utilities/reduction_utilities.h" -#include "utilities/string_utilities.h" -#include "future/utilities/xml_utilities/xml_appended_data_element_wrapper.h" -#include "future/utilities/xml_utilities/xml_elements_array.h" -#include "future/utilities/xml_utilities/xml_in_place_data_element_wrapper.h" -#include "future/utilities/xml_utilities/xml_utils.h" - -// Include base h -#include "vtu_output.h" - -namespace Kratos::Future { - -namespace { - -std::string GetEndianness() -{ - int i = 0x0001; - - if (*reinterpret_cast(&i) != 0) { - return "LittleEndian"; - } else { - return "BigEndian"; - } -} - -template -void CheckDataArrayName( - const std::string& rName, - const Globals::DataLocation& rLocation, - const VtuOutput::DataList& rList) -{ - KRATOS_TRY - - KRATOS_ERROR_IF(rList[static_cast(rLocation)].find(rName) != rList[static_cast(rLocation)].end()) - << "Found an existing data array with the same name = \"" << rName << "\".\n"; - - KRATOS_CATCH(""); -} - -void CheckDataArrayName( - const std::string& rName, - const Globals::DataLocation& rLocation, - const VtuOutput::UnstructuredGridData& rUnstructuredGridData) -{ - KRATOS_TRY - - bool found_existing_name = false; - switch (rLocation) { - case Globals::DataLocation::NodeHistorical: - case Globals::DataLocation::NodeNonHistorical: - // The following code block will be executed for Globals::DataLocation::NodeHistorical and Globals::DataLocation::NodeNonHistorical. - found_existing_name = rUnstructuredGridData.mMapOfPointTensorAdaptors.find(rName) != rUnstructuredGridData.mMapOfPointTensorAdaptors.end(); - break; - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: - // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. - found_existing_name = rUnstructuredGridData.mMapOfCellTensorAdaptors.find(rName) != rUnstructuredGridData.mMapOfCellTensorAdaptors.end(); - break; - default: - KRATOS_ERROR << "Unsupported data location type."; - } - - KRATOS_ERROR_IF(found_existing_name) - << "Found an existing data array with the same name = \"" << rName << "\".\n"; - - KRATOS_CATCH(""); -} - -void CheckDataArrayName( - const std::string& rName, - const Globals::DataLocation& rLocation, - const std::vector& rListOfUnstructuredGridData) -{ - KRATOS_TRY - - for (const auto& r_model_part_data : rListOfUnstructuredGridData) { - switch (rLocation) { - case Globals::DataLocation::NodeHistorical: - case Globals::DataLocation::NodeNonHistorical: - // The following code block will be executed for Globals::DataLocation::NodeHistorical and Globals::DataLocation::NodeNonHistorical. - if (r_model_part_data.UsePointsForDataFieldOutput) { - CheckDataArrayName(rName, rLocation, r_model_part_data); - } - break; - default: - CheckDataArrayName(rName, rLocation, r_model_part_data); - } - } - - KRATOS_CATCH(""); -} - -std::string GetEntityName(const std::optional& pCellContainer) -{ - if (pCellContainer.has_value()) { - return std::visit([](auto p_cell_container) { - using container_type = BareType; - return ModelPart::Container::GetEntityName(); - }, pCellContainer.value()); - } else { - return "node"; - } -} - -void CopyAttributes( - const XmlElement& rSource, - XmlElement& rDestination) -{ - for (const auto& [attribute, value] : rSource.GetAttributes()) { - rDestination.AddAttribute(attribute, value); - } -} - -template -NDDataPointerType GetWritingNDData( - const std::vector& rWritingIndices, - NDDataPointerType pNDData) -{ - KRATOS_TRY - - const auto& origin_shape = pNDData->Shape(); - - KRATOS_ERROR_IF(origin_shape.size() == 0) - << "NDData shape should have at least one dimension representing number of entities [ nd data = " - << *pNDData << " ].\n"; - - if (rWritingIndices.size() == origin_shape[0]) { - // number of writing indices are same as the first dimension of the NdData, hence - // there is nothing to be ignored from this data set. Returning the original - return pNDData; - } else { - // now there is a mismatch between number of writing indices and the number of entities represented by the pNDData. - // Hence we continue with copying data. - - // data type of the NDData, may be unsigned char, int, bool, double - using data_type = typename BareType::DataType; - - // compute number of components for each entity. - const auto number_of_components = std::accumulate(origin_shape.begin() + 1, origin_shape.end(), 1u, std::multiplies{}); - - // construct the new NDData holder having only the data from writing indices. - DenseVector destination_shape(origin_shape); - destination_shape[0] = rWritingIndices.size(); - auto p_destination_nd_data = Kratos::make_shared>(destination_shape); - - // get spans - const auto& origin_span = pNDData->ViewData(); - auto destination_span = p_destination_nd_data->ViewData(); - - // now copy the data - IndexPartition(rWritingIndices.size()).for_each([&origin_span, &destination_span, &rWritingIndices, number_of_components](const auto Index) { - auto orig_itr = origin_span.begin() + rWritingIndices[Index] * number_of_components; - auto dest_itr = destination_span.begin() + Index * number_of_components; - std::copy(orig_itr, orig_itr + number_of_components, dest_itr); - }); - - return p_destination_nd_data; - } - - KRATOS_CATCH(""); -} - -template -NDData::Pointer GetGeometryTypes( - std::vector& rWritingIndices, - const TContainerType& rContainer, - const IndexType EchoLevel) -{ - auto p_geometry_types = Kratos::make_shared>(DenseVector(1, rContainer.size())); - auto span = p_geometry_types->ViewData(); - - DenseVector ignored_indices(rContainer.size(), 0); - - IndexPartition(rContainer.size()).for_each([&span, &rContainer, &ignored_indices, EchoLevel](const IndexType Index) { - - const auto p_itr = VtkDefinitions::KratosVtkGeometryTypes.find((rContainer.begin() + Index)->GetGeometry().GetGeometryType()); - if (p_itr != VtkDefinitions::KratosVtkGeometryTypes.end()) { - *(span.begin() + Index) = static_cast(p_itr->second); - } else { - ignored_indices[Index] = 1; - KRATOS_WARNING_IF("VtuOutput", EchoLevel > 1) - << "Skipping unsupported geometry type in " - << ModelPart::Container::GetEntityName() - << " with id " << (rContainer.begin() + Index)->Id() << ".\n"; - } - }); - - // fill in the writing indices - rWritingIndices.reserve(rContainer.size()); - for (IndexType i = 0; i < rContainer.size(); ++i) { - if (ignored_indices[i] != 1) { - rWritingIndices.push_back(i); - } - } - - return p_geometry_types; -} - -template -NDData::Pointer GetOffsets( - const std::vector& rWritingIndices, - const TContainerType& rContainer) -{ - auto p_offsets = Kratos::make_shared>(DenseVector(1, rWritingIndices.size())); - auto data_itr = p_offsets->ViewData().begin(); - - int total_offset = 0; - for (IndexType i = 0; i < rWritingIndices.size(); ++i) { - total_offset += (rContainer.begin() + rWritingIndices[i])->GetGeometry().size(); - data_itr[i] = total_offset; - } - - return p_offsets; -} - -template -NDData::Pointer GetConnectivities( - const NDData& rOffsets, - const TContainerType& rContainer, - const std::unordered_map& rKratosVtuIndicesMap, - const std::vector& rWritingIndices) -{ - if (rOffsets.Size() == 0) { - return Kratos::make_shared>(DenseVector(1, 0)); - } - - const auto offsets_span = rOffsets.ViewData(); - auto p_connectivities = Kratos::make_shared>(DenseVector(1, offsets_span.back())); - auto connectivities_span = p_connectivities->ViewData(); - - IndexPartition(rWritingIndices.size()).for_each([&connectivities_span, &offsets_span, &rContainer, &rKratosVtuIndicesMap, &rWritingIndices](const IndexType Index) { - const auto& r_geometry = (rContainer.begin() + rWritingIndices[Index])->GetGeometry(); - auto entity_data_begin_itr = connectivities_span.begin() + offsets_span[Index] - r_geometry.size(); - - for (IndexType i_node = 0; i_node < r_geometry.size(); ++i_node) { - const auto p_itr = rKratosVtuIndicesMap.find(r_geometry[i_node].Id()); - if (p_itr != rKratosVtuIndicesMap.end()) { - entity_data_begin_itr[i_node] = p_itr->second; - } else { - KRATOS_ERROR << "Node with id " << r_geometry[i_node].Id() << " not found in nodes list."; - } - } - }); - - return p_connectivities; -} - -template -void AddConnectivityData( - XmlElementsArray& rCellElement, - std::vector& rWritingIndices, - const ModelPart::NodesContainerType& rNodes, - VtuOutput::CellContainerPointerType pCells, - TXmlDataElementWrapper& rXmlDataElementWrapper, - const IndexType EchoLevel) -{ - std::visit([&rCellElement, &rXmlDataElementWrapper, &rWritingIndices, &rNodes, EchoLevel](auto p_container) { - std::unordered_map indices_map; - indices_map.reserve(rNodes.size()); - IndexType vtu_index = 0; - for (const auto& r_node : rNodes) { - indices_map[r_node.Id()] = vtu_index++; - } - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting Vtk geometry type info...\n"; - auto p_type_data = GetGeometryTypes(rWritingIndices, *p_container, EchoLevel); - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Ignored " << (p_container->size() - rWritingIndices.size()) << "/" - << p_container->size() << " " << GetEntityName(p_container) << "(s).\n"; - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting geometry offsets info...\n"; - auto p_offsets = GetOffsets(rWritingIndices, *p_container); - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting geometry connectivity info...\n"; - rCellElement.AddElement(rXmlDataElementWrapper.Get("connectivity", GetConnectivities(*p_offsets, *p_container, indices_map, rWritingIndices))); - rCellElement.AddElement(rXmlDataElementWrapper.Get("offsets", p_offsets)); - rCellElement.AddElement(rXmlDataElementWrapper.Get("types", GetWritingNDData(rWritingIndices, p_type_data))); - }, pCells); -} - -template -void AddFieldsUsingTensorAdaptorImpl( - XmlElementsArray& rXmlElement, - TContainerPointerType pContainer, - const Variable& rVariable, - TXmlDataElementWrapper& rXmlDataElementWrapper, - const DataCommunicator& rDataCommunicator, - const std::vector& rWritingIndices, - const IndexType EchoLevel, - TArgs&&... rArgs) -{ - KRATOS_TRY - - - using primitive_data_type = typename DataTypeTraits::PrimitiveType; - - if constexpr(std::is_same_v) { - // we only support int variable, and there are no TensorAdaptors to - // collect data from integer variables, we do it manually here. - auto p_nd_data = Kratos::make_shared>(DenseVector(1, pContainer->size())); - const auto& shape = p_nd_data->Shape(); - if constexpr (std::is_same_v) { - ContainerIOUtils::CopyToContiguousArray( - *pContainer, p_nd_data->ViewData(), - shape.data().begin(), shape.data().begin() + 1, - [&rVariable](int& rValue, const Node& rNode) { - rValue = rNode.FastGetSolutionStepValue(rVariable); - }); - } else if constexpr(std::is_same_v) { - ContainerIOUtils::CopyToContiguousArray( - *pContainer, p_nd_data->ViewData(), - shape.data().begin(), shape.data().begin() + 1, - [&rVariable](int& rValue, const auto& rNode) { - rValue = rNode.GetValue(rVariable); - }); - } else { - KRATOS_ERROR << "Unsupported tensor adaptor type."; - } - - // since we only support Variable, which is having a static data shape - // we don't have to do mpi communication to decide the shape on the - // empty ranks. - rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, p_nd_data))); - } else if constexpr(std::is_same_v) { - using data_type_traits = DataTypeTraits; - - if constexpr(data_type_traits::IsDynamic) { - // this is a dynamic type such as Vector or Matrix, so - // we need to do communication to decide the correct size - // because, there may be ranks with zero entities, hence these ranks will not have - // correctly sized dynamic Matrix or Vectors. Vtu needs all the ranks to have the same number - // of components, hence communication is a must in here. - - // construct the correct data_shape - std::vector data_shape(data_type_traits::Dimension, 0); - - if (!pContainer->empty()) { - // if the container is not empty. - TTensorAdaptorType tensor_adaptor(pContainer, &rVariable, rArgs...); - tensor_adaptor.CollectData(); - - const auto& ta_shape = tensor_adaptor.Shape(); - std::copy(ta_shape.begin() + 1, ta_shape.end(), data_shape.begin()); - - // create the xml element in ranks which do have entities. - rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); - } - - // communicate to identify the correct data shape to be written down to ranks which - // do not have any entities. - const auto& max_data_shape = rDataCommunicator.MaxAll(data_shape); - - if (pContainer->empty()) { - // if the container is empty, now create an empty NDData with correct data shape. - DenseVector nd_shape(max_data_shape.size() + 1); - std::copy(max_data_shape.begin(), max_data_shape.end(), nd_shape.begin() + 1); - nd_shape[0] = pContainer->size(); - auto p_nd_data = Kratos::make_shared(nd_shape); - - // create the xml element in ranks which do not have any entities. - rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), p_nd_data)); - } - } else { - // this is a static type such as double, array_1d, ... - // So no need of mpi communication - TTensorAdaptorType tensor_adaptor(pContainer, &rVariable, rArgs...); - tensor_adaptor.CollectData(); - rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); - } - } else { - KRATOS_ERROR << "Unsupported variable type."; - } - - KRATOS_CATCH(""); -} - -template -void AddFieldsUsingTensorAdaptor( - XmlElementsArray& rXmlElement, - TContainerPointerType pContainer, - const TMapType& rMap, - TXmlDataElementWrapper& rXmlDataElementWrapper, - const DataCommunicator& rDataCommunicator, - const std::vector& rWritingIndices, - const IndexType EchoLevel, - TArgs&&... rArgs) -{ - KRATOS_TRY - - for (const auto& r_pair : rMap) { - using data_type = BareType; - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting " << r_pair.first << " data...\n"; - - if constexpr(std::is_same_v) { - if (r_pair.first == "KRATOS_ID") { - // this is specific to write KRATOS_IDS. - auto p_nd_data = Kratos::make_shared>(DenseVector(1, rWritingIndices.size())); - auto span = p_nd_data->ViewData(); - IndexPartition(rWritingIndices.size()).for_each([&pContainer, &span, &rWritingIndices](const auto Index) { - span[Index] = (pContainer->begin() + rWritingIndices[Index])->Id(); - }); - rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, p_nd_data)); - } else { - // the map is of type flags - // here we don't need to do any communication because Flags are always having a static data shape. - TTensorAdaptorType tensor_adaptor(pContainer, *r_pair.second, rArgs...); - tensor_adaptor.CollectData(); - rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); - } - } else { - std::visit([&](const auto p_variable) { - AddFieldsUsingTensorAdaptorImpl( - rXmlElement, pContainer, *p_variable, rXmlDataElementWrapper, - rDataCommunicator, rWritingIndices, EchoLevel, rArgs...); - }, r_pair.second); - } - } - - KRATOS_CATCH(""); -} - -template -void AddFields( - XmlElementsArray& rXmlElement, - const std::map& rMap, - TXmlDataElementWrapper& rXmlDataElementWrapper, - const std::vector& rWritingIndices, - const DataCommunicator& rDataCommunicator, - const IndexType EchoLevel) -{ - for (const auto& r_pair : rMap) { - KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting " << r_pair.first << " data...\n"; - - std::visit([&rXmlElement, &r_pair, &rXmlDataElementWrapper, &rWritingIndices, &rDataCommunicator](auto pTensorAdaptor) { - // here we need to make sure all the tensor adaptors from every rank has the same data shape, even - // from the ranks which do not have any entities. Therefore following check is done with mpi communication - - // all the ranks should have the same number of dimensions, because number of dimensions should not depend - // on whether the rank is empty or not. - const auto& ta_shape = pTensorAdaptor->Shape(); - const auto max_number_of_dimensions = rDataCommunicator.MaxAll(static_cast(ta_shape.size())); - - KRATOS_ERROR_IF_NOT(max_number_of_dimensions == ta_shape.size()) - << "The number of dimensions represented by \"" << r_pair.first << "\" tensor adaptor is different in different ranks [ max number of dimensions from all ranks = " - << max_number_of_dimensions << ", tensor adaptor = " << *pTensorAdaptor << " ].\n"; - - // since all ranks have same number of dimensions, now we can check if the tensor adaptors have the correct sizes. - // in here we check the followings - // - each rank which does not have emtpy containers (ta_shape[0] != 0) should have same number of components in the data shape. - // - ranks which do have empty containers (ta_shape[0] == 0) should have either same number of components as in the ranks which have non empty - // containers or 0. - - std::vector communicated_shape(ta_shape.begin(), ta_shape.end()); - auto all_ta_shapes = rDataCommunicator.AllGatherv(communicated_shape); - - // find a data shape from some rank which has non-empty container - DenseVector ref_ta_shape(max_number_of_dimensions, 0); - for (const auto& rank_shape : all_ta_shapes) { - if (rank_shape[0] != 0) { - std::copy(rank_shape.begin() + 1, rank_shape.end(), ref_ta_shape.begin() + 1); - break; - } - } - - for (IndexType i_rank = 0; i_rank < all_ta_shapes.size(); ++i_rank) { - auto& rank_shape = all_ta_shapes[i_rank]; - - // modify the rank shape if it is coming from a rank having an empty container. - if (rank_shape[0] == 0) { - // this is a rank with an empty container. - for (IndexType i_dim = 1; i_dim < ref_ta_shape.size(); ++i_dim) { - // modify only if the number of components in the higher dimensions are zero. - if (rank_shape[i_dim] == 0) { - rank_shape[i_dim] = ref_ta_shape[i_dim]; - } - } - } - - // now we check in all ranks whether the data shape is equal - for (IndexType i_dim = 1; i_dim < ref_ta_shape.size(); ++i_dim) { - KRATOS_ERROR_IF_NOT(rank_shape[i_dim] == ref_ta_shape[i_dim]) - << "All ranks should have same number of components in the shape dimensions except for the first dimension. If the rank is empty," - << " then that rank should have zeros for all shape dimensions or correct number of components in the dimensions as in the ranks with" - << " non-empty containers [ mismatching shape rank = " << i_rank << ", mismatching tensor adaptor shape = " << rank_shape - << ", ref tensor adaptor shape from other ranks = " << ref_ta_shape << ", tensor adaptor name = " << r_pair.first - << ", tensor adaptor = " << *pTensorAdaptor << " ].\n"; - } - } - - if (ta_shape[0] == 0) { - // get the storage type of the tensor adaptor. This may be NDData, NDData, ... - using TDataType = typename BareType::Storage; - // this is a rank with an empty container. - rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, Kratos::make_shared(ref_ta_shape))); - } else { - // this is a rank with non-empty container. - rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, GetWritingNDData(rWritingIndices, pTensorAdaptor->pGetStorage()))); - } - - }, r_pair.second); - } -} - -template -ModelPart::NodesContainerType::Pointer GetNodesContainer(TEntityContainerType& rContainer) -{ - std::vector temp_nodes; - temp_nodes.reserve(rContainer.size() * 20); - for (auto& r_entity : rContainer) { - auto& r_geometry = r_entity.GetGeometry(); - for (auto p_itr = r_geometry.ptr_begin(); p_itr != r_geometry.ptr_end(); ++p_itr) { - temp_nodes.push_back(*p_itr); - } - } - - auto p_nodes_container = Kratos::make_shared(); - p_nodes_container->insert(temp_nodes.begin(), temp_nodes.end()); - return p_nodes_container; -} - -void AddUnstructuredGridData( - std::vector& rOutput, - ModelPart& rModelPart, - const IndexType EchoLevel, - const bool UseSubModelParts) -{ - const std::vector entity_availability{rModelPart.NumberOfNodes() > 0, rModelPart.NumberOfConditions() > 0, rModelPart.NumberOfElements() > 0}; - const auto& max_entity_availability = rModelPart.GetRootModelPart().GetCommunicator().GetDataCommunicator().MaxAll(entity_availability); - const bool has_nodes = max_entity_availability[0]; - const bool has_conditions = max_entity_availability[1]; - const bool has_elements = max_entity_availability[2]; - - if (has_elements) { - // Model part has elements. Hence add a separate output - // for elements. - - // now check if it has proper nodes - if (has_nodes) { - KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) - << "Configuring output for \"" << rModelPart.FullName() << "\" elements with existing nodes container.\n"; - VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), rModelPart.pElements()}; - rOutput.push_back(model_part_data); - } else { - // create the nodes container. - KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) - << "Configuring output for \"" << rModelPart.FullName() << "\" elements with new nodes container.\n"; - auto p_nodes = GetNodesContainer(rModelPart.Elements()); - VtuOutput::UnstructuredGridData model_part_data{false, &rModelPart, p_nodes, rModelPart.pElements()}; - rOutput.push_back(model_part_data); - } - } - - if (has_conditions) { - // Model part has conditions. Hence add a separate output - // for conditions. - - if (!has_elements && has_nodes) { - KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) - << "Configuring output for \"" << rModelPart.FullName() << "\" conditions with existing nodes container.\n"; - VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), rModelPart.pConditions()}; - rOutput.push_back(model_part_data); - } else { - // either this model part also contains elements, or it does not - // contain nodes. In either case, the nodes list given by the rModelPart - // does not reflect the actual nodes used by the conditions. - // In order to avoid writing nodes, which are not used by the conditions, - // this will use a new nodes list. - - KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) - << "Configuring output for \"" << rModelPart.FullName() << "\" conditions with new nodes container.\n"; - - auto p_nodes = GetNodesContainer(rModelPart.Conditions()); - VtuOutput::UnstructuredGridData model_part_data{false, &rModelPart, p_nodes, rModelPart.pConditions()}; - rOutput.push_back(model_part_data); - } - } - - if (!has_elements && !has_conditions) { - KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) - << "Configuring output for \"" << rModelPart.FullName() << "\" nodes.\n"; - // Model part does not have either conditions or elements. - // Hence, only adding the nodes. - VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), std::nullopt}; - rOutput.push_back(model_part_data); - } - - if (UseSubModelParts) { - // now recursively add all the sub model part data. - for (auto& r_sub_model_part : rModelPart.SubModelParts()) { - AddUnstructuredGridData(rOutput, r_sub_model_part, EchoLevel, UseSubModelParts); - } - } -} - -template -const typename VtuOutput::DataList::value_type& GetContainerMap( - const VtuOutput::DataList& rList, - TCellPointerType pCellPointer) -{ - return std::visit([&rList](auto pContainer) -> const typename VtuOutput::DataList::value_type& { - using container_type = BareType; - if constexpr(std::is_same_v) { - return rList[static_cast(Globals::DataLocation::Condition)]; - } else if constexpr(std::is_same_v) { - return rList[static_cast(Globals::DataLocation::Element)]; - } else { - KRATOS_ERROR << "Unsupported container type."; - return rList[static_cast(Globals::DataLocation::Element)]; - } - }, pCellPointer); -} - -std::string WritePartitionedUnstructuredGridData( - XmlElementsArray& rPointDataElement, - XmlElementsArray& rCellDataElement, - const std::string& rOutputVtuFileName, - const DataCommunicator& rDataCommunicator) -{ - const int writing_rank = 0; - - // remove the rank from the rOutputVtuFileName. - const auto& r_base_name = rOutputVtuFileName.substr(0, rOutputVtuFileName.rfind("_")); - - const auto& p_vtu_file_name = r_base_name + ".pvtu"; - - if (rDataCommunicator.Rank() == writing_rank) { - // create the pvtu file - XmlElementsArray p_vtu_file_element("VTKFile"); - p_vtu_file_element.AddAttribute("type", "PUnstructuredGrid"); - p_vtu_file_element.AddAttribute("version", "0.1"); - p_vtu_file_element.AddAttribute("byte_order", GetEndianness()); - - // create the unstructured grid - auto p_unstructured_grid_element = Kratos::make_shared("PUnstructuredGrid"); - p_unstructured_grid_element->AddAttribute("GhostLevel", "0"); - p_vtu_file_element.AddElement(p_unstructured_grid_element); - - // ppoints_element - auto p_points_element = Kratos::make_shared("PPoints"); - p_unstructured_grid_element->AddElement(p_points_element); - - // position element - auto p_position_element = Kratos::make_shared("PDataArray"); - p_position_element->AddAttribute("type", "Float64"); - p_position_element->AddAttribute("Name", "Position"); - p_position_element->AddAttribute("NumberOfComponents", "3"); - p_points_element->AddElement(p_position_element); - - // pcells element - auto p_cells_element = Kratos::make_shared("PCells"); - p_unstructured_grid_element->AddElement(p_cells_element); - - // connectivity element - auto p_connectivity_element = Kratos::make_shared("PDataArray"); - p_connectivity_element->AddAttribute("type", "Int32"); - p_connectivity_element->AddAttribute("Name", "connectivity"); - p_connectivity_element->AddAttribute("NumberOfComponents", "1"); - p_cells_element->AddElement(p_connectivity_element); - - // offsets element - auto p_offsets_element = Kratos::make_shared("PDataArray"); - p_offsets_element->AddAttribute("type", "Int32"); - p_offsets_element->AddAttribute("Name", "offsets"); - p_offsets_element->AddAttribute("NumberOfComponents", "1"); - p_cells_element->AddElement(p_offsets_element); - - // types element - auto p_types_element = Kratos::make_shared("PDataArray"); - p_types_element->AddAttribute("type", "UInt8"); - p_types_element->AddAttribute("Name", "types"); - p_types_element->AddAttribute("NumberOfComponents", "1"); - p_cells_element->AddElement(p_types_element); - - // ppoint data element - auto p_point_data_element = Kratos::make_shared("PPointData"); - p_unstructured_grid_element->AddElement(p_point_data_element); - - // now add the point data fields - for (const auto& p_element : rPointDataElement.GetElements()) { - auto p_current_element = Kratos::make_shared("PDataArray"); - CopyAttributes(*p_element, *p_current_element); - p_point_data_element->AddElement(p_current_element); - } - - // pcell data element - auto p_cell_data_element = Kratos::make_shared("PCellData"); - p_unstructured_grid_element->AddElement(p_cell_data_element); - - // now add the cell data fields - for (const auto& p_element : rCellDataElement.GetElements()) { - auto p_current_element = Kratos::make_shared("PDataArray"); - CopyAttributes(*p_element, *p_current_element); - p_cell_data_element->AddElement(p_current_element); - } - - // now add the piece elements - for (int i_rank = 0; i_rank < rDataCommunicator.Size(); ++i_rank) { - const auto& r_file_name = r_base_name + "_" + std::to_string(i_rank) + ".vtu"; - auto piece = Kratos::make_shared("Piece"); - // since we are writing to the same folder the pvtu files - piece->AddAttribute( - "Source", std::filesystem::relative( - std::filesystem::absolute(r_file_name), - std::filesystem::absolute(p_vtu_file_name).parent_path()) - .generic_string()); - p_unstructured_grid_element->AddElement(piece); - } - - // writing to file - std::ofstream output_file; - output_file.open(p_vtu_file_name, std::ios::out | std::ios::trunc); - output_file << "\n"; - p_vtu_file_element.Write(output_file); - - } - - return p_vtu_file_name; -} - -template -void PrintDataLocationData( - std::ostream& rOStream, - const std::string& rMapType, - const VtuOutput::DataList& rList) -{ - rOStream << "List of " << rMapType << "s:"; - for (IndexType i = 0; i < rList.size(); ++i) { - switch (i) { - case static_cast(Globals::DataLocation::NodeHistorical): - rOStream << "\n\tNode historical " << rMapType << "s:"; - break; - case static_cast(Globals::DataLocation::NodeNonHistorical): - rOStream << "\n\tNode " << rMapType << "s:"; - break; - case static_cast(Globals::DataLocation::Condition): - rOStream << "\n\tCondition " << rMapType << "s:"; - break; - case static_cast(Globals::DataLocation::Element): - rOStream << "\n\tElement " << rMapType << "s:"; - break; - default: - break; - } - - for ([[maybe_unused]]const auto& [name, variable] : rList[i]) { - rOStream << "\n\t\t" << name; - } - } -} - -template -std::pair::iterator> FindUnstructuredGridData( - const TContainerType& rContainer, - std::vector& rUnstructuredGridDataList) -{ - for (auto itr = rUnstructuredGridDataList.begin(); itr != rUnstructuredGridDataList.end(); ++itr) { - auto p_model_part = itr->mpModelPart; - if constexpr(std::is_same_v) { - if (itr->UsePointsForDataFieldOutput) { - if ( - &rContainer == &p_model_part->Nodes() || - (!p_model_part->IsDistributed() && &rContainer == &p_model_part->GetCommunicator().LocalMesh().Nodes()) - ) { - return std::make_pair(Globals::DataLocation::NodeNonHistorical, itr); - } - } - } else if constexpr(std::is_same_v) { - // since Kratos is doing partitioning based on elements, and there are no conditions - // on the ghost meshes. so normal mesh and the local mesh should be having identical entities. - if (itr->mpCells.has_value() && - std::holds_alternative(itr->mpCells.value()) && - ( - &rContainer == &*std::get(itr->mpCells.value()) || - &rContainer == &p_model_part->GetCommunicator().LocalMesh().Conditions() - ) - ) { - return std::make_pair(Globals::DataLocation::Condition, itr); - } - } else if constexpr(std::is_same_v) { - // since Kratos is doing partitioning based on elements, and there are no elements - // on the ghost meshes. so normal mesh and the local mesh should be having identical entities. - if (itr->mpCells.has_value() && - std::holds_alternative(itr->mpCells.value()) && - ( - &rContainer == &*std::get(itr->mpCells.value()) || - &rContainer == &p_model_part->GetCommunicator().LocalMesh().Elements() - ) - ) { - return std::make_pair(Globals::DataLocation::Element, itr); - } - } else { - KRATOS_ERROR << "Unsupported container type."; - } - } - - return std::make_pair(Globals::DataLocation::ModelPart, rUnstructuredGridDataList.end()); -} - -} // namespace - -VtuOutput::VtuOutput( - ModelPart& rModelPart, - const Globals::Configuration Configuration, - const WriterFormat OutputFormat, - const IndexType Precision, - const bool OutputSubModelParts, - const bool WriteIds, - const IndexType EchoLevel) - : mIsPVDFileHeaderWritten(false), - mrModelPart(rModelPart), - mConfiguration(Configuration), - mEchoLevel(EchoLevel), - mOutputFormat(OutputFormat), - mPrecision(Precision) -{ - AddUnstructuredGridData(mUnstructuredGridDataList, rModelPart, mEchoLevel, OutputSubModelParts); - - // sort the order of output to be consistent between different compilers - std::sort(mUnstructuredGridDataList.begin(), mUnstructuredGridDataList.end(), - [](const auto& rV1, const auto& rV2) { - return rV1.mpModelPart->FullName() < rV2.mpModelPart->FullName(); - }); - - if (WriteIds) { - // Adds a dummy place holder called "KRATOS_ID" to every container type - // so the user is prohibited from adding any tensor adaptors - // with the name KRATOS_ID in future. This will be treated - // separately, hence the use of nullptr. - mFlags[static_cast(Globals::DataLocation::NodeNonHistorical)]["KRATOS_ID"] = nullptr; - mFlags[static_cast(Globals::DataLocation::Condition)]["KRATOS_ID"] = nullptr; - mFlags[static_cast(Globals::DataLocation::Element)]["KRATOS_ID"] = nullptr; - } -} - -const ModelPart& VtuOutput::GetModelPart() const -{ - return mrModelPart; -} - -std::vector VtuOutput::GetOutputContainerList() const -{ - std::vector result; - for (const auto& r_unstructured_grid : mUnstructuredGridDataList) { - if (r_unstructured_grid.UsePointsForDataFieldOutput) { - result.push_back(r_unstructured_grid.mpPoints); - - if (!r_unstructured_grid.mpModelPart->GetRootModelPart().IsDistributed()) { - // since local mesh and the mesh are the same in the case of non-distributed - // run. - result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pNodes()); - } - } - - if (r_unstructured_grid.mpCells.has_value()) { - std::visit([&result, &r_unstructured_grid](auto p_cells) { - result.push_back(p_cells); - - // since local mesh and the mesh are the same. - using container_type = BareType; - if constexpr(std::is_same_v) { - result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pConditions()); - } else if constexpr(std::is_same_v) { - result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pElements()); - } - }, r_unstructured_grid.mpCells.value()); - } - } - return result; -} - -void VtuOutput::AddFlag( - const std::string& rFlagName, - const Flags& rFlagVariable, - const Globals::DataLocation& DataLocation) -{ - KRATOS_TRY - - KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) - << "Flags can be added only before the first call to the PrintOutput [ flag name = " - << rFlagName << " ].\n"; - - switch (DataLocation) { - case Globals::DataLocation::NodeNonHistorical: - // user is trying to add a flag to nodes. now we are checking - // whether there are variables with the same name in the variables - // from the nodal historical. - // note: there is no break here. - CheckDataArrayName(rFlagName, Globals::DataLocation::NodeHistorical, mFlags); - CheckDataArrayName(rFlagName, Globals::DataLocation::NodeHistorical, mVariables); - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: - // The following code block will be executed for Globals::DataLocation::NodeHistorical, Globals::DataLocation::Condition, and Globals::DataLocation::Element. - - // user is trying to add a flag variable to nodes, conditions or elements. - // here we check if the given flag name is there in the existing flags for user specified data location, - // and also in the variables. - CheckDataArrayName(rFlagName, DataLocation, mFlags); - CheckDataArrayName(rFlagName, DataLocation, mVariables); - - // since specified flags are used to output in every unstructured grid. We check here whether - // any of the tensor adaptors in the given data location contains the same name as rFlagName. - CheckDataArrayName(rFlagName, DataLocation, mUnstructuredGridDataList); - - // If there are no conflicts, we add the flag variable. - mFlags[static_cast(DataLocation)][rFlagName] = &rFlagVariable; - break; - default: - KRATOS_ERROR << "Flags can be only added to NodeNonHistorical, Condition, and Element data locations."; - break; - } - - KRATOS_CATCH(""); -} - -template -void VtuOutput::AddVariable( - const Variable& rVariable, - const Globals::DataLocation& DataLocation) -{ - KRATOS_TRY - - KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) - << "Variables can be added only before the first call to the PrintOutput [ variable name = " - << rVariable.Name() << " ].\n"; - - switch (DataLocation) { - case Globals::DataLocation::NodeHistorical: - // Now the user is adding a nodal historical variable. So, this checks whether - // the a variable with the same name exists in the nodal non-historical variables map. - // note: there is no break in here. - CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeNonHistorical, mFlags); - CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeNonHistorical, mVariables); - case Globals::DataLocation::NodeNonHistorical: - // Now the user is adding a nodal non-historical variable. So this checks whether - // a variable with the same name exists in the nodal historical variables map. - // not: there is no break in here. - CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeHistorical, mFlags); - CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeHistorical, mVariables); - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: - // The following code block will be executed for Globals::DataLocation::NodeHistorical, Globals::DataLocation::NodeNonHistorical, Globals::DataLocation::Condition, and Globals::DataLocation::Element. - - // Now the user is trying to add a nodal-historical, nodal-non-historical, element or condition variable. - // so now we check whether another variable with the same name exists - // in the user specified container in flags and variables maps. - CheckDataArrayName(rVariable.Name(), DataLocation, mFlags); - CheckDataArrayName(rVariable.Name(), DataLocation, mVariables); - - // this checks whether there is already a tensor adaptor added with a name equal to the variable name - // in any of the unstructured grids. Since these variables will be used to output data in all the unstructured grids, - // non-of them should have any tensor adaptors with this name. - CheckDataArrayName(rVariable.Name(), DataLocation, mUnstructuredGridDataList); // checks in the tensor adaptors list - - // if there are no conflicts, adding the variable. - mVariables[static_cast(DataLocation)][rVariable.Name()] = &rVariable; - break; - default: - KRATOS_ERROR << "Variables can be only added to NodeHistorical, NodeNonHistorical, Condition, and Element data locations."; - break; - } - - KRATOS_CATCH(""); -} - -template -void VtuOutput::AddIntegrationPointVariable( - const Variable& rVariable, - const Globals::DataLocation& DataLocation) -{ - KRATOS_TRY - - KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) - << "Integration point variables can be added only before the first call to the PrintOutput [ integration point variable name = " - << rVariable.Name() << " ].\n"; - - switch (DataLocation) { - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: - // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. - - // checks if the integration point variable name already exists on the - // list of integration point variables. - CheckDataArrayName(rVariable.Name(), DataLocation, mIntegrationPointVariables); - - // If no conflicts in the naming is found, then put integration point variable for the output. - mIntegrationPointVariables[static_cast(DataLocation)][rVariable.Name()] = &rVariable; - break; - default: - KRATOS_ERROR << "Integration point variables can be only added to Condition, and Element data locations."; - break; - } - - KRATOS_CATCH(""); -} - -template -void VtuOutput::AddTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor) -{ - KRATOS_TRY - - KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) - << "TensorAdaptors can be added only before the first call to the PrintOutput [ tensor adaptor name = " - << rTensorAdaptorName << " ].\n"; - - // a visitor for NodesContainer::Pointer, ConditionsContainer::Pointer, ElementsContainerPointer - // of the given pTensorAdaptor - std::visit([this, &rTensorAdaptorName, &pTensorAdaptor](auto pContainer){ - // finds the unstructured grid for which the given tensor adaptor's pContainer refers to. - // mesh_type is of Kratos::Globals::DataLocation enum - // itr points to the unstructured grid which is referring to the given pContainer. - // if not found, mesh_type is returned with Kratos::Globals::DataLocation::ModelPart - // enum value, which will throw an error. - [[maybe_unused]] auto [mesh_type, itr] = FindUnstructuredGridData(*pContainer, this->mUnstructuredGridDataList); - - switch (mesh_type) { - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: { - // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. - - // here we have to check if the specified tensor adaptor name is there in the found unstructured grid - // referred by the itr. - - // checks in the condition or element maps of flags and variables whether the rTensorAdaptorName already - // exists. - CheckDataArrayName(rTensorAdaptorName, mesh_type, mFlags); // checks in the current data location of mFlags map - CheckDataArrayName(rTensorAdaptorName, mesh_type, mVariables); // checks in the current data location of mVariables map - - // checks in either Condition or Element map of tensor adaptors whether the given rTensorAdaptorName - // exists - CheckDataArrayName(rTensorAdaptorName, mesh_type, *itr); - - // If no conflicts in the naming is found, then put the tensor adaptor for output. - itr->mMapOfCellTensorAdaptors[rTensorAdaptorName] = pTensorAdaptor; - break; - } - case Globals::DataLocation::NodeNonHistorical: { - // checks if the given rTensorAdaptorName is already there in the nodal non-historical - // variables list, nodal-non-historical variables list and flags list. - CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, mFlags); - CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, mVariables); - CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeHistorical, mFlags); - CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeHistorical, mVariables); - - // checks if the given rTensorAdaptorName is already there in the list of nodal tensor adaptors - // of the unstructured grid referred by itr. - CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, *itr); - - // If no conflicts in the naming is found, then put the tensor adaptor for output. - itr->mMapOfPointTensorAdaptors[rTensorAdaptorName] = pTensorAdaptor; - break; - } - default: - KRATOS_ERROR - << "The container in the TensorAdaptor is not referring to any of the containers " - << "written by this Vtu output [ tensor adaptor name = " << rTensorAdaptorName - << ", tensor_adaptor = " << *pTensorAdaptor << " ]\n" - << *this; - break; - } - }, pTensorAdaptor->GetContainer()); - - KRATOS_CATCH(""); -} - -template -void VtuOutput::ReplaceTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor) -{ - KRATOS_TRY - - // a visitor for NodesContainer::Pointer, ConditionsContainer::Pointer, ElementsContainerPointer - // of the given pTensorAdaptor - std::visit([this, &rTensorAdaptorName, &pTensorAdaptor](auto pContainer){ - // finds the unstructured grid for which the given tensor adaptor's pContainer refers to. - // mesh_type is of Kratos::Globals::DataLocation enum - // itr points to the unstructured grid which is referring to the given pContainer. - // if not found, mesh_type is returned with Kratos::Globals::DataLocation::ModelPart - // enum value, which will throw an error. - [[maybe_unused]] auto [mesh_type, itr] = FindUnstructuredGridData(*pContainer, this->mUnstructuredGridDataList); - - switch (mesh_type) { - case Globals::DataLocation::Condition: - case Globals::DataLocation::Element: { - // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. - auto data_field_itr = itr->mMapOfCellTensorAdaptors.find(rTensorAdaptorName); - - KRATOS_ERROR_IF(data_field_itr == itr->mMapOfCellTensorAdaptors.end()) - << "TensorAdaptor name = \"" - << rTensorAdaptorName << "\" not found in the existing data fields. It is only allowed to update existing data fields. VtuOutput: \n" - << *this; - - data_field_itr->second = pTensorAdaptor; - break; - } - case Globals::DataLocation::NodeNonHistorical: { - auto data_field_itr = itr->mMapOfPointTensorAdaptors.find(rTensorAdaptorName); - - KRATOS_ERROR_IF(data_field_itr == itr->mMapOfPointTensorAdaptors.end()) - << "TensorAdaptor name = \"" - << rTensorAdaptorName << "\" not found in the existing data fields. It is only allowed to update existing data fields. VtuOutput: \n" - << *this; - - data_field_itr->second = pTensorAdaptor; - break; - } - default: - KRATOS_ERROR - << "The container in the TensorAdaptor is not referring to any of the containers " - << "written by this Vtu output [ tensor adaptor name = " << rTensorAdaptorName - << ", tensor_adaptor = " << *pTensorAdaptor << " ]\n" - << *this; - break; - } - }, pTensorAdaptor->GetContainer()); - - KRATOS_CATCH(""); -} - -template -void VtuOutput::EmplaceTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor) -{ - if (!mIsPVDFileHeaderWritten) { - AddTensorAdaptor(rTensorAdaptorName, pTensorAdaptor); - } else { - ReplaceTensorAdaptor(rTensorAdaptorName, pTensorAdaptor); - } -} - -template -std::pair VtuOutput::WriteUnstructuredGridData( - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputFileNamePrefix, - const IndexType Step) const -{ - const auto& r_data_communicator = mrModelPart.GetCommunicator().GetDataCommunicator(); - auto p_nodes = rUnstructuredGridData.mpPoints; - - // create the vtk file - XmlElementsArray vtk_file_element("VTKFile"); - vtk_file_element.AddAttribute("type", "UnstructuredGrid"); - vtk_file_element.AddAttribute("version", "0.1"); - vtk_file_element.AddAttribute("byte_order", GetEndianness()); - - // create the unstructured grid - auto unstructured_grid_element = Kratos::make_shared("UnstructuredGrid"); - vtk_file_element.AddElement(unstructured_grid_element); - - auto p_xml_data_element_wrapper = rElementDataWrapperCreateFunctor(); - rElementDataWrapperAppendFunctor(vtk_file_element, p_xml_data_element_wrapper); - - // create the piece element - auto piece_element = Kratos::make_shared("Piece"); - // adding number of points - piece_element->AddAttribute("NumberOfPoints", std::to_string(p_nodes->size())); - unstructured_grid_element->AddElement(piece_element); - - // create the position element - KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting nodal " << (mConfiguration == Globals::Configuration::Initial ? "initial" : "current") << " position data...\n"; - NodePositionTensorAdaptor node_position_tensor_adaptor(p_nodes, mConfiguration); - node_position_tensor_adaptor.CollectData(); - - // create the points element - auto points_element = Kratos::make_shared("Points"); - points_element->AddElement(p_xml_data_element_wrapper->Get("Position", node_position_tensor_adaptor.pGetStorage())); - piece_element->AddElement(points_element); - - // create the cells element - auto cells_element = Kratos::make_shared("Cells"); - std::vector writing_indices; - if (rUnstructuredGridData.mpCells.has_value()) { - KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting " << GetEntityName(rUnstructuredGridData.mpCells) << " connectivity data...\n"; - AddConnectivityData(*cells_element, writing_indices, *rUnstructuredGridData.mpPoints, rUnstructuredGridData.mpCells.value(), *p_xml_data_element_wrapper, mEchoLevel); - } - piece_element->AddAttribute("NumberOfCells", std::to_string(writing_indices.size())); - piece_element->AddElement(cells_element); - - // create the point data - auto point_data_element = Kratos::make_shared("PointData"); - piece_element->AddElement(point_data_element); - - if (rUnstructuredGridData.UsePointsForDataFieldOutput) { - KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting nodal data fields...\n"; - // generate and add point field data - std::vector all_indices(p_nodes->size()); - std::iota(all_indices.begin(), all_indices.end(), 0); - AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mFlags[static_cast(Globals::DataLocation::NodeNonHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel); - AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mVariables[static_cast(Globals::DataLocation::NodeNonHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel); - AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mVariables[static_cast(Globals::DataLocation::NodeHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel, 0); - AddFields(*point_data_element, rUnstructuredGridData.mMapOfPointTensorAdaptors, *p_xml_data_element_wrapper, all_indices, r_data_communicator, mEchoLevel); - } - - // create cell data - auto cell_data_element = Kratos::make_shared("CellData"); - piece_element->AddElement(cell_data_element); - - // generate and add cell field data - if (rUnstructuredGridData.mpCells.has_value()) { - KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting " << GetEntityName(rUnstructuredGridData.mpCells) << " data fields...\n"; - std::visit([this, &rUnstructuredGridData, &cell_data_element, &p_xml_data_element_wrapper, &r_data_communicator, &writing_indices](auto p_container){ - AddFieldsUsingTensorAdaptor(*cell_data_element, p_container, GetContainerMap(this->mVariables, rUnstructuredGridData.mpCells.value()), *p_xml_data_element_wrapper, r_data_communicator, writing_indices, mEchoLevel); - AddFieldsUsingTensorAdaptor(*cell_data_element, p_container, GetContainerMap(this->mFlags, rUnstructuredGridData.mpCells.value()), *p_xml_data_element_wrapper, r_data_communicator, writing_indices, mEchoLevel); - }, rUnstructuredGridData.mpCells.value()); - AddFields(*cell_data_element, rUnstructuredGridData.mMapOfCellTensorAdaptors, *p_xml_data_element_wrapper, writing_indices, r_data_communicator, mEchoLevel); - } - - std::stringstream output_vtu_file_name; - output_vtu_file_name << rOutputFileNamePrefix << "/" << rUnstructuredGridData.mpModelPart->FullName(); - - // identify suffix with the entity type. - const std::string& suffix = "_" + GetEntityName(rUnstructuredGridData.mpCells) + "s"; - - const std::string pvd_data_set_name = rUnstructuredGridData.mpModelPart->FullName() + suffix; - - // append with the step value and rank and extension - output_vtu_file_name << suffix << "_" << Step - << (r_data_communicator.IsDistributed() - ? "_" + std::to_string(r_data_communicator.Rank()) - : "") - << ".vtu"; - - // write the vtu file. - std::ofstream output_file; - output_file.open(output_vtu_file_name.str(), std::ios::out | std::ios::trunc | std::ios::binary); - output_file << "\n"; - vtk_file_element.Write(output_file); - output_file.close(); - - // if it is run on a distributed system, create the pvtu file. - if (r_data_communicator.IsDistributed()) { - return std::make_pair(pvd_data_set_name, - WritePartitionedUnstructuredGridData( - *point_data_element, *cell_data_element, - output_vtu_file_name.str(), r_data_communicator)); - } - - // return the final file name for - return std::make_pair(pvd_data_set_name, output_vtu_file_name.str()); -} - -template -std::pair VtuOutput::WriteIntegrationPointData( - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputFileNamePrefix, - const IndexType Step) const -{ - if (!rUnstructuredGridData.mpCells.has_value()) { - // nothing to do here. - return std::make_pair("", ""); - } - - const auto& integration_point_vars = GetContainerMap( - mIntegrationPointVariables, rUnstructuredGridData.mpCells.value()); - - if (integration_point_vars.empty()) { - // nothing to do here. - return std::make_pair("", ""); - } - - // create the vtk file - XmlElementsArray vtk_file_element("VTKFile"); - vtk_file_element.AddAttribute("type", "UnstructuredGrid"); - vtk_file_element.AddAttribute("version", "0.1"); - vtk_file_element.AddAttribute("byte_order", GetEndianness()); - - // create the unstructured grid - auto unstructured_grid_element = Kratos::make_shared("UnstructuredGrid"); - vtk_file_element.AddElement(unstructured_grid_element); - - auto p_xml_data_element_wrapper = rElementDataWrapperCreateFunctor(); - rElementDataWrapperAppendFunctor(vtk_file_element, p_xml_data_element_wrapper); - - DenseVector offsets; - - const auto total_gauss_points = std::visit([&offsets](auto p_container) { - // resize the offsets - offsets.resize(p_container->size(), false); - - IndexType total_number_of_gauss_points = 0; - - // now compute the offsets for each entity. This allows - // having different number of gps in different entities. - // which is the case if we have a model part with mixed type - // of elements. - for (IndexType i = 0; i < p_container->size(); ++i) { - const auto& r_entity = *(p_container->begin() + i); - const auto number_of_gps = r_entity.GetGeometry().IntegrationPointsNumber(r_entity.GetIntegrationMethod()); - total_number_of_gauss_points += number_of_gps; - offsets[i] = total_number_of_gauss_points - number_of_gps; - } - - return total_number_of_gauss_points; - }, rUnstructuredGridData.mpCells.value()); - - // create the piece element - auto piece_element = Kratos::make_shared("Piece"); - piece_element->AddAttribute("NumberOfPoints", std::to_string(total_gauss_points)); - piece_element->AddAttribute("NumberOfCells", "0"); - unstructured_grid_element->AddElement(piece_element); - - // construct the gauss point position data - DenseVector gauss_point_nd_data_shape(2); - gauss_point_nd_data_shape[0] = total_gauss_points; - gauss_point_nd_data_shape[1] = 3; - auto gauss_point_positions = Kratos::make_shared>(gauss_point_nd_data_shape); - const auto span = gauss_point_positions->ViewData(); - - std::visit([&span, &offsets](auto p_container){ - IndexPartition(p_container->size()).for_each(array_1d{}, [&span, &p_container, &offsets](const auto Index, auto& rTLS) { - const auto& r_entity = *(p_container->begin() + Index); - const auto number_of_gauss_points = r_entity.GetGeometry().IntegrationPointsNumber(r_entity.GetIntegrationMethod()); - for (IndexType i = 0; i < number_of_gauss_points; ++i) { - r_entity.GetGeometry().GlobalCoordinates(rTLS, i); - std::copy(rTLS.begin(), rTLS.end(), span.begin() + offsets[Index] * 3 + i * 3); - } - - }); - }, rUnstructuredGridData.mpCells.value()); - - // create the gauss points element - auto points_element = Kratos::make_shared("Points"); - points_element->AddElement(p_xml_data_element_wrapper->Get("Position", gauss_point_positions)); - piece_element->AddElement(points_element); - - auto cells_element = Kratos::make_shared("Cells"); - piece_element->AddElement(cells_element); - - // create the point data - auto point_data_element = Kratos::make_shared("PointData"); - piece_element->AddElement(point_data_element); - - const auto& r_data_communicator = mrModelPart.GetCommunicator().GetDataCommunicator(); - - // add the gauss point data - bool is_gauss_point_data_available = false; - for (const auto& r_pair : integration_point_vars) { - std::visit([&offsets, &point_data_element, &p_xml_data_element_wrapper, &rUnstructuredGridData, &is_gauss_point_data_available, &r_data_communicator, total_gauss_points](auto pVariable, auto pContainer) { - // type information of the variable - using data_type = typename BareType::Type; - using data_type_traits = DataTypeTraits; - using primitive_data_type = typename data_type_traits::PrimitiveType; - - if constexpr(std::is_same_v) { - // here we cannot use GaussPointVariableTensorAdaptor because - // it does not allow recording gauss point information if different - // entities have different number of gauss points. - // hence we do the computation here manually. - - std::vector output; - - // first we need to find out the shape of the gauss point data - std::vector local_shape(data_type_traits::Dimension, 0u); - if (!pContainer->empty()) { - pContainer->front().CalculateOnIntegrationPoints( - *pVariable, output, rUnstructuredGridData.mpModelPart->GetProcessInfo()); - - if (!output.empty()) { - // if there are available gauss point information - data_type_traits::Shape(output.front(), local_shape.data(), - local_shape.data() + local_shape.size()); - } - } - - // now do the communication between ranks to get the correct size - const auto& max_local_shape = r_data_communicator.MaxAll(local_shape); - - // now we construct the nd_data_shape - DenseVector nd_data_shape(local_shape.size() + 1); - std::copy(max_local_shape.begin(), max_local_shape.end(), nd_data_shape.begin() + 1); - nd_data_shape[0] = total_gauss_points; - - const auto total_number_of_components = std::accumulate(max_local_shape.begin(), max_local_shape.end(), 1u, std::multiplies{}); - - auto p_gauss_data = Kratos::make_shared>(nd_data_shape); - auto span = p_gauss_data->ViewData(); - - if (r_data_communicator.SumAll(static_cast(span.size())) > 0) { - is_gauss_point_data_available = true; - IndexPartition(pContainer->size()).for_each(std::vector{}, [&span, &pContainer, &pVariable, &rUnstructuredGridData, &offsets, total_number_of_components](const auto Index, auto& rTLS) { - auto& r_entity = *(pContainer->begin() + Index); - r_entity.CalculateOnIntegrationPoints(*pVariable, rTLS, rUnstructuredGridData.mpModelPart->GetProcessInfo()); - DataTypeTraits>::CopyToContiguousData(span.begin() + offsets[Index] * total_number_of_components, rTLS); - }); - point_data_element->AddElement(p_xml_data_element_wrapper->Get(pVariable->Name(), p_gauss_data)); - } - } - }, r_pair.second, rUnstructuredGridData.mpCells.value()); - } - - if (is_gauss_point_data_available) { - std::stringstream output_vtu_file_name; - output_vtu_file_name - << rOutputFileNamePrefix << "/" << rUnstructuredGridData.mpModelPart->FullName() << "_" - << GetEntityName(rUnstructuredGridData.mpCells) - << "_gauss_" << Step - << (r_data_communicator.IsDistributed() - ? "_" + std::to_string(r_data_communicator.Rank()) - : "") - << ".vtu"; - - std::ofstream output_file; - output_file.open(output_vtu_file_name.str(), std::ios::out | std::ios::trunc); - output_file << "\n"; - vtk_file_element.Write(output_file); - output_file.close(); - - if (r_data_communicator.IsDistributed()) { - return std::make_pair( - rUnstructuredGridData.mpModelPart->FullName() + "_" + GetEntityName(rUnstructuredGridData.mpCells) + "_gauss", - WritePartitionedUnstructuredGridData( - *point_data_element, *Kratos::make_shared(""), - output_vtu_file_name.str(), r_data_communicator)); - } - - return std::make_pair(rUnstructuredGridData.mpModelPart->FullName() + "_" + GetEntityName(rUnstructuredGridData.mpCells) + "_gauss", - output_vtu_file_name.str()); - } - else { - return std::make_pair("", ""); - } -} - -template -void VtuOutput::WriteData( - std::vector>& rPVDFileNameInfo, - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputPrefix, - const IndexType Step) const -{ - KRATOS_TRY - - rPVDFileNameInfo.push_back(WriteUnstructuredGridData( - rElementDataWrapperCreateFunctor, rElementDataWrapperAppendFunctor, - rUnstructuredGridData, rOutputPrefix, Step)); - - rPVDFileNameInfo.push_back(WriteIntegrationPointData( - rElementDataWrapperCreateFunctor, rElementDataWrapperAppendFunctor, - rUnstructuredGridData, rOutputPrefix, Step)); - - KRATOS_CATCH(""); -} - -void VtuOutput::PrintOutput(const std::string& rOutputFileNamePrefix) -{ - KRATOS_TRY - - const auto& r_process_info = mrModelPart.GetProcessInfo(); - - // here we do not check whether the r_process_info has the time variable specified - // because, in a const DataValueContainer, if the variable is not there, it returns the - // zero value of the variable. - const double time = r_process_info[TIME]; - - const IndexType step = r_process_info[STEP]; - - std::filesystem::create_directories(rOutputFileNamePrefix); - - std::vector> pvd_file_name_info; - - for (auto& r_unstructured_grid_data : mUnstructuredGridDataList) { - switch (mOutputFormat) { - case ASCII: - { - WriteData( - pvd_file_name_info, - [this](){ return Kratos::make_shared(XmlInPlaceDataElementWrapper::ASCII, this->mPrecision); }, - [](auto& rVtkFileElement, auto pXmlDataElementWrapper) {}, - r_unstructured_grid_data, - rOutputFileNamePrefix, - step); - break; - } - case BINARY: - { - WriteData( - pvd_file_name_info, - [this](){ return Kratos::make_shared(XmlInPlaceDataElementWrapper::BINARY, this->mPrecision); }, - [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddAttribute("header_type", "UInt64"); }, - r_unstructured_grid_data, - rOutputFileNamePrefix, - step); - break; - } - case RAW: - { - WriteData( - pvd_file_name_info, - [](){ return Kratos::make_shared(XmlAppendedDataElementWrapper::RAW); }, - [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddElement(pXmlDataElementWrapper); rVtkFileElement.AddAttribute("header_type", "UInt64"); }, - r_unstructured_grid_data, - rOutputFileNamePrefix, - step); - break; - } - case COMPRESSED_RAW: - { - WriteData( - pvd_file_name_info, - [](){ return Kratos::make_shared(XmlAppendedDataElementWrapper::COMPRESSED_RAW); }, - [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddElement(pXmlDataElementWrapper); rVtkFileElement.AddAttribute("header_type", "UInt64"); rVtkFileElement.AddAttribute("compressor", "vtkZLibDataCompressor"); }, - r_unstructured_grid_data, - rOutputFileNamePrefix, - step); - break; - } - } - } - - // now generate the *.pvd file - if (mrModelPart.GetCommunicator().MyPID() == 0) { - KRATOS_INFO_IF("VtuOutput", mEchoLevel > 1) - << "Writing \"" << mrModelPart.FullName() - << "\" PVD file...\n"; - // Single pvd file links all the vtu files from sum-model parts - // partitioned model_parts and time step vtu files together. - - if (!mIsPVDFileHeaderWritten) { - mIsPVDFileHeaderWritten = true; - - // creates the pvd file element - XmlElementsArray pvd_file_element("VTKFile"); - pvd_file_element.AddAttribute("type", "Collection"); - pvd_file_element.AddAttribute("version", "1.0"); - pvd_file_element.AddAttribute("byte_order", GetEndianness()); - - // creates the collection element - auto collection_element = Kratos::make_shared("Collection"); - pvd_file_element.AddElement(collection_element); - - // now iterate through all the time steps and correctly write - // the file names for each time step. - IndexType local_index = 0; - for (IndexType i = 0; i < pvd_file_name_info.size(); ++i) { - if (pvd_file_name_info[i].second != "") { - auto current_element = Kratos::make_shared("DataSet"); - - // write the time with the specified precision. - std::stringstream str_time; - str_time << std::scientific << std::setprecision(mPrecision) << time; - - current_element->AddAttribute("timestep", str_time.str()); - current_element->AddAttribute("name", pvd_file_name_info[i].first); - current_element->AddAttribute("part", std::to_string(local_index++)); - current_element->AddAttribute( - "file", std::filesystem::relative( - std::filesystem::absolute(pvd_file_name_info[i].second), - std::filesystem::absolute(rOutputFileNamePrefix).parent_path()) - .generic_string()); - collection_element->AddElement(current_element); - } - } - - std::ofstream output_file; - output_file.open(rOutputFileNamePrefix + ".pvd", std::ios::out | std::ios::trunc); - output_file << "\n"; - pvd_file_element.Write(output_file); - output_file.close(); - } else { - std::ofstream output_file; - output_file.open(rOutputFileNamePrefix + ".pvd", std::ios::in | std::ios::out); - output_file.seekp(-28, std::ios::end); - - // now iterate through all the time steps and correctly write - // the file names for each time step. - IndexType local_index = 0; - for (IndexType i = 0; i < pvd_file_name_info.size(); ++i) { - if (pvd_file_name_info[i].second != "") { - auto current_element = Kratos::make_shared("DataSet"); - - // write the time with the specified precision. - std::stringstream str_time; - str_time << std::scientific << std::setprecision(mPrecision) << time; - - current_element->AddAttribute("timestep", str_time.str()); - current_element->AddAttribute("name", pvd_file_name_info[i].first); - current_element->AddAttribute("part", std::to_string(local_index++)); - current_element->AddAttribute( - "file", std::filesystem::relative( - std::filesystem::absolute(pvd_file_name_info[i].second), - std::filesystem::absolute(rOutputFileNamePrefix).parent_path()) - .generic_string()); - - current_element->Write(output_file, 2); - } - } - - output_file << " \n\n"; - output_file.close(); - } - - } - - KRATOS_CATCH(""); -} - -std::string VtuOutput::Info() const -{ - std::stringstream info; - info << "VtuOutput: " << mrModelPart.FullName() << " [ writer = "; - switch (mOutputFormat) { - case ASCII: - info << "ASCII"; - break; - case BINARY: - info << "BINARY"; - break; - case RAW: - info << "RAW"; - break; - case COMPRESSED_RAW: - info << "COMPRESSED_RAW"; - break; - } - - info << ", precision = " << mPrecision << ", configuration = "; - - switch (mConfiguration){ - case Globals::Configuration::Initial: - info << "initial"; - break; - case Globals::Configuration::Current: - info << "current"; - break; - } - - info << ", echo level = " << mEchoLevel << " ]"; - - return info.str(); -} - -void VtuOutput::PrintInfo(std::ostream& rOStream) const -{ - rOStream << this->Info(); -} - -void VtuOutput::PrintData(std::ostream& rOStream) const -{ - PrintDataLocationData(rOStream, "flag", mFlags); - rOStream << "\n"; - PrintDataLocationData(rOStream, "variable", mVariables); - rOStream << "\n"; - PrintDataLocationData(rOStream, "integration variable", mIntegrationPointVariables); - rOStream << "\n"; - - rOStream << "List of model part info:"; - for (const auto& r_model_part_data : mUnstructuredGridDataList) { - rOStream << "\n\tModel part: \"" << r_model_part_data.mpModelPart->FullName() << "\"" - << " with " << GetEntityName(r_model_part_data.mpCells) << "s" - << ", used for point fields = " << (r_model_part_data.UsePointsForDataFieldOutput ? "yes" : "no"); - - if (r_model_part_data.UsePointsForDataFieldOutput) { - rOStream << "\n\t\t" << "Point fields:"; - for (const auto& r_pair : r_model_part_data.mMapOfPointTensorAdaptors) { - std::visit([&rOStream, &r_pair](auto pNDData){ - rOStream << "\n\t\t\t" << r_pair.first << ": " << *pNDData; - }, r_pair.second); - } - } - - rOStream << "\n\t\t" << "Cell fields:"; - for (const auto& r_pair : r_model_part_data.mMapOfCellTensorAdaptors) { - std::visit([&rOStream, &r_pair](auto pNDData){ - rOStream << "\n\t\t\t" << r_pair.first << ": " << *pNDData; - }, r_pair.second); - } - } -} - -// template instantiations -#ifndef KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION -#define KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(...) \ - template KRATOS_API(KRATOS_CORE) void VtuOutput::AddVariable<__VA_ARGS__>(const Variable<__VA_ARGS__>&, const Globals::DataLocation&); \ - template KRATOS_API(KRATOS_CORE) void VtuOutput::AddIntegrationPointVariable<__VA_ARGS__>(const Variable<__VA_ARGS__>&, const Globals::DataLocation&); \ - -#endif - -#ifndef KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION -#define KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(DATA_TYPE) \ - template KRATOS_API(KRATOS_CORE) void VtuOutput::AddTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ - template KRATOS_API(KRATOS_CORE) void VtuOutput::ReplaceTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ - template KRATOS_API(KRATOS_CORE) void VtuOutput::EmplaceTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ - -#endif - -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(int) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(double) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(Vector) -KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(Matrix) - -KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(bool) -KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(int) -KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(double) - -#undef KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION -#undef KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION - -} // namespace Kratos diff --git a/kratos/future/input_output/vtu_output.h b/kratos/future/input_output/vtu_output.h deleted file mode 100644 index 0dfbd6aa2dab..000000000000 --- a/kratos/future/input_output/vtu_output.h +++ /dev/null @@ -1,383 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -#pragma once - -// System includes -#include -#include -#include - -// External includes - -// Project includes -#include "containers/flags.h" -#include "containers/nd_data.h" -#include "containers/variable.h" -#include "includes/define.h" -#include "includes/global_variables.h" -#include "includes/io.h" -#include "includes/model_part.h" -#include "tensor_adaptors/tensor_adaptor.h" -#include "future/utilities/xml_utilities/xml_data_element_wrapper.h" - -namespace Kratos::Future { - -/** - * @class VtuOutput - * @brief Handles VTU (Visualization Toolkit Unstructured grid) output for Kratos ModelParts. - * @author Suneth Warnakulasuriya - * @ingroup KratosCore - * - * This class provides functionality to export simulation data from a Kratos ModelPart to VTU files, - * supporting both ASCII, BINARY, RAW and COMPRESSED_RAW with zlib compression. It allows users to register @ref Variable , @ref Flags , - * and @ref TensorAdaptor for output, and supports writing data on nodes, elements, conditions, and integration points. - * The output can be configured to include submodel parts and supports parallel execution (MPI). - * - * @section vtu_output_usage Usage - * This output put process can be used at any point in the simulation (static or dynamic). But, upon construction of an object of - * @ref VtuOutput, all the variables, flags, integration point variables and tensor adaptors should be added - * using @ref AddFlag, @ref AddVariable, @ref AddIntegrationPointVariable or @ref AddTensorAdaptor . Once the - * @ref PrintOutput is called, no more data fields can be added because Vtk library does not support varying fields. - * - * But, already added @ref TensorAdaptor objects may be replaced with new @ref TensorAdaptor objects after calling @ref PrintOutput - * by using @ref ReplaceTensorAdaptor method. - * - * A convenience method called @ref EmplaceTensorAdaptor is there to add the @ref TensorAdaptor if it is not existing and if the call is - * before the first call of @ref PrintOutput. Otherwise, it will try replacing an existing @ref TensorAdaptor. - * - */ -class KRATOS_API(KRATOS_CORE) VtuOutput : public IO -{ -public: - ///@name Type definitions - ///@{ - - // Index type definition - using IndexType = std::size_t; - - // Variant defining supported container (i.e. @ref PointerVectorSet ) type pointers. - using SupportedContainerPointerType = std::variant< - ModelPart::NodesContainerType::Pointer, - ModelPart::ConditionsContainerType::Pointer, - ModelPart::ElementsContainerType::Pointer - >; - - // Variant defining supported cell type @ref PointerVectorSte which can be visualized with cell data with vtk library. - using CellContainerPointerType = std::variant< - ModelPart::ConditionsContainerType::Pointer, - ModelPart::ElementsContainerType::Pointer - >; - - // Variant defining all the @ref Variable types which are supported to be visualized at point or cell data with vtk library. - using SupportedVariablePointerType = std::variant< - Variable const *, - Variable const *, - Variable> const *, - Variable> const *, - Variable> const *, - Variable> const *, - Variable const *, - Variable const * - >; - - // Variant definining all the supported @ref TensorAdaptor which can be used to pass data fields to point or cell data using the vtk library. - using SupportedTensorAdaptorPointerType = std::variant< - TensorAdaptor::Pointer, - TensorAdaptor::Pointer, - TensorAdaptor::Pointer - >; - - - // A list of maps of name and a @p T for different locations ( @ref Globals::DataLocation ) which are used for output at later time. - template - using DataList = std::array, static_cast(Kratos::Globals::DataLocation::NumberOfDataLocations)>; - - KRATOS_CLASS_POINTER_DEFINITION(VtuOutput); - - ///@} - ///@name Public enums - ///@{ - - /// Enumerations for the output writer format. - enum WriterFormat - { - ASCII, ///< ASCII format. - BINARY, ///< Binary format. - RAW, ///< Raw format. All data is appended to one stream. - COMPRESSED_RAW ///< Data is first compressed with zlib and the appended to one stream. - }; - - struct UnstructuredGridData - { - bool UsePointsForDataFieldOutput; // If true, then the mpPoints represents a container in the model part, otherwise, mpPoints refers to a container which is on the fly generated. - ModelPart * mpModelPart; // Model part associated with the unstructured grid data. - ModelPart::NodesContainerType::Pointer mpPoints; // Points to be used in the unstructured grid. - std::optional mpCells; // Cells to be used in the unstructured grid. - std::map mMapOfPointTensorAdaptors; // Point data tensor adaptors. - std::map mMapOfCellTensorAdaptors; // Cell data tensor adaptors. - }; - - ///@} - ///@name Life cycle - ///@{ - - /** - * @brief Construct a new Vtu Output - * - * @param rModelPart Model part to be used in the vtu output. - * @param Configuration Which nodal positions to be written out. - * @param OutputFormat The format of the output. - * @param Precision Precision of the double values to be used when writing the doubles as ASCII. - * @param OutputSubModelParts To consider all the submodel parts recursively for output. - * @param WriteIds To write ids under the name "KRATOS_ID" to be visualized. - * @param EchoLevel Echo level for to print information. - */ - VtuOutput( - ModelPart& rModelPart, - const Globals::Configuration Configuration, - const WriterFormat OutputFormat = WriterFormat::COMPRESSED_RAW, - const IndexType Precision = 9, - const bool OutputSubModelParts = false, - const bool WriteIds = false, - const IndexType EchoLevel = 0); - - ///@} - ///@name Public operations - ///@{ - - /** - * @brief Adds a flag to the VTU output. - * - * This method registers a flag @p rFlagVariable to be included in the VTU output file. - * The flag will be associated with the specified data location (e.g., node, element, condition, refer @ref Globals::DataLocation ) - * given by @p DataLocation . This allows the Flag's values to be written to the output file - * when @ref PrintOutput is called with the name @p rFlagName. - * - * @throws std::runtime_error if @ref AddFlag is called after @ref PrintOutput. - * @throws std::runtime_error if tries to add the same @p rFlagName more than ones. - * @throws std::runtime_error if there already exist a field name same as @p rFlagName in one of the compatible data locations with @p DataLocation . - * @throws std::runtime_error if @p DataLocation is not NodeNonHistorical, Condition, or Element. - * - * @param rFlagName The name of the flag to be added. - * @param rFlagVariable The flag variable to be added. - * @param DataLocation The location where the flag data is stored (e.g., NodeNonHistorical, Condition, Element). - * - * @see @ref FlagsTensorAdaptor - */ - void AddFlag( - const std::string& rFlagName, - const Flags& rFlagVariable, - const Globals::DataLocation& DataLocation); - - /** - * @brief Adds a variable to the output for a specified data location. - * - * Registers the given @p rVariable to be included in the VTU output at the specified - * @p DataLocation (e.g., NodeHistorical, NodeNonHistorical, Condition, or Element, refer @ref Globals::DataLocation). - * This allows the variable's values to be written to the output file when @ref PrintOutput is called. - * - * @throws std::runtime_error if @ref AddVariable is called after @ref PrintOutput. - * @throws std::runtime_error if tries to add the same @p rVariable more than ones. - * @throws std::runtime_error if there already exist a field name same as @p rVariable in one of the compatible data locations with @p DataLocation . - * @throws std::runtime_error if @p DataLocation is not NodeHistorical, NodeNonHistorical, Condition, or Element. - * - * @tparam TDataType Data type of the variable. - * @param rVariable Variable to be added. - * @param DataLocation The location in the model where the variable is defined (e.g., NodeHistorical, NodeNonHistorical, Condition, or Element). - * - * @see @ref VariableTensorAdaptor - * @see @ref HistoricalVariableTensorAdaptor - */ - template - void AddVariable( - const Variable& rVariable, - const Globals::DataLocation& DataLocation); - - /** - * @brief Adds a variable to be output at integration points. - * - * This method registers a @p rVariable for output at the integration points of the mesh elements or conditions - * specified by @p DataLocation (refer @ref Globals::DataLocation ). This allows the entities variable's integration point values to - * be written to the output file when @ref PrintOutput is called. - * - * @throws std::runtime_error if @ref AddIntegrationPointVariable is called after @ref PrintOutput. - * @throws std::runtime_error if tries to add the same @p rVariable more than ones. - * @throws std::runtime_error if there already exist a field name same as @p rVariable in one of the compatible data locations with @p DataLocation . - * @throws std::runtime_error if @p DataLocation is not Condition or Element. - * - * @tparam TDataType Data type of the variable. - * @param rVariable Variable to be added. - * @param DataLocation Specifies the location (e.g., Condition or Element) where the variable is used to calculate integration point values. - */ - template - void AddIntegrationPointVariable( - const Variable& rVariable, - const Globals::DataLocation& DataLocation); - - /** - * @brief Adds a tensor adaptor to the output. - * - * Registers a @p pTensorAdaptor with the specified @p TensorAdaptorName for the the vtu output. this does not - * copy the tensor adaptor. When @ref PrintOutput is called, the values of the @p pTensorAdaptor at this point will - * be written to vtu. - * - * @throws std::runtime_error if @ref AddTensorAdaptor is called after @ref PrintOutput. - * @throws std::runtime_error if tries to add the same @p rTensorAdaptorName more than ones. - * @throws std::runtime_error if there already exist a field name same as @p rTensorAdaptorName in one of the compatible data locations represented by the container of @p pTensorAdaptor . - * @throws std::runtime_error if @p pTensorAdaptor does not corresponds to any of the containers which is written by this @ref VtuOutput . - * - * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. - * @param rTensorAdaptorName The name to associate with the tensor adaptor. - * @param pTensorAdaptor Pointer to the tensor adaptor to be added. - */ - template - void AddTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor); - - /** - * @brief Updates the tensor adaptor associated with the given name. - * - * This method assigns a new tensor adaptor to the specified name, allowing - * for dynamic changes to the tensor adaptor used in the @ref VtuOutput process. - * This also copies the internal data of @p pTensorAdaptor to vtu output's internal data. - * - * @throws std::runtime_error if there is no field name same as @p rTensorAdaptorName in one of the compatible data locations represented by the container of @p pTensorAdaptor . - * @throws std::runtime_error if @p pTensorAdaptor does not corresponds to any of the containers which is written by this @ref VtuOutput . - * - * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. - * @param rTensorAdaptorName The name identifying the tensor adaptor to update. - * @param pTensorAdaptor Pointer to the new tensor adaptor to be associated. - */ - template - void ReplaceTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor); - - /** - * @brief Inserts a @ref TensorAdaptor into the internal storage with the specified name. - * - * This method: - * - If PrintOutput is not called at all, then calls @ref AddTensorAdaptor - * - If PrintOutput is at least once called, then calls @ref ReplaceTensorAdaptor - * - * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. - * @param rTensorAdaptorName The name to associate with the @ref TensorAdaptor. - * @param pTensorAdaptor Pointer to the @ref TensorAdaptor to be stored. - */ - template - void EmplaceTensorAdaptor( - const std::string& rTensorAdaptorName, - TTensorAdaptorPointerType pTensorAdaptor); - - /** - * @brief Returns the model part. - * @return The constant reference to the model part. - */ - const ModelPart& GetModelPart() const; - - /** - * @brief Get the list of output containers - * @details This method returns containers of the model part which are used when writing fields. - * @return std::vector List of container which are used in when writing fields. - */ - std::vector GetOutputContainerList() const; - - /** - * @brief Prints the vtu output data to a file with the specified filename prefix. - * - * Will create the folder with the provided @p rOutputFilenamePrefix . In this folder, following files will be created. - * - One vtu file per timestep, per model part's container (Including sub model parts if @p OutputSubModelParts is true) (in MPI, per rank as well). - * - If it find any gauss point fields, then there will be a vtu file per time step, per model part's container (in MPI, per rank as well). - * - If this is called in MPI, then this will create one pvtu file per timestep, per model part's container (will be having information of all the corresponding rank vtu files) - * - If this is called in MPI, then this will create one pvtu file per timestep, per model part's gauss point container (will be having information of all the corresponding rank vtu files) - * - * Finally it will create one pvd ( @p rOutputFilenamePrefix .pvd ) file for all the model parts, all the timesteps all the gauss point container linking - * - In MPI the pvtu files created. - * - In shared memory parallelism the vtu files created. - * - * @param rOutputFilenamePrefix The prefix to use for the output filename. - */ - void PrintOutput(const std::string& rOutputFilenamePrefix); - - ///@} - ///@name Input and output - ///@{ - - /// Turn back information as a string. - std::string Info() const override; - - /// Print information about this object. - void PrintInfo(std::ostream& rOStream) const override; - - /// Print object's data. - void PrintData(std::ostream& rOStream) const override; - - ///@} - -private: - ///@name Private member variables - ///@{ - - bool mIsPVDFileHeaderWritten; - - ModelPart& mrModelPart; - - const Globals::Configuration mConfiguration; - - const IndexType mEchoLevel; - - const WriterFormat mOutputFormat; - - const IndexType mPrecision; - - DataList mFlags; - - DataList mVariables; - - DataList mIntegrationPointVariables; - - std::vector mUnstructuredGridDataList; - - ///@} - ///@name Private operations - ///@{ - - template - void WriteData( - std::vector>& rPVDFileNameInfo, - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputPrefix, - const IndexType Step) const; - - template - std::pair WriteUnstructuredGridData( - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputPrefix, - const IndexType Step) const; - - template - std::pair WriteIntegrationPointData( - TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, - TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, - UnstructuredGridData& rUnstructuredGridData, - const std::string& rOutputPrefix, - const IndexType Step) const; - - ///@} -}; -} // namespace Kratos::Future diff --git a/kratos/future/python/add_io_to_python.cpp b/kratos/future/python/add_io_to_python.cpp index c627adbf6949..a89ebf9d3f06 100644 --- a/kratos/future/python/add_io_to_python.cpp +++ b/kratos/future/python/add_io_to_python.cpp @@ -16,7 +16,6 @@ // Project includes #include "includes/define_python.h" -#include "future/input_output/vtu_output.h" // Include base h #include "add_io_to_python.h" @@ -27,57 +26,6 @@ namespace Kratos::Future::Python void AddIOToPython(pybind11::module& m) { namespace py = pybind11; - - auto vtu_output = py::class_(m, "VtuOutput"); - - py::enum_(vtu_output, "WriterFormat") - .value("ASCII", VtuOutput::WriterFormat::ASCII) - .value("BINARY", VtuOutput::WriterFormat::BINARY) - .value("RAW", VtuOutput::WriterFormat::RAW) - .value("COMPRESSED_RAW", VtuOutput::WriterFormat::COMPRESSED_RAW) - .export_values() - ; - - vtu_output - .def(py::init(), - py::arg("model_part"), - py::arg("configuration") = Globals::Configuration::Initial, - py::arg("output_format") = VtuOutput::WriterFormat::COMPRESSED_RAW, - py::arg("precision") = 9, - py::arg("output_sub_model_parts") = false, - py::arg("write_ids") = false, - py::arg("echo_level") = 0) - .def("AddFlag", &VtuOutput::AddFlag, py::arg("flag_name"), py::arg("flag"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) - .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) - .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) - .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) - .def("GetModelPart", &VtuOutput::GetModelPart, py::return_value_policy::reference) - .def("GetOutputContainerList", &VtuOutput::GetOutputContainerList) - .def("PrintOutput", &VtuOutput::PrintOutput, py::arg("output_file_name_prefix")) - .def("__str__", PrintObject) - ; } } // namespace Kratos::Python. diff --git a/kratos/future/tests/test_KratosFutureCore.py b/kratos/future/tests/test_KratosFutureCore.py index 55fc6c6d82cd..f5766f865d86 100644 --- a/kratos/future/tests/test_KratosFutureCore.py +++ b/kratos/future/tests/test_KratosFutureCore.py @@ -5,7 +5,6 @@ import KratosMultiphysics.KratosUnittest as KratosUnittest # Import the tests or test_classes to create the suites -import test_vtu_output import test_linear_system import test_sparse_matrix_linear_operator @@ -28,9 +27,6 @@ def AssembleTestSuites(): smallSuite = suites['small'] smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([test_linear_system.TestLinearSystem])) smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([test_sparse_matrix_linear_operator.TestSparseMatrixLinearOperator])) - smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([test_vtu_output.TestVtuOutput2D])) - smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([test_vtu_output.TestVtuOutput3D])) - smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([test_vtu_output.TestVtuOutput])) # Create a test suite with the selected tests plus all small tests nightSuite = suites['nightly'] diff --git a/kratos/future/tests/test_vtu_output.py b/kratos/future/tests/test_vtu_output.py deleted file mode 100644 index 85e3dad5f43e..000000000000 --- a/kratos/future/tests/test_vtu_output.py +++ /dev/null @@ -1,585 +0,0 @@ -import math, typing -from pathlib import Path -import xml.etree.ElementTree as ET - -import KratosMultiphysics as Kratos -import KratosMultiphysics.KratosUnittest as kratos_unittest -import KratosMultiphysics.kratos_utilities as kratos_utils -from KratosMultiphysics.compare_two_files_check_process import CompareTwoFilesCheckProcess - -# import from the tests -with kratos_unittest.WorkFolderScope("../../tests", __file__, True): - from test_vtk_output_process import SetupModelPart2D, SetupModelPart3D - -class TestVtuOutputBase: - @classmethod - def SetSolution(cls): - node: Kratos.Node - for node in cls.model_part.Nodes: - node.SetSolutionStepValue(Kratos.DISPLACEMENT, 0,[node.X * 2, node.Y * 3, node.Z * 4]) - node.SetSolutionStepValue(Kratos.VELOCITY, 0,[node.X * 5, node.Y * 6, node.Z * 7]) - node.SetSolutionStepValue(Kratos.PRESSURE, 0, node.Id * 8.0) - - elem: Kratos.Element - for i_elem, elem in enumerate(cls.model_part.Elements): - elem.SetValue(Kratos.DETERMINANT, [i_elem*0.189, i_elem * 1.236, i_elem * 2.365]) - - cond: Kratos.Condition - for i_cond, cond in enumerate(cls.model_part.Conditions): - cond.SetValue(Kratos.DENSITY, i_cond * 4.362) - cond.SetValue(Kratos.YOUNG_MODULUS, i_cond * 5.326) - cond.SetValue(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Vector()) - - @classmethod - def setUpClass(cls, output_prefix: str, setup_method, output_sub_model_parts: bool) -> None: - cls.model = Kratos.Model() - cls.model_part = cls.model.CreateModelPart("test") - cls.model_part.ProcessInfo[Kratos.STEP] = 0 - cls.model_part.ProcessInfo[Kratos.TIME] = 1.0 - cls.output_prefix = output_prefix - cls.output_sub_model_parts = output_sub_model_parts - setup_method(cls.model_part) - cls.SetSolution() - - def WriteVtu(self, output_format: Kratos.Future.VtuOutput.WriterFormat, error_check = False): - vtu_output = Kratos.Future.VtuOutput(self.model_part, Kratos.Configuration.Initial, output_format, 9, echo_level=0, output_sub_model_parts=self.output_sub_model_parts, write_ids=True) - vtu_output.AddVariable(Kratos.PRESSURE, Kratos.Globals.DataLocation.NodeHistorical) - vtu_output.AddVariable(Kratos.VELOCITY, Kratos.Globals.DataLocation.NodeHistorical) - vtu_output.AddVariable(Kratos.DISPLACEMENT, Kratos.Globals.DataLocation.NodeHistorical) - vtu_output.AddVariable(Kratos.DETERMINANT, Kratos.Globals.DataLocation.Element) - vtu_output.AddVariable(Kratos.DENSITY, Kratos.Globals.DataLocation.Condition) - vtu_output.AddVariable(Kratos.YOUNG_MODULUS, Kratos.Globals.DataLocation.Condition) - if error_check: - # adds a vector with zero size to check for the error. Because, in vtu lib, - # if the behavior is undefined if the "NumberOfComponents = 0". - vtu_output.AddVariable(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Globals.DataLocation.Condition) - - ta_1 = Kratos.TensorAdaptors.HistoricalVariableTensorAdaptor(self.model_part.Nodes, Kratos.PRESSURE) - ta_1.CollectData() - ta_2 = Kratos.TensorAdaptors.VariableTensorAdaptor(self.model_part.Elements, Kratos.DETERMINANT) - ta_2.CollectData() - - ta_1.data *= 3 - ta_2.data *= 3 - - vtu_output.AddTensorAdaptor("hist_ta", ta_1) - vtu_output.AddTensorAdaptor("elem_ta", ta_2) - - with kratos_unittest.WorkFolderScope("vtk_output_process_ref_files", __file__, True): - output_file_prefix = output_format.name.lower() + self.output_prefix + "/Main" - vtu_output.PrintOutput("temp/" + output_file_prefix) - self.Check("temp/" + output_file_prefix, output_file_prefix) - - def test_WriteMeshAscii(self): - self.WriteVtu(Kratos.Future.VtuOutput.ASCII) - - def test_WriteMeshBinary(self): - self.WriteVtu(Kratos.Future.VtuOutput.BINARY) - - def test_WriteMeshRaw(self): - self.WriteVtu(Kratos.Future.VtuOutput.RAW) - - def test_WriteMeshCompressedRaw(self): - self.WriteVtu(Kratos.Future.VtuOutput.COMPRESSED_RAW) - - def test_WriteMeshAsciiWithError(self): - self.addCleanup(kratos_utils.DeleteDirectoryIfExisting, "vtk_output_process_ref_files/temp") - with self.assertRaises(RuntimeError): - self.WriteVtu(Kratos.Future.VtuOutput.ASCII, True) - - def test_WriteMeshBinaryWithError(self): - self.addCleanup(kratos_utils.DeleteDirectoryIfExisting, "vtk_output_process_ref_files/temp") - with self.assertRaises(RuntimeError): - self.WriteVtu(Kratos.Future.VtuOutput.BINARY, True) - - def test_WriteMeshRawWithError(self): - self.addCleanup(kratos_utils.DeleteDirectoryIfExisting, "vtk_output_process_ref_files/temp") - with self.assertRaises(RuntimeError): - self.WriteVtu(Kratos.Future.VtuOutput.RAW, True) - - def test_WriteMeshCompressedRawWithError(self): - self.addCleanup(kratos_utils.DeleteDirectoryIfExisting, "vtk_output_process_ref_files/temp") - with self.assertRaises(RuntimeError): - self.WriteVtu(Kratos.Future.VtuOutput.COMPRESSED_RAW, True) - - def Check(self, output_prefix, reference_prefix): - def check_file(output_file_name: str, reference_file_name: str): - ## Settings string in json format - params = Kratos.Parameters("""{ - "reference_file_name" : "", - "output_file_name" : "", - "comparison_type" : "deterministic" - }""") - params["reference_file_name"].SetString(reference_file_name) - params["output_file_name"].SetString(output_file_name) - CompareTwoFilesCheckProcess(params).Execute() - - for file_path in Path(reference_prefix).iterdir(): - self.assertTrue((Path(output_prefix) / file_path.name).is_file(), msg=f"\"{(Path(output_prefix) / file_path.name)}\" is not a file.") - check_file(f"{output_prefix}/{file_path.name}", str(file_path)) - check_file(f"{output_prefix}.pvd", f"{reference_prefix}.pvd") - - kratos_utils.DeleteDirectoryIfExistingAndEmpty("temp") - -class TestVtuOutput2D(TestVtuOutputBase, kratos_unittest.TestCase): - @classmethod - def setUpClass(cls) -> None: - super().setUpClass("2D", SetupModelPart2D, output_sub_model_parts = True) - -class TestVtuOutput3D(TestVtuOutputBase, kratos_unittest.TestCase): - @classmethod - def setUpClass(cls) -> None: - # the method SetupModelPart3D does not create sub model parts - # with nodes which do not include nodes from its conditions or elements. It uses - # some random nodes. Hence sub_model_part output is disabled. - super().setUpClass("3D", SetupModelPart3D, output_sub_model_parts = False) - -class TestVtuOutput(kratos_unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.data_location = Kratos.Globals.DataLocation - - cls.model = Kratos.Model() - cls.model_part = cls.model.CreateModelPart("test") - cls.model_part.AddNodalSolutionStepVariable(Kratos.STEP) - cls.model_part.AddNodalSolutionStepVariable(Kratos.PRESSURE) - cls.model_part.AddNodalSolutionStepVariable(Kratos.DISPLACEMENT) - cls.model_part.AddNodalSolutionStepVariable(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT) - cls.model_part.AddNodalSolutionStepVariable(Kratos.CONSTITUTIVE_MATRIX) - - cls.model_part.ProcessInfo[Kratos.TIME] = 1 - - # creating a circular pie with origin (0, 0) - radius = 1.0 - number_of_elements_or_conditions = 50 - angle = 2 * math.pi / number_of_elements_or_conditions - - cls.model_part.CreateNewNode(1, 0, 0, 0) # origin node - for i in range(number_of_elements_or_conditions): - theta = i * angle - cls.model_part.CreateNewNode(i + 2, radius * math.cos(theta), radius * math.sin(theta), 0.0) - - prop = cls.model_part.CreateNewProperties(1) - for i in range(number_of_elements_or_conditions): - cls.model_part.CreateNewElement("Element2D3N", i + 1, [1, i + 2, (i + 1) % (number_of_elements_or_conditions) + 2], prop) - cls.model_part.CreateNewCondition("LineCondition2D2N", i + 1, [i + 2, (i + 1) % (number_of_elements_or_conditions) + 2], prop) - - # create the sub model part structure - for j in range(4): - l_1 = j // 9 - l_2 = (j // 3) % 3 - l_3 = j % 3 - model_part = cls.model_part.CreateSubModelPart(f"mp_{l_1}.mp_{l_2}.mp_{l_3}") - # fill the sub range - for i in range(number_of_elements_or_conditions): - if (j % 2 == 0): - if (i % ((l_1 + 1) * (l_2 + 1) * (l_3 + 1)) == 0): - model_part.AddCondition(cls.model_part.GetCondition(i + 1)) - else: - if (i % ((l_1 + 1) * (l_2 + 1) * (l_3 + 1)) == 1): - model_part.AddElement(cls.model_part.GetElement(i + 1)) - - # now recursively fill the nodes - def fill_nodes(model_part: Kratos.ModelPart): - list_of_node_ids: 'list[int]' = [] - for condition in model_part.Conditions: - for node in condition.GetGeometry(): - list_of_node_ids.append(node.Id) - for element in model_part.Elements: - for node in element.GetGeometry(): - list_of_node_ids.append(node.Id) - - model_part.AddNodes(list_of_node_ids) - - for sub_model_part in model_part.SubModelParts: - fill_nodes(sub_model_part) - - fill_nodes(cls.model_part) - - def add_variables(container, setter): - for entity in container: - setter(entity, Kratos.STEP, entity.Id * 2) - setter(entity, Kratos.PRESSURE, entity.Id) - setter(entity, Kratos.DISPLACEMENT, Kratos.Array3([entity.Id, entity.Id + 1, entity.Id + 2])) - setter(entity, Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Vector([entity.Id, entity.Id + 1, entity.Id + 2, entity.Id + 3, entity.Id + 4])) - setter(entity, Kratos.CONSTITUTIVE_MATRIX, Kratos.Matrix([[entity.Id, entity.Id + 1], [entity.Id + 2, entity.Id + 3], [entity.Id + 4, entity.Id + 5]])) - - add_variables(cls.model_part.Nodes, lambda x, y, z: x.SetSolutionStepValue(y, z)) - add_variables(cls.model_part.Nodes, lambda x, y, z: x.SetValue(y, z)) - add_variables(cls.model_part.Conditions, lambda x, y, z: x.SetValue(y, z)) - add_variables(cls.model_part.Elements, lambda x, y, z: x.SetValue(y, z)) - - def setUp(self): - self.model_part.ProcessInfo[Kratos.STEP] = 0 - - def test_GetOutputContainerList(self): - unstructured_grid_list = self.GetUnstructuredGridList(self.model_part, self.model_part.GetRootModelPart().GetCommunicator().GetDataCommunicator(), True) - - vtu_output = Kratos.Future.VtuOutput(self.model_part, output_sub_model_parts=True, output_format=Kratos.Future.VtuOutput.BINARY) - list_of_containers = vtu_output.GetOutputContainerList() - - list_of_ref_containers = [] - for mp, is_nodes_used, cells_container in unstructured_grid_list: - if is_nodes_used: - list_of_ref_containers.append(mp.Nodes) - list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Nodes) - - if cells_container is not None: - list_of_ref_containers.append(cells_container) - if isinstance(cells_container, Kratos.ConditionsArray): - list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Conditions) - elif isinstance(cells_container, Kratos.ElementsArray): - list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Elements) - - self.assertEqual(list_of_containers, list_of_ref_containers) - - def test_PointVariableAddition(self): - vtu_output = Kratos.Future.VtuOutput(self.model_part, output_sub_model_parts=True, output_format=Kratos.Future.VtuOutput.BINARY) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Condition) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Element) - vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Condition) - vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Element) - - with self.assertRaises(RuntimeError): - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) - - with self.assertRaises(RuntimeError): - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeNonHistorical) - - ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Nodes, Kratos.DoubleNDData([51, 5])) - ta.Check() - with self.assertRaises(RuntimeError): - vtu_output.AddTensorAdaptor("PRESSURE", ta) - vtu_output.AddTensorAdaptor("PRESSURE_1", ta) - - with self.assertRaises(RuntimeError): - vtu_output.AddTensorAdaptor("PRESSURE_1", ta) - vtu_output.AddTensorAdaptor("PRESSURE_2", ta) - - ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Conditions, Kratos.DoubleNDData([50,2,4])) - ta.Check() - with self.assertRaises(RuntimeError): - vtu_output.AddTensorAdaptor("PRESSURE", ta) - vtu_output.AddTensorAdaptor("PRESSURE_1", ta) - vtu_output.AddTensorAdaptor("PRESSURE_2", ta) - vtu_output.AddTensorAdaptor("PRESSURE_3", ta) - - ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Elements, Kratos.DoubleNDData([50,2,5])) - ta.Check() - with self.assertRaises(RuntimeError): - vtu_output.AddTensorAdaptor("PRESSURE", ta) - vtu_output.AddTensorAdaptor("PRESSURE_1", ta) - vtu_output.AddTensorAdaptor("PRESSURE_2", ta) - vtu_output.AddTensorAdaptor("PRESSURE_3", ta) - - vtu_output.PrintOutput("temp/vtu_output/variable_test") - - model_part = vtu_output.GetModelPart() - unstructured_grid_list = self.GetUnstructuredGridList(model_part, model_part.GetCommunicator().GetDataCommunicator(), True) - list_of_vtu_file_names: 'list[str]' = [] - for model_part, use_nodes, container in unstructured_grid_list: - vtu_file_name = TestVtuOutput.GetUnstructuredGridName((model_part, use_nodes, container), "temp/vtu_output/variable_test", 0, model_part.GetCommunicator().GetDataCommunicator()) - list_of_vtu_file_names.append(vtu_file_name) - if model_part.FullName() == "test": - if use_nodes: - TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "binary", - { - "PRESSURE": (1, "Float64"), - "PRESSURE_1": (5, "Float64"), - "PRESSURE_2": (5, "Float64") - }, - { - "PRESSURE": (1, "Float64") - }) - elif isinstance(container, Kratos.ConditionsArray): - TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", - {}, - { - "PRESSURE": (1, "Float64"), - "PRESSURE_1": (8, "Float64"), - "PRESSURE_2": (8, "Float64"), - "PRESSURE_3": (8, "Float64") - }) - elif isinstance(container, Kratos.ElementsArray): - TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", - { - "PRESSURE": (1, "Float64"), - "PRESSURE_1": (5, "Float64"), - "PRESSURE_2": (1, "Float64"), - "PRESSURE_3": (5, "Float64") - }, - { - "PRESSURE": (1, "Float64"), - "PRESSURE_1": (10, "Float64"), - "PRESSURE_2": (10, "Float64"), - "PRESSURE_3": (10, "Float64") - }) - else: - if use_nodes: - TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "binary", - { - "PRESSURE": (1, "Float64") - }, - { - "PRESSURE": (1, "Float64") - }) - else: - TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", - { - }, - { - "PRESSURE": (1, "Float64") - }) - # check gauss - list_of_vtu_file_names.append(TestVtuOutput.CheckGaussVtuFile(self, model_part, container, "temp/vtu_output/variable_test", 0, "binary", model_part.GetCommunicator().GetDataCommunicator(), - { - "PRESSURE": (1, "Float64") - })) - TestVtuOutput.CheckPvdFile(self, "temp/vtu_output/variable_test.pvd", list_of_vtu_file_names, [1 + 1e-9]) - - def test_CellVariableAddition(self): - vtu_output = Kratos.Future.VtuOutput(self.model_part, output_format=Kratos.Future.VtuOutput.ASCII, output_sub_model_parts=True) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Condition) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) - vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Element) - vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Condition) - vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Element) - - vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.Element) - vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.NodeHistorical) - vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.Condition) - vtu_output.AddIntegrationPointVariable(Kratos.DISPLACEMENT, self.data_location.Condition) - vtu_output.AddIntegrationPointVariable(Kratos.DISPLACEMENT, self.data_location.Element) - - vtu_output.PrintOutput("temp/vtu_output/time_step_test") - vtu_output.GetModelPart().ProcessInfo[Kratos.TIME] += 1e-9 - vtu_output.GetModelPart().ProcessInfo[Kratos.STEP] += 1 - vtu_output.PrintOutput("temp/vtu_output/time_step_test") - - model_part = vtu_output.GetModelPart() - unstructured_grid_list = self.GetUnstructuredGridList(model_part, model_part.GetCommunicator().GetDataCommunicator(), True) - list_of_vtu_file_names: 'list[str]' = [] - for step in range(2): - for model_part, use_nodes, container in unstructured_grid_list: - vtu_file_name = TestVtuOutput.GetUnstructuredGridName((model_part, use_nodes, container), "temp/vtu_output/time_step_test", step, model_part.GetCommunicator().GetDataCommunicator()) - list_of_vtu_file_names.append(vtu_file_name) - if use_nodes: - TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "ascii", - { - "PRESSURE": (1, "Float64"), - "DISPLACEMENT": (3, "Float64") - }, - { - "PRESSURE": (1, "Float64"), - "DISPLACEMENT": (3, "Float64") - }) - else: - TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "ascii", - { - }, - { - "PRESSURE": (1, "Float64"), - "DISPLACEMENT": (3, "Float64") - }) - - # check gauss - list_of_vtu_file_names.append(TestVtuOutput.CheckGaussVtuFile(self, model_part, container, "temp/vtu_output/time_step_test", step, "ascii", model_part.GetCommunicator().GetDataCommunicator(), - { - "DISPLACEMENT": (3, "Float64") - })) - - TestVtuOutput.CheckPvdFile(self, "temp/vtu_output/time_step_test.pvd", list_of_vtu_file_names, [1, 1 + 1e-9]) - - @staticmethod - def GetUnstructuredGridList(model_part: Kratos.ModelPart, data_communicator: Kratos.DataCommunicator, recursively: bool) -> 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]': - unstructured_grid_list: 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]' = [] - TestVtuOutput.__GetUnstructuredGridList(unstructured_grid_list, model_part, data_communicator, recursively) - return sorted(unstructured_grid_list, key = lambda x: x[0].FullName()) - - @staticmethod - def GetUnstructuredGridName(unstructured_grid: 'tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]', prefix: str, step: int, data_communicator: Kratos.DataCommunicator, entity_suffix = "s") -> str: - if data_communicator.IsDistributed(): - rank_suffix = f"_{data_communicator.Rank()}" - else: - rank_suffix = "" - - if unstructured_grid[2] is None: - entity_type = "node" - elif isinstance(unstructured_grid[2], Kratos.ConditionsArray): - entity_type = "condition" - elif isinstance(unstructured_grid[2], Kratos.ElementsArray): - entity_type = "element" - return f"{prefix}/{unstructured_grid[0].FullName()}_{entity_type}{entity_suffix}_{step}{rank_suffix}.vtu" - - @staticmethod - def GetNodes(model_part: Kratos.ModelPart, use_model_part_nodes: bool, container: 'typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]') -> 'list[Kratos.Node]': - if use_model_part_nodes: - return model_part.Nodes - else: - temp = [] - for entity in container: - for node in entity.GetGeometry(): - temp.append(node.Id) - return [model_part.GetRootModelPart().GetNode(node_id) for node_id in list(sorted(set(temp)))] - - def GetNumberOfNodes(container: 'typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]') -> int: - temp = [] - for entity in container: - for node in entity.GetGeometry(): - temp.append(node.Id) - return len(list(set(temp))) - - @staticmethod - def CheckDataArray(test_class: kratos_unittest.TestCase, xml_element: ET.Element, number_of_components: int, name: str, data_type: str, data_format: 'typing.Optional[str]' = None): - test_class.assertEqual(xml_element.get("NumberOfComponents"), str(number_of_components)) - test_class.assertEqual(xml_element.get("type"), data_type) - test_class.assertEqual(xml_element.get("Name"), name) - if data_format is not None: - test_class.assertEqual(xml_element.get("format"), data_format) - - @staticmethod - def CheckVtuFile( - test_class: kratos_unittest.TestCase, - vtu_file_name: str, - number_of_points: int, - number_of_cells: 'typing.Optional[int]', - data_format : str, - point_data_fields: 'dict[str, tuple[int, str]]', - cell_data_fields: 'dict[str, tuple[int, str]]'): - - test_class.assertTrue(Path(vtu_file_name).is_file(), f"The file {vtu_file_name} not found.") - tree = ET.parse(vtu_file_name) - root = tree.getroot() - - test_class.assertEqual(root.tag, "VTKFile") - test_class.assertEqual(root.get("type"), "UnstructuredGrid") - test_class.assertEqual(root.get("version"), "0.1") - - unstructured_grid = root.find("UnstructuredGrid") - piece = unstructured_grid.find("Piece") - - if number_of_cells is None: - local_number_of_cells = 0 - else: - local_number_of_cells = number_of_cells - - test_class.assertEqual(piece.get("NumberOfPoints"), f"{number_of_points}", f"Vtu file name = {vtu_file_name}") - test_class.assertEqual(piece.get("NumberOfCells"), f"{local_number_of_cells}", f"Vtu file name = {vtu_file_name}") - - points = piece.find("Points") - TestVtuOutput.CheckDataArray(test_class, points.find("DataArray"), 3, "Position", "Float64", data_format) - - cells = piece.find("Cells") - if not number_of_cells is None: - data_arrays = cells.findall("DataArray") - TestVtuOutput.CheckDataArray(test_class, data_arrays[0], 1, "connectivity", "Int32", data_format) - TestVtuOutput.CheckDataArray(test_class, data_arrays[1], 1, "offsets", "Int32", data_format) - TestVtuOutput.CheckDataArray(test_class, data_arrays[2], 1, "types", "UInt8", data_format) - - # now checking for point data - point_data = piece.find("PointData") - for data_field_name, (data_field_number_of_components, data_field_data_type) in point_data_fields.items(): - found = False - for point_data_array in point_data.findall("DataArray"): - if point_data_array.get("Name") == data_field_name: - TestVtuOutput.CheckDataArray(test_class, point_data_array, data_field_number_of_components, data_field_name, data_field_data_type, data_format) - found = True - break - test_class.assertTrue(found, f"Point data field \"{data_field_name}\" not found in the \"{vtu_file_name}\"") - - if not number_of_cells is None: - # now checking for cell data - cell_data = piece.find("CellData") - for data_field_name, (data_field_number_of_components, data_field_data_type) in cell_data_fields.items(): - found = False - for point_data_array in cell_data.findall("DataArray"): - if point_data_array.get("Name") == data_field_name: - TestVtuOutput.CheckDataArray(test_class, point_data_array, data_field_number_of_components, data_field_name, data_field_data_type, data_format) - found = True - break - test_class.assertTrue(found, f"Cell data field \"{data_field_name}\" not found in the \"{vtu_file_name}\"") - kratos_utils.DeleteFileIfExisting(vtu_file_name) - - @staticmethod - def CheckPvdFile(test_class: kratos_unittest.TestCase, pvd_file_name: str, vtu_file_name_list: 'list[str]', time_step_list: 'list[float]'): - test_class.assertTrue(Path(pvd_file_name).is_file(), f"The file {pvd_file_name} not found.") - tree = ET.parse(pvd_file_name) - root = tree.getroot() - - test_class.assertEqual(root.tag, "VTKFile") - test_class.assertEqual(root.get("type"), "Collection") - test_class.assertEqual(root.get("version"), "1.0") - - collection = root.find("Collection") - datasets = collection.findall("DataSet") - test_class.assertEqual(len(datasets), len(vtu_file_name_list), f"file name = {pvd_file_name}, list_of_time_steps = {time_step_list}, list_of_vtu_files = \n" + "\n\t".join(vtu_file_name_list)) - for i, dataset in enumerate(datasets): - relative_path = Path(vtu_file_name_list[i]).absolute().relative_to(Path(pvd_file_name).absolute().parent) - test_class.assertEqual(dataset.get("file"), str(relative_path)) - test_class.assertEqual(dataset.get("name"), relative_path.name[:relative_path.name.rfind("_")]) - test_class.assertEqual(dataset.get("part"), str(i % (len(vtu_file_name_list) // len(time_step_list)))) - test_class.assertEqual(dataset.get("timestep"), f"{time_step_list[i // (len(vtu_file_name_list) // len(time_step_list))]:0.9e}", f"file name = {relative_path}") - kratos_utils.DeleteFileIfExisting(pvd_file_name) - - @staticmethod - def CheckGaussVtuFile(test_class: kratos_unittest.TestCase, model_part: Kratos.ModelPart, container, prefix: str, step_id: int, output_type: str, data_communicator: Kratos.DataCommunicator, point_fields): - number_of_points = 0 - for entity in container: - if len(entity.GetGeometry()) == 4: - number_of_points += 4 - elif len(entity.GetGeometry()) == 3: - number_of_points += 1 - elif len(entity.GetGeometry()) == 2: - number_of_points += 1 - else: - raise RuntimeError("Unsupported geometry") - - if isinstance(container, Kratos.ConditionsArray): - suffix = "condition" - elif isinstance(container, Kratos.ElementsArray): - suffix = "element" - else: - raise RuntimeError("Unsupported container type.") - - if data_communicator.IsDistributed(): - rank_suffix = f"_{data_communicator.Rank()}" - else: - rank_suffix = "" - - file_name = f"{prefix}/{model_part.FullName()}_{suffix}_gauss_{step_id}{rank_suffix}.vtu" - TestVtuOutput.CheckVtuFile( - test_class, - file_name, - number_of_points, None, output_type, point_fields, {}) - kratos_utils.DeleteFileIfExisting(file_name) - return file_name - - @staticmethod - def __GetUnstructuredGridList(unstructured_grid_list: 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]', model_part: Kratos.ModelPart, data_communicator: Kratos.DataCommunicator, recursively: bool) -> None: - availability = data_communicator.MaxAll(Kratos.Array3([model_part.NumberOfNodes(), model_part.NumberOfConditions(), model_part.NumberOfElements()])) - has_nodes = availability[0] > 0 - has_conditions = availability[1] > 0 - has_elements = availability[2] > 0 - - if has_elements: - unstructured_grid_list.append((model_part, has_nodes, model_part.Elements)) - - if has_conditions: - unstructured_grid_list.append((model_part, not has_elements and has_nodes, model_part.Conditions)) - - if not has_elements and not has_conditions: - unstructured_grid_list.append((model_part, has_nodes, None)) - - if recursively: - for sub_model_part in model_part.SubModelParts: - TestVtuOutput.__GetUnstructuredGridList(unstructured_grid_list, sub_model_part, data_communicator, recursively) - - @classmethod - def tearDownClass(cls): - kratos_utils.DeleteDirectoryIfExistingAndEmpty("temp") - - -if __name__ == "__main__": - Kratos.Logger.GetDefaultOutput().SetSeverity(Kratos.Logger.Severity.INFO) - kratos_unittest.main() \ No newline at end of file diff --git a/kratos/input_output/vtu_output.cpp b/kratos/input_output/vtu_output.cpp index 249f9be2b7c4..187b5a8d200f 100644 --- a/kratos/input_output/vtu_output.cpp +++ b/kratos/input_output/vtu_output.cpp @@ -11,831 +11,1734 @@ // // System includes -#include -#include +#include +#include #include +#include // External includes // Project includes -#include "expression/container_data_io.h" -#include "expression/container_expression.h" -#include "expression/literal_flat_expression.h" -#include "expression/variable_expression_io.h" #include "includes/data_communicator.h" #include "input_output/base_64_encoded_output.h" #include "input_output/vtk_definitions.h" -#include "utilities/global_pointer_utilities.h" +#include "tensor_adaptors/flags_tensor_adaptor.h" +#include "tensor_adaptors/historical_variable_tensor_adaptor.h" +#include "tensor_adaptors/node_position_tensor_adaptor.h" +#include "tensor_adaptors/variable_tensor_adaptor.h" +#include "utilities/container_io_utils.h" +#include "utilities/data_type_traits.h" #include "utilities/parallel_utilities.h" -#include "utilities/pointer_communicator.h" +#include "utilities/reduction_utilities.h" #include "utilities/string_utilities.h" -#include "utilities/xml_utilities/xml_expression_element.h" -#include "utilities/xml_utilities/xml_ostream_ascii_writer.h" -#include "utilities/xml_utilities/xml_ostream_base64_binary_writer.h" +#include "utilities/xml_utilities/xml_appended_data_element_wrapper.h" +#include "utilities/xml_utilities/xml_elements_array.h" +#include "utilities/xml_utilities/xml_in_place_data_element_wrapper.h" +#include "utilities/xml_utilities/xml_utils.h" // Include base h #include "vtu_output.h" namespace Kratos { - KRATOS_CREATE_LOCAL_FLAG(VtuOutput, NODES, 1); - KRATOS_CREATE_LOCAL_FLAG(VtuOutput, CONDITIONS, 2); - KRATOS_CREATE_LOCAL_FLAG(VtuOutput, ELEMENTS, 3); +namespace { -namespace VtuOutputHelperUtilities { - -Expression::ConstPointer CreatePositionsExpression( - const ModelPart::NodesContainerType& rNodes, - const bool IsInitialConfiguration) -{ - auto p_position_expression = LiteralFlatExpression::Create(rNodes.size(), {3}); - auto& r_position_expression = *p_position_expression; - - if (IsInitialConfiguration) { - IndexPartition(rNodes.size()).for_each([&r_position_expression, &rNodes](const IndexType Index) { - const auto& r_coordinates = (rNodes.begin() + Index)->GetInitialPosition().Coordinates(); - const IndexType start_index = Index * 3; - r_position_expression.SetData(start_index, 0, r_coordinates[0]); - r_position_expression.SetData(start_index, 1, r_coordinates[1]); - r_position_expression.SetData(start_index, 2, r_coordinates[2]); - }); +constexpr std::string GetEndianness() +{ + if constexpr(std::endian::native == std::endian::little) { + return "LittleEndian"; + } else if constexpr(std::endian::native == std::endian::big) { + return "BigEndian"; } else { - IndexPartition(rNodes.size()).for_each([&r_position_expression, &rNodes](const IndexType Index) { - const auto& r_coordinates = (rNodes.begin() + Index)->Coordinates(); - const IndexType start_index = Index * 3; - r_position_expression.SetData(start_index, 0, r_coordinates[0]); - r_position_expression.SetData(start_index, 1, r_coordinates[1]); - r_position_expression.SetData(start_index, 2, r_coordinates[2]); - }); + KRATOS_ERROR << "Unsupported endianess."; + return ""; } +} - return p_position_expression; +template +void CheckDataArrayName( + const std::string& rName, + const Globals::DataLocation& rLocation, + const VtuOutput::DataList& rList) +{ + KRATOS_TRY + + KRATOS_ERROR_IF(rList[static_cast(rLocation)].find(rName) != rList[static_cast(rLocation)].end()) + << "Found an existing data array with the same name = \"" << rName << "\".\n"; + + KRATOS_CATCH(""); } -XmlExpressionElement::Pointer CreateDataArrayElement( - const std::string& rDataArrayName, - const std::vector& rExpressions) +void CheckDataArrayName( + const std::string& rName, + const Globals::DataLocation& rLocation, + const VtuOutput::UnstructuredGridData& rUnstructuredGridData) { - std::vector expressions; - for (const auto& p_expression : rExpressions) { - if (p_expression) { - expressions.push_back(p_expression); - } + KRATOS_TRY + + bool found_existing_name = false; + switch (rLocation) { + case Globals::DataLocation::NodeHistorical: + case Globals::DataLocation::NodeNonHistorical: + // The following code block will be executed for Globals::DataLocation::NodeHistorical and Globals::DataLocation::NodeNonHistorical. + found_existing_name = rUnstructuredGridData.mMapOfPointTensorAdaptors.find(rName) != rUnstructuredGridData.mMapOfPointTensorAdaptors.end(); + break; + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: + // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. + found_existing_name = rUnstructuredGridData.mMapOfCellTensorAdaptors.find(rName) != rUnstructuredGridData.mMapOfCellTensorAdaptors.end(); + break; + default: + KRATOS_ERROR << "Unsupported data location type."; } - if (expressions.size() > 0) { - return Kratos::make_shared(rDataArrayName, expressions); - } else { - return nullptr; + + KRATOS_ERROR_IF(found_existing_name) + << "Found an existing data array with the same name = \"" << rName << "\".\n"; + + KRATOS_CATCH(""); +} + +void CheckDataArrayName( + const std::string& rName, + const Globals::DataLocation& rLocation, + const std::vector& rListOfUnstructuredGridData) +{ + KRATOS_TRY + + for (const auto& r_model_part_data : rListOfUnstructuredGridData) { + switch (rLocation) { + case Globals::DataLocation::NodeHistorical: + case Globals::DataLocation::NodeNonHistorical: + // The following code block will be executed for Globals::DataLocation::NodeHistorical and Globals::DataLocation::NodeNonHistorical. + if (r_model_part_data.UsePointsForDataFieldOutput) { + CheckDataArrayName(rName, rLocation, r_model_part_data); + } + break; + default: + CheckDataArrayName(rName, rLocation, r_model_part_data); + } } + + KRATOS_CATCH(""); } -template -const Expression* pGetExpression(const ContainerExpression& rContainerExpression) +std::string GetEntityName(const std::optional& pCellContainer) { - if (rContainerExpression.HasExpression()) { - return &*rContainerExpression.pGetExpression(); + if (pCellContainer.has_value()) { + return std::visit([](auto p_cell_container) { + using container_type = BareType; + return ModelPart::Container::GetEntityName(); + }, pCellContainer.value()); } else { - return nullptr; + return "node"; } } -void AddDataArrayElement( - XmlExpressionElement::Pointer pParentElement, - XmlExpressionElement::Pointer pDataArrayElement) +void CopyAttributes( + const XmlElement& rSource, + XmlElement& rDestination) { - if (pDataArrayElement) { - pParentElement->AddElement(pDataArrayElement); + for (const auto& [attribute, value] : rSource.GetAttributes()) { + rDestination.AddAttribute(attribute, value); } } -XmlExpressionElement::Pointer CreatePointsXmlElement( - const ModelPart& rModelPart, - const bool IsInitialConfiguration) +template +NDDataPointerType GetWritingNDData( + const std::vector& rWritingIndices, + NDDataPointerType pNDData) { - auto p_points_xml_element = Kratos::make_shared("Points"); + KRATOS_TRY - const auto& r_communicator = rModelPart.GetCommunicator(); - const auto& r_local_nodes = r_communicator.LocalMesh().Nodes(); - const auto& r_ghost_nodes = r_communicator.GhostMesh().Nodes(); + const auto& origin_shape = pNDData->Shape(); - auto local_position = CreatePositionsExpression(r_local_nodes, IsInitialConfiguration); - auto ghost_position = CreatePositionsExpression(r_ghost_nodes, IsInitialConfiguration); + KRATOS_ERROR_IF(origin_shape.size() == 0) + << "NDData shape should have at least one dimension representing number of entities [ nd data = " + << *pNDData << " ].\n"; - AddDataArrayElement( - p_points_xml_element, - CreateDataArrayElement("Position", {&*local_position, &*ghost_position})); + if (rWritingIndices.size() == origin_shape[0]) { + // number of writing indices are same as the first dimension of the NdData, hence + // there is nothing to be ignored from this data set. Returning the original + return pNDData; + } else { + // now there is a mismatch between number of writing indices and the number of entities represented by the pNDData. + // Hence we continue with copying data. - return p_points_xml_element; -} + // data type of the NDData, may be unsigned char, int, bool, double + using data_type = typename BareType::DataType; -template -LiteralFlatExpression::Pointer CreateOffsetsExpression(const TContainerType& rContainer) -{ - auto p_offsets_expression = LiteralFlatExpression::Create(rContainer.size(), {}); - auto data_itr = p_offsets_expression->begin(); + // compute number of components for each entity. + const auto number_of_components = std::accumulate(origin_shape.begin() + 1, origin_shape.end(), 1u, std::multiplies{}); + + // construct the new NDData holder having only the data from writing indices. + DenseVector destination_shape(origin_shape); + destination_shape[0] = rWritingIndices.size(); + auto p_destination_nd_data = Kratos::make_shared>(destination_shape); - IndexType total_offset = 0; - for (const auto& r_entity : rContainer) { - total_offset += r_entity.GetGeometry().size(); - *(data_itr++) = total_offset; + // get spans + const auto& origin_span = pNDData->ViewData(); + auto destination_span = p_destination_nd_data->ViewData(); + + // now copy the data + IndexPartition(rWritingIndices.size()).for_each([&origin_span, &destination_span, &rWritingIndices, number_of_components](const auto Index) { + auto orig_itr = origin_span.begin() + rWritingIndices[Index] * number_of_components; + auto dest_itr = destination_span.begin() + Index * number_of_components; + std::copy(orig_itr, orig_itr + number_of_components, dest_itr); + }); + + return p_destination_nd_data; } - return p_offsets_expression; + + KRATOS_CATCH(""); } template -Expression::Pointer CreateGeometryTypesExpression(const TContainerType& rContainer) +NDData::Pointer GetGeometryTypes( + std::vector& rWritingIndices, + const TContainerType& rContainer, + const IndexType EchoLevel) { - auto p_geometry_expression = LiteralFlatExpression::Create(rContainer.size(), {}); - auto data_itr = p_geometry_expression->begin(); + auto p_geometry_types = Kratos::make_shared>(DenseVector(1, rContainer.size())); + auto span = p_geometry_types->ViewData(); + + DenseVector ignored_indices(rContainer.size(), 0); + + IndexPartition(rContainer.size()).for_each([&span, &rContainer, &ignored_indices, EchoLevel](const IndexType Index) { - IndexPartition(rContainer.size()).for_each([data_itr, &rContainer](const IndexType Index) { const auto p_itr = VtkDefinitions::KratosVtkGeometryTypes.find((rContainer.begin() + Index)->GetGeometry().GetGeometryType()); if (p_itr != VtkDefinitions::KratosVtkGeometryTypes.end()) { - *(data_itr + Index) = p_itr->second; + *(span.begin() + Index) = static_cast(p_itr->second); } else { - KRATOS_ERROR << "Element with id " << (rContainer.begin() + Index)->Id() << " has unsupported geometry."; + ignored_indices[Index] = 1; + KRATOS_WARNING_IF("VtuOutput", EchoLevel > 1) + << "Skipping unsupported geometry type in " + << ModelPart::Container::GetEntityName() + << " with id " << (rContainer.begin() + Index)->Id() << ".\n"; } }); - return p_geometry_expression; + + // fill in the writing indices + rWritingIndices.reserve(rContainer.size()); + for (IndexType i = 0; i < rContainer.size(); ++i) { + if (ignored_indices[i] != 1) { + rWritingIndices.push_back(i); + } + } + + return p_geometry_types; +} + +template +NDData::Pointer GetOffsets( + const std::vector& rWritingIndices, + const TContainerType& rContainer) +{ + auto p_offsets = Kratos::make_shared>(DenseVector(1, rWritingIndices.size())); + auto data_itr = p_offsets->ViewData().begin(); + + int total_offset = 0; + for (IndexType i = 0; i < rWritingIndices.size(); ++i) { + total_offset += (rContainer.begin() + rWritingIndices[i])->GetGeometry().size(); + data_itr[i] = total_offset; + } + + return p_offsets; } template -Expression::Pointer CreateConnectivityExpression( - const LiteralFlatExpression::Pointer pOffsetsExpression, +NDData::Pointer GetConnectivities( + const NDData& rOffsets, const TContainerType& rContainer, - const std::unordered_map& rKratosVtuIndicesMap) + const std::unordered_map& rKratosVtuIndicesMap, + const std::vector& rWritingIndices) { - auto offset_data_itr = pOffsetsExpression->begin(); + if (rOffsets.Size() == 0) { + return Kratos::make_shared>(DenseVector(1, 0)); + } - auto p_connectivity_expression = LiteralFlatExpression::Create(*(offset_data_itr + rContainer.size() - 1), {}); - auto data_itr = p_connectivity_expression->begin(); + const auto offsets_span = rOffsets.ViewData(); + auto p_connectivities = Kratos::make_shared>(DenseVector(1, offsets_span.back())); + auto connectivities_span = p_connectivities->ViewData(); - IndexPartition(rContainer.size()).for_each([data_itr, offset_data_itr, &rContainer, &rKratosVtuIndicesMap](const IndexType Index) { - const auto& r_geometry = (rContainer.begin() + Index)->GetGeometry(); - auto entity_data_begin_itr = data_itr + *(offset_data_itr + Index) - r_geometry.size(); + IndexPartition(rWritingIndices.size()).for_each([&connectivities_span, &offsets_span, &rContainer, &rKratosVtuIndicesMap, &rWritingIndices](const IndexType Index) { + const auto& r_geometry = (rContainer.begin() + rWritingIndices[Index])->GetGeometry(); + auto entity_data_begin_itr = connectivities_span.begin() + offsets_span[Index] - r_geometry.size(); - for (const auto& r_node : r_geometry) { - const auto p_itr = rKratosVtuIndicesMap.find(r_node.Id()); + for (IndexType i_node = 0; i_node < r_geometry.size(); ++i_node) { + const auto p_itr = rKratosVtuIndicesMap.find(r_geometry[i_node].Id()); if (p_itr != rKratosVtuIndicesMap.end()) { - *(entity_data_begin_itr++) = p_itr->second; + entity_data_begin_itr[i_node] = p_itr->second; } else { - KRATOS_ERROR << "Node with id " << r_node.Id() << " not found in nodes list."; + KRATOS_ERROR << "Node with id " << r_geometry[i_node].Id() << " not found in nodes list."; } } }); - return p_connectivity_expression; + + return p_connectivities; } -template -XmlExpressionElement::Pointer CreateCellsXmlElement( - const TContainerType& rContainer, - const std::unordered_map& rKratosVtuIndicesMap) +template +void AddConnectivityData( + XmlElementsArray& rCellElement, + std::vector& rWritingIndices, + const ModelPart::NodesContainerType& rNodes, + VtuOutput::CellContainerPointerType pCells, + TXmlDataElementWrapper& rXmlDataElementWrapper, + const IndexType EchoLevel) { - auto p_cells_xml_element = Kratos::make_shared("Cells"); + std::visit([&rCellElement, &rXmlDataElementWrapper, &rWritingIndices, &rNodes, EchoLevel](auto p_container) { + std::unordered_map indices_map; + indices_map.reserve(rNodes.size()); + IndexType vtu_index = 0; + for (const auto& r_node : rNodes) { + indices_map[r_node.Id()] = vtu_index++; + } + + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting Vtk geometry type info...\n"; + auto p_type_data = GetGeometryTypes(rWritingIndices, *p_container, EchoLevel); + + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Ignored " << (p_container->size() - rWritingIndices.size()) << "/" + << p_container->size() << " " << GetEntityName(p_container) << "(s).\n"; - auto p_offsets_expression = CreateOffsetsExpression(rContainer); - auto p_connectivity_expression = CreateConnectivityExpression(p_offsets_expression, rContainer, rKratosVtuIndicesMap); - auto p_geometry_type_expression = CreateGeometryTypesExpression(rContainer); + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting geometry offsets info...\n"; + auto p_offsets = GetOffsets(rWritingIndices, *p_container); - AddDataArrayElement( - p_cells_xml_element, - CreateDataArrayElement("connectivity", {&*p_connectivity_expression})); - AddDataArrayElement(p_cells_xml_element, - CreateDataArrayElement("offsets", {&*p_offsets_expression})); - AddDataArrayElement(p_cells_xml_element, - CreateDataArrayElement("types", {&*p_geometry_type_expression})); - return p_cells_xml_element; + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting geometry connectivity info...\n"; + rCellElement.AddElement(rXmlDataElementWrapper.Get("connectivity", GetConnectivities(*p_offsets, *p_container, indices_map, rWritingIndices))); + rCellElement.AddElement(rXmlDataElementWrapper.Get("offsets", p_offsets)); + rCellElement.AddElement(rXmlDataElementWrapper.Get("types", GetWritingNDData(rWritingIndices, p_type_data))); + }, pCells); } -template -XmlExpressionElement::Pointer CreateVariableDataXmlElement( +template +void AddFieldsUsingTensorAdaptorImpl( + XmlElementsArray& rXmlElement, + TContainerPointerType pContainer, const Variable& rVariable, - ModelPart& rModelPart) + TXmlDataElementWrapper& rXmlDataElementWrapper, + const DataCommunicator& rDataCommunicator, + const std::vector& rWritingIndices, + const IndexType EchoLevel, + TArgs&&... rArgs) { - if constexpr(std::is_same_v) { - ContainerExpression local_container(rModelPart); - if constexpr(std::is_same_v) { - VariableExpressionIO::Read(local_container, &rVariable, true); + KRATOS_TRY + + + using primitive_data_type = typename DataTypeTraits::PrimitiveType; + + if constexpr(std::is_same_v) { + // we only support int variable, and there are no TensorAdaptors to + // collect data from integer variables, we do it manually here. + auto p_nd_data = Kratos::make_shared>(DenseVector(1, pContainer->size())); + const auto& shape = p_nd_data->Shape(); + if constexpr (std::is_same_v) { + ContainerIOUtils::CopyToContiguousArray( + *pContainer, p_nd_data->ViewData(), + shape.data().begin(), shape.data().begin() + 1, + [&rVariable](int& rValue, const Node& rNode) { + rValue = rNode.FastGetSolutionStepValue(rVariable); + }); + } else if constexpr(std::is_same_v) { + ContainerIOUtils::CopyToContiguousArray( + *pContainer, p_nd_data->ViewData(), + shape.data().begin(), shape.data().begin() + 1, + [&rVariable](int& rValue, const auto& rNode) { + rValue = rNode.GetValue(rVariable); + }); } else { - VariableExpressionIO::Read(local_container, &rVariable, false); + KRATOS_ERROR << "Unsupported tensor adaptor type."; } - if (rModelPart.GetCommunicator().GhostMesh().NumberOfNodes() > 0) { - ContainerExpression ghost_container(rModelPart); - if constexpr(std::is_same_v) { - VariableExpressionIO::Read(ghost_container, &rVariable, true); - } else { - VariableExpressionIO::Read(ghost_container, &rVariable, false); + // since we only support Variable, which is having a static data shape + // we don't have to do mpi communication to decide the shape on the + // empty ranks. + rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, p_nd_data))); + } else if constexpr(std::is_same_v) { + using data_type_traits = DataTypeTraits; + + if constexpr(data_type_traits::IsDynamic) { + // this is a dynamic type such as Vector or Matrix, so + // we need to do communication to decide the correct size + // because, there may be ranks with zero entities, hence these ranks will not have + // correctly sized dynamic Matrix or Vectors. Vtu needs all the ranks to have the same number + // of components, hence communication is a must in here. + + // construct the correct data_shape + std::vector data_shape(data_type_traits::Dimension, 0); + + if (!pContainer->empty()) { + // if the container is not empty. + TTensorAdaptorType tensor_adaptor(pContainer, &rVariable, rArgs...); + tensor_adaptor.CollectData(); + + const auto& ta_shape = tensor_adaptor.Shape(); + std::copy(ta_shape.begin() + 1, ta_shape.end(), data_shape.begin()); + + // create the xml element in ranks which do have entities. + rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); } - return CreateDataArrayElement( - rVariable.Name(), - {pGetExpression(local_container), pGetExpression(ghost_container)}); + // communicate to identify the correct data shape to be written down to ranks which + // do not have any entities. + const auto& max_data_shape = rDataCommunicator.MaxAll(data_shape); + + if (pContainer->empty()) { + // if the container is empty, now create an empty NDData with correct data shape. + DenseVector nd_shape(max_data_shape.size() + 1); + std::copy(max_data_shape.begin(), max_data_shape.end(), nd_shape.begin() + 1); + nd_shape[0] = pContainer->size(); + auto p_nd_data = Kratos::make_shared(nd_shape); + + // create the xml element in ranks which do not have any entities. + rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), p_nd_data)); + } } else { - return CreateDataArrayElement( - rVariable.Name(), - {pGetExpression(local_container)}); + // this is a static type such as double, array_1d, ... + // So no need of mpi communication + TTensorAdaptorType tensor_adaptor(pContainer, &rVariable, rArgs...); + tensor_adaptor.CollectData(); + rXmlElement.AddElement(rXmlDataElementWrapper.Get(rVariable.Name(), GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); } - } else { - ContainerExpression local_container(rModelPart); - VariableExpressionIO::Read(local_container, &rVariable); - - return CreateDataArrayElement(rVariable.Name(), {pGetExpression(local_container)}); + KRATOS_ERROR << "Unsupported variable type."; } + + KRATOS_CATCH(""); } -template -Expression::Pointer CreateContainerFlagExpression( - const TContainerType& rContainer, - const Flags& rFlag) +template +void AddFieldsUsingTensorAdaptor( + XmlElementsArray& rXmlElement, + TContainerPointerType pContainer, + const TMapType& rMap, + TXmlDataElementWrapper& rXmlDataElementWrapper, + const DataCommunicator& rDataCommunicator, + const std::vector& rWritingIndices, + const IndexType EchoLevel, + TArgs&&... rArgs) { - auto p_flag_expression = LiteralFlatExpression::Create(rContainer.size(), {}); - auto data_itr = p_flag_expression->begin(); - - IndexPartition(rContainer.size()).for_each([data_itr, &rContainer, &rFlag](const IndexType Index) { - *(data_itr + Index) = (rContainer.begin() + Index)->Is(rFlag); - }); + KRATOS_TRY + + for (const auto& r_pair : rMap) { + using data_type = BareType; + + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting " << r_pair.first << " data...\n"; + + if constexpr(std::is_same_v) { + if (r_pair.first == "KRATOS_ID") { + // this is specific to write KRATOS_IDS. + auto p_nd_data = Kratos::make_shared>(DenseVector(1, rWritingIndices.size())); + auto span = p_nd_data->ViewData(); + IndexPartition(rWritingIndices.size()).for_each([&pContainer, &span, &rWritingIndices](const auto Index) { + span[Index] = (pContainer->begin() + rWritingIndices[Index])->Id(); + }); + rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, p_nd_data)); + } else { + // the map is of type flags + // here we don't need to do any communication because Flags are always having a static data shape. + TTensorAdaptorType tensor_adaptor(pContainer, *r_pair.second, rArgs...); + tensor_adaptor.CollectData(); + rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, GetWritingNDData(rWritingIndices, tensor_adaptor.pGetStorage()))); + } + } else { + std::visit([&](const auto p_variable) { + AddFieldsUsingTensorAdaptorImpl( + rXmlElement, pContainer, *p_variable, rXmlDataElementWrapper, + rDataCommunicator, rWritingIndices, EchoLevel, rArgs...); + }, r_pair.second); + } + } - return p_flag_expression; + KRATOS_CATCH(""); } -template -XmlExpressionElement::Pointer CreateFlagDataXmlElement( - const std::string& rFlagName, - const Flags& rFlags, - const ModelPart& rModelPart) -{ - if constexpr(std::is_same_v) { - const auto& r_communicator = rModelPart.GetCommunicator(); - const auto& r_local_nodes = r_communicator.LocalMesh().Nodes(); - const auto& r_ghost_nodes = r_communicator.GhostMesh().Nodes(); - - return CreateDataArrayElement( - rFlagName, - {&*CreateContainerFlagExpression(r_local_nodes, rFlags), - &*CreateContainerFlagExpression(r_ghost_nodes, rFlags)}); - } else if constexpr(std::is_same_v) { - return CreateDataArrayElement( - rFlagName, - {&*CreateContainerFlagExpression(rModelPart.GetCommunicator().LocalMesh().Conditions(), rFlags)}); - } else if constexpr(std::is_same_v) { - return CreateDataArrayElement( - rFlagName, - {&*CreateContainerFlagExpression(rModelPart.GetCommunicator().LocalMesh().Elements(), rFlags)}); - } -} - -Expression::Pointer CreateGhostNodeExpression( +template +void AddFields( + XmlElementsArray& rXmlElement, + const std::map& rMap, + TXmlDataElementWrapper& rXmlDataElementWrapper, + const std::vector& rWritingIndices, const DataCommunicator& rDataCommunicator, - const Expression& rLocalNodesExpression, - const ModelPart::NodesContainerType& rLocalNodes, - const ModelPart::NodesContainerType& rGhostNodes, - const std::unordered_map& rKratosVtuIndicesMap) + const IndexType EchoLevel) { - const IndexType number_of_ghost_nodes = rGhostNodes.size(); - - std::vector ghost_indices(number_of_ghost_nodes); - std::transform(rGhostNodes.begin(), rGhostNodes.end(), ghost_indices.begin(), [](const auto& rNode) { return rNode.Id(); }); - auto gp_list = GlobalPointerUtilities::RetrieveGlobalIndexedPointers(rLocalNodes, ghost_indices, rDataCommunicator); - - GlobalPointerCommunicator pointer_comm(rDataCommunicator, gp_list.ptr_begin(), gp_list.ptr_end()); + for (const auto& r_pair : rMap) { + KRATOS_INFO_IF("VtuOutput", EchoLevel > 2) << "------ Collecting " << r_pair.first << " data...\n"; + + std::visit([&rXmlElement, &r_pair, &rXmlDataElementWrapper, &rWritingIndices, &rDataCommunicator](auto pTensorAdaptor) { + // here we need to make sure all the tensor adaptors from every rank has the same data shape, even + // from the ranks which do not have any entities. Therefore following check is done with mpi communication + + // all the ranks should have the same number of dimensions, because number of dimensions should not depend + // on whether the rank is empty or not. + const auto& ta_shape = pTensorAdaptor->Shape(); + const auto max_number_of_dimensions = rDataCommunicator.MaxAll(static_cast(ta_shape.size())); + + KRATOS_ERROR_IF_NOT(max_number_of_dimensions == ta_shape.size()) + << "The number of dimensions represented by \"" << r_pair.first << "\" tensor adaptor is different in different ranks [ max number of dimensions from all ranks = " + << max_number_of_dimensions << ", tensor adaptor = " << *pTensorAdaptor << " ].\n"; + + // since all ranks have same number of dimensions, now we can check if the tensor adaptors have the correct sizes. + // in here we check the followings + // - each rank which does not have emtpy containers (ta_shape[0] != 0) should have same number of components in the data shape. + // - ranks which do have empty containers (ta_shape[0] == 0) should have either same number of components as in the ranks which have non empty + // containers or 0. + + std::vector communicated_shape(ta_shape.begin(), ta_shape.end()); + auto all_ta_shapes = rDataCommunicator.AllGatherv(communicated_shape); + + // find a data shape from some rank which has non-empty container + DenseVector ref_ta_shape(max_number_of_dimensions, 0); + for (const auto& rank_shape : all_ta_shapes) { + if (rank_shape[0] != 0) { + std::copy(rank_shape.begin() + 1, rank_shape.end(), ref_ta_shape.begin() + 1); + break; + } + } - const IndexType number_of_components = rLocalNodesExpression.GetItemComponentCount(); + for (IndexType i_rank = 0; i_rank < all_ta_shapes.size(); ++i_rank) { + auto& rank_shape = all_ta_shapes[i_rank]; + + // modify the rank shape if it is coming from a rank having an empty container. + if (rank_shape[0] == 0) { + // this is a rank with an empty container. + for (IndexType i_dim = 1; i_dim < ref_ta_shape.size(); ++i_dim) { + // modify only if the number of components in the higher dimensions are zero. + if (rank_shape[i_dim] == 0) { + rank_shape[i_dim] = ref_ta_shape[i_dim]; + } + } + } - auto values_proxy = pointer_comm.Apply( - [&rLocalNodesExpression, number_of_components, &rKratosVtuIndicesMap](GlobalPointer& rGP) -> std::vector { - std::vector values(number_of_components); - const auto p_itr = rKratosVtuIndicesMap.find(rGP->Id()); - if (p_itr != rKratosVtuIndicesMap.end()) { - const IndexType enitity_data_begin_index = p_itr->second * number_of_components; - for (IndexType i = 0; i < number_of_components; ++i) { - values[i] = rLocalNodesExpression.Evaluate(p_itr->second, enitity_data_begin_index, i); + // now we check in all ranks whether the data shape is equal + for (IndexType i_dim = 1; i_dim < ref_ta_shape.size(); ++i_dim) { + KRATOS_ERROR_IF_NOT(rank_shape[i_dim] == ref_ta_shape[i_dim]) + << "All ranks should have same number of components in the shape dimensions except for the first dimension. If the rank is empty," + << " then that rank should have zeros for all shape dimensions or correct number of components in the dimensions as in the ranks with" + << " non-empty containers [ mismatching shape rank = " << i_rank << ", mismatching tensor adaptor shape = " << rank_shape + << ", ref tensor adaptor shape from other ranks = " << ref_ta_shape << ", tensor adaptor name = " << r_pair.first + << ", tensor adaptor = " << *pTensorAdaptor << " ].\n"; } - } else { - KRATOS_ERROR << "The node with id " << rGP->Id() << " not found in the owning rank local expression."; } - return values; - } - ); - auto p_ghost_nodes_expression = LiteralFlatExpression::Create(number_of_ghost_nodes, rLocalNodesExpression.GetItemShape()); - auto data_itr = p_ghost_nodes_expression->begin(); + if (ta_shape[0] == 0) { + // get the storage type of the tensor adaptor. This may be NDData, NDData, ... + using TDataType = typename BareType::Storage; + // this is a rank with an empty container. + rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, Kratos::make_shared(ref_ta_shape))); + } else { + // this is a rank with non-empty container. + rXmlElement.AddElement(rXmlDataElementWrapper.Get(r_pair.first, GetWritingNDData(rWritingIndices, pTensorAdaptor->pGetStorage()))); + } - for(IndexType i = 0; i < number_of_ghost_nodes; ++i) { - const auto& r_gp_value = values_proxy.Get(gp_list(i)); - for (IndexType j = 0; j < number_of_components; ++j) { - *(data_itr++) = r_gp_value[j]; - } + }, r_pair.second); } - return p_ghost_nodes_expression; } -template -XmlExpressionElement::Pointer CreateContainerExpressionXmlElement( - const std::string& rExpressionName, - const ContainerExpression& rContainerExpression, - const std::unordered_map& rKratosVtuIndicesMap) -{ - if constexpr(std::is_same_v) { - const auto& r_communicator = rContainerExpression.GetModelPart().GetCommunicator(); - const auto& r_local_nodes = r_communicator.LocalMesh().Nodes(); - const auto& r_ghost_nodes = r_communicator.GhostMesh().Nodes(); - - auto ghost_node_expression = CreateGhostNodeExpression( - r_communicator.GetDataCommunicator(), rContainerExpression.GetExpression(), - r_local_nodes, r_ghost_nodes, rKratosVtuIndicesMap); - - return CreateDataArrayElement( - rExpressionName, {pGetExpression(rContainerExpression), &*ghost_node_expression}); - } else { - return CreateDataArrayElement(rExpressionName, - {pGetExpression(rContainerExpression)}); +template +ModelPart::NodesContainerType::Pointer GetNodesContainer(TEntityContainerType& rContainer) +{ + std::vector temp_nodes; + temp_nodes.reserve(rContainer.size() * 20); + for (auto& r_entity : rContainer) { + auto& r_geometry = r_entity.GetGeometry(); + for (auto p_itr = r_geometry.ptr_begin(); p_itr != r_geometry.ptr_end(); ++p_itr) { + temp_nodes.push_back(*p_itr); + } } -} -template -void CheckDataArrayName( - const std::string& rName, - TLists&... rLists) -{ - const bool found_existing_name = !(... && (rLists.find(rName) == rLists.end())); - KRATOS_ERROR_IF(found_existing_name) - << "Found an existing data array with the same name = \"" << rName << "\".\n"; + auto p_nodes_container = Kratos::make_shared(); + p_nodes_container->insert(temp_nodes.begin(), temp_nodes.end()); + return p_nodes_container; } -template -void AddListOfVariables( - XmlExpressionElement::Pointer pXmlDataElement, +void AddUnstructuredGridData( + std::vector& rOutput, ModelPart& rModelPart, - const std::map& rVariablesMap) + const IndexType EchoLevel, + const bool UseSubModelParts) { - for (const auto& p_variable_variant : rVariablesMap){ - std::visit([&rModelPart, &pXmlDataElement](auto pVariable) { - using variable_type = - typename std::remove_const_t>::Type; - AddDataArrayElement( - pXmlDataElement, - CreateVariableDataXmlElement( - *pVariable, rModelPart)); - }, - p_variable_variant.second); + const std::vector entity_availability{rModelPart.NumberOfNodes() > 0, rModelPart.NumberOfConditions() > 0, rModelPart.NumberOfElements() > 0}; + const auto& max_entity_availability = rModelPart.GetRootModelPart().GetCommunicator().GetDataCommunicator().MaxAll(entity_availability); + const bool has_nodes = max_entity_availability[0]; + const bool has_conditions = max_entity_availability[1]; + const bool has_elements = max_entity_availability[2]; + + if (has_elements) { + // Model part has elements. Hence add a separate output + // for elements. + + // now check if it has proper nodes + if (has_nodes) { + KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) + << "Configuring output for \"" << rModelPart.FullName() << "\" elements with existing nodes container.\n"; + VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), rModelPart.pElements()}; + rOutput.push_back(model_part_data); + } else { + // create the nodes container. + KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) + << "Configuring output for \"" << rModelPart.FullName() << "\" elements with new nodes container.\n"; + auto p_nodes = GetNodesContainer(rModelPart.Elements()); + VtuOutput::UnstructuredGridData model_part_data{false, &rModelPart, p_nodes, rModelPart.pElements()}; + rOutput.push_back(model_part_data); + } } -} -template -void AddListOfFlags( - XmlExpressionElement::Pointer pXmlDataElement, - ModelPart& rModelPart, - const std::map& rFlagsMap) -{ - for (const auto& r_flag_pair : rFlagsMap){ - AddDataArrayElement(pXmlDataElement, CreateFlagDataXmlElement(r_flag_pair.first, *r_flag_pair.second, rModelPart)); - } -} + if (has_conditions) { + // Model part has conditions. Hence add a separate output + // for conditions. -template -void AddListOfContainerExpressions( - XmlExpressionElement::Pointer pXmlDataElement, - ModelPart& rModelPart, - const std::unordered_map& rKratosVtuIndicesMap, - const std::map& rContainerExpressionsMap) -{ - for (const auto& r_container_expression_pair : rContainerExpressionsMap){ - const std::string& r_name = r_container_expression_pair.first; - if constexpr(std::is_same_v::Pointer>) { - AddDataArrayElement( - pXmlDataElement, - CreateContainerExpressionXmlElement( - r_name, - *r_container_expression_pair.second, rKratosVtuIndicesMap)); + if (!has_elements && has_nodes) { + KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) + << "Configuring output for \"" << rModelPart.FullName() << "\" conditions with existing nodes container.\n"; + VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), rModelPart.pConditions()}; + rOutput.push_back(model_part_data); } else { - std::visit([&r_name, &pXmlDataElement, &rKratosVtuIndicesMap](auto pContainerExpression) { - AddDataArrayElement( - pXmlDataElement, - CreateContainerExpressionXmlElement( - r_name, *pContainerExpression, rKratosVtuIndicesMap)); - }, - r_container_expression_pair.second); + // either this model part also contains elements, or it does not + // contain nodes. In either case, the nodes list given by the rModelPart + // does not reflect the actual nodes used by the conditions. + // In order to avoid writing nodes, which are not used by the conditions, + // this will use a new nodes list. + + KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) + << "Configuring output for \"" << rModelPart.FullName() << "\" conditions with new nodes container.\n"; + + auto p_nodes = GetNodesContainer(rModelPart.Conditions()); + VtuOutput::UnstructuredGridData model_part_data{false, &rModelPart, p_nodes, rModelPart.pConditions()}; + rOutput.push_back(model_part_data); } } -} -void CopyAttributes( - XmlExpressionElement& rOutputElement, - const XmlExpressionElement& rInputElement) -{ - for (const auto& r_attribute_data : rInputElement.GetAttributes()) { - rOutputElement.AddAttribute(r_attribute_data.first, r_attribute_data.second); + if (!has_elements && !has_conditions) { + KRATOS_INFO_IF("VtuOutput", EchoLevel > 0) + << "Configuring output for \"" << rModelPart.FullName() << "\" nodes.\n"; + // Model part does not have either conditions or elements. + // Hence, only adding the nodes. + VtuOutput::UnstructuredGridData model_part_data{true, &rModelPart, rModelPart.pNodes(), std::nullopt}; + rOutput.push_back(model_part_data); } -} -void CreatePDataArrays( - XmlExpressionElement& rOutputElement, - const XmlExpressionElement& rInputElement) -{ - for (const auto& p_element : rInputElement.GetElements()) { - auto new_pdata_array = Kratos::make_shared("PDataArray"); - CopyAttributes(*new_pdata_array, *p_element); - rOutputElement.AddElement(new_pdata_array); + if (UseSubModelParts) { + // now recursively add all the sub model part data. + for (auto& r_sub_model_part : rModelPart.SubModelParts()) { + AddUnstructuredGridData(rOutput, r_sub_model_part, EchoLevel, UseSubModelParts); + } } } -std::string GetEndianness() +template +const typename VtuOutput::DataList::value_type& GetContainerMap( + const VtuOutput::DataList& rList, + TCellPointerType pCellPointer) { - int i = 0x0001; - - if (*reinterpret_cast(&i) != 0) { - return "LittleEndian"; - } else { - return "BigEndian"; - } + return std::visit([&rList](auto pContainer) -> const typename VtuOutput::DataList::value_type& { + using container_type = BareType; + if constexpr(std::is_same_v) { + return rList[static_cast(Globals::DataLocation::Condition)]; + } else if constexpr(std::is_same_v) { + return rList[static_cast(Globals::DataLocation::Element)]; + } else { + KRATOS_ERROR << "Unsupported container type."; + return rList[static_cast(Globals::DataLocation::Element)]; + } + }, pCellPointer); } -void WritePvtuFile( - XmlExpressionElement::Pointer pVtkFileElement, - const ModelPart& rModelPart, - const std::string& rOutputFileNamePrefix, - const std::string& rOutputFileName) +std::string WritePartitionedUnstructuredGridData( + XmlElementsArray& rPointDataElement, + XmlElementsArray& rCellDataElement, + const std::string& rOutputVtuFileName, + const DataCommunicator& rDataCommunicator) { - // get list of file names - std::stringstream list_of_file_names; + const int writing_rank = 0; - const auto& r_communicator = rModelPart.GetCommunicator(); - const auto& r_data_communicator = r_communicator.GetDataCommunicator(); + // remove the rank from the rOutputVtuFileName. + const auto& r_base_name = rOutputVtuFileName.substr(0, rOutputVtuFileName.rfind("_")); - // TODO: May be we want to check a rank which has some entities (not empty ranks) - // Then write on that rank. - const int writing_rank = 0; + const auto& p_vtu_file_name = r_base_name + ".pvtu"; - list_of_file_names << rOutputFileName << "\n"; - if (r_data_communicator.Rank() == writing_rank) { - for (int rank = 0; rank < r_data_communicator.Size(); ++rank) { - if (rank != writing_rank) { - std::string msg; - r_data_communicator.Recv(msg, rank); - list_of_file_names << msg; - } + if (rDataCommunicator.Rank() == writing_rank) { + // create the pvtu file + XmlElementsArray p_vtu_file_element("VTKFile"); + p_vtu_file_element.AddAttribute("type", "PUnstructuredGrid"); + p_vtu_file_element.AddAttribute("version", "0.1"); + p_vtu_file_element.AddAttribute("byte_order", GetEndianness()); + + // create the unstructured grid + auto p_unstructured_grid_element = Kratos::make_shared("PUnstructuredGrid"); + p_unstructured_grid_element->AddAttribute("GhostLevel", "0"); + p_vtu_file_element.AddElement(p_unstructured_grid_element); + + // ppoints_element + auto p_points_element = Kratos::make_shared("PPoints"); + p_unstructured_grid_element->AddElement(p_points_element); + + // position element + auto p_position_element = Kratos::make_shared("PDataArray"); + p_position_element->AddAttribute("type", "Float64"); + p_position_element->AddAttribute("Name", "Position"); + p_position_element->AddAttribute("NumberOfComponents", "3"); + p_points_element->AddElement(p_position_element); + + // pcells element + auto p_cells_element = Kratos::make_shared("PCells"); + p_unstructured_grid_element->AddElement(p_cells_element); + + // connectivity element + auto p_connectivity_element = Kratos::make_shared("PDataArray"); + p_connectivity_element->AddAttribute("type", "Int32"); + p_connectivity_element->AddAttribute("Name", "connectivity"); + p_connectivity_element->AddAttribute("NumberOfComponents", "1"); + p_cells_element->AddElement(p_connectivity_element); + + // offsets element + auto p_offsets_element = Kratos::make_shared("PDataArray"); + p_offsets_element->AddAttribute("type", "Int32"); + p_offsets_element->AddAttribute("Name", "offsets"); + p_offsets_element->AddAttribute("NumberOfComponents", "1"); + p_cells_element->AddElement(p_offsets_element); + + // types element + auto p_types_element = Kratos::make_shared("PDataArray"); + p_types_element->AddAttribute("type", "UInt8"); + p_types_element->AddAttribute("Name", "types"); + p_types_element->AddAttribute("NumberOfComponents", "1"); + p_cells_element->AddElement(p_types_element); + + // ppoint data element + auto p_point_data_element = Kratos::make_shared("PPointData"); + p_unstructured_grid_element->AddElement(p_point_data_element); + + // now add the point data fields + for (const auto& p_element : rPointDataElement.GetElements()) { + auto p_current_element = Kratos::make_shared("PDataArray"); + CopyAttributes(*p_element, *p_current_element); + p_point_data_element->AddElement(p_current_element); } - } else { - r_data_communicator.Send(list_of_file_names.str(), writing_rank); - } - r_data_communicator.Barrier(); - if (r_data_communicator.Rank() == writing_rank) { - // create the vtk file - auto vtk_file_element = Kratos::make_shared("VTKFile"); - vtk_file_element->AddAttribute("type", "PUnstructuredGrid"); - vtk_file_element->AddAttribute("version", "0.1"); - vtk_file_element->AddAttribute("byte_order", GetEndianness()); + // pcell data element + auto p_cell_data_element = Kratos::make_shared("PCellData"); + p_unstructured_grid_element->AddElement(p_cell_data_element); - // create the unstructured grid - auto unstructured_grid_element = Kratos::make_shared("PUnstructuredGrid"); - unstructured_grid_element->AddAttribute("GhostLevel", "0"); - vtk_file_element->AddElement(unstructured_grid_element); - - // get the points xml element - auto piece = pVtkFileElement->GetElements("UnstructuredGrid")[0]->GetElements("Piece")[0]; - - auto points = piece->GetElements("Points")[0]; - auto p_points = Kratos::make_shared("PPoints"); - VtuOutputHelperUtilities::CreatePDataArrays(*p_points, *points); - unstructured_grid_element->AddElement(p_points); - - auto cells = piece->GetElements("Cells")[0]; - auto p_cells = Kratos::make_shared("PCells"); - VtuOutputHelperUtilities::CreatePDataArrays(*p_cells, *cells); - unstructured_grid_element->AddElement(p_cells); - - auto point_data = piece->GetElements("PointData")[0]; - auto p_point_data = Kratos::make_shared("PPointData"); - VtuOutputHelperUtilities::CreatePDataArrays(*p_point_data, *point_data); - unstructured_grid_element->AddElement(p_point_data); - - auto cell_data = piece->GetElements("CellData")[0]; - auto p_cell_data = Kratos::make_shared("PCellData"); - VtuOutputHelperUtilities::CreatePDataArrays(*p_cell_data, *cell_data); - unstructured_grid_element->AddElement(p_cell_data); - - // now write all the pieces - const auto& r_file_names = StringUtilities::SplitStringByDelimiter(list_of_file_names.str(), '\n'); - for (const auto& r_file_name : r_file_names) { - auto piece = Kratos::make_shared("Piece"); - piece->AddAttribute("Source", r_file_name); - unstructured_grid_element->AddElement(piece); + // now add the cell data fields + for (const auto& p_element : rCellDataElement.GetElements()) { + auto p_current_element = Kratos::make_shared("PDataArray"); + CopyAttributes(*p_element, *p_current_element); + p_cell_data_element->AddElement(p_current_element); + } + + // now add the piece elements + for (int i_rank = 0; i_rank < rDataCommunicator.Size(); ++i_rank) { + const auto& r_file_name = r_base_name + "_" + std::to_string(i_rank) + ".vtu"; + auto piece = Kratos::make_shared("Piece"); + // since we are writing to the same folder the pvtu files + piece->AddAttribute( + "Source", std::filesystem::relative( + std::filesystem::absolute(r_file_name), + std::filesystem::absolute(p_vtu_file_name).parent_path()) + .generic_string()); + p_unstructured_grid_element->AddElement(piece); } // writing to file - std::stringstream output_pvtu_file_name; - output_pvtu_file_name << rOutputFileNamePrefix << ".pvtu"; std::ofstream output_file; - output_file.open(output_pvtu_file_name.str(), std::ios::out | std::ios::trunc); - XmlOStreamAsciiWriter writer(output_file, 1); - writer.WriteElement(*vtk_file_element); - output_file.close(); + output_file.open(p_vtu_file_name, std::ios::out | std::ios::trunc); + output_file << "" << std::endl; + p_vtu_file_element.Write(output_file); + + } + + return p_vtu_file_name; +} + +template +void PrintLocationData( + std::ostream& rOStream, + const std::string& rMapType, + const VtuOutput::DataList& rList) +{ + rOStream << "List of " << rMapType << "s:"; + for (IndexType i = 0; i < rList.size(); ++i) { + switch (i) { + case static_cast(Globals::DataLocation::NodeHistorical): + rOStream << "\n\tNode historical " << rMapType << "s:"; + break; + case static_cast(Globals::DataLocation::NodeNonHistorical): + rOStream << "\n\tNode " << rMapType << "s:"; + break; + case static_cast(Globals::DataLocation::Condition): + rOStream << "\n\tCondition " << rMapType << "s:"; + break; + case static_cast(Globals::DataLocation::Element): + rOStream << "\n\tElement " << rMapType << "s:"; + break; + default: + break; + } + + for ([[maybe_unused]]const auto& [name, variable] : rList[i]) { + rOStream << "\n\t\t" << name; + } + } +} + +template +std::pair::iterator> FindUnstructuredGridData( + const TContainerType& rContainer, + std::vector& rUnstructuredGridDataList) +{ + for (auto itr = rUnstructuredGridDataList.begin(); itr != rUnstructuredGridDataList.end(); ++itr) { + auto p_model_part = itr->mpModelPart; + if constexpr(std::is_same_v) { + if (itr->UsePointsForDataFieldOutput) { + if ( + &rContainer == &p_model_part->Nodes() || + (!p_model_part->IsDistributed() && &rContainer == &p_model_part->GetCommunicator().LocalMesh().Nodes()) + ) { + return std::make_pair(Globals::DataLocation::NodeNonHistorical, itr); + } + } + } else if constexpr(std::is_same_v) { + // since Kratos is doing partitioning based on elements, and there are no conditions + // on the ghost meshes. so normal mesh and the local mesh should be having identical entities. + if (itr->mpCells.has_value() && + std::holds_alternative(itr->mpCells.value()) && + ( + &rContainer == &*std::get(itr->mpCells.value()) || + &rContainer == &p_model_part->GetCommunicator().LocalMesh().Conditions() + ) + ) { + return std::make_pair(Globals::DataLocation::Condition, itr); + } + } else if constexpr(std::is_same_v) { + // since Kratos is doing partitioning based on elements, and there are no elements + // on the ghost meshes. so normal mesh and the local mesh should be having identical entities. + if (itr->mpCells.has_value() && + std::holds_alternative(itr->mpCells.value()) && + ( + &rContainer == &*std::get(itr->mpCells.value()) || + &rContainer == &p_model_part->GetCommunicator().LocalMesh().Elements() + ) + ) { + return std::make_pair(Globals::DataLocation::Element, itr); + } + } else { + KRATOS_ERROR << "Unsupported container type."; + } } + + return std::make_pair(Globals::DataLocation::ModelPart, rUnstructuredGridDataList.end()); } -}; // namespace VtuOutputHelperUtilities +} // namespace VtuOutput::VtuOutput( ModelPart& rModelPart, const bool IsInitialConfiguration, const WriterFormat OutputFormat, - const IndexType Precision) - : mrModelPart(rModelPart), - mIsInitialConfiguration(IsInitialConfiguration), + const IndexType Precision, + const bool OutputSubModelParts, + const bool WriteIds, + const IndexType EchoLevel) + : mIsPVDFileHeaderWritten(false), + mrModelPart(rModelPart), + mConfiguration(IsInitialConfiguration ? Globals::Configuration::Initial : Globals::Configuration::Current), + mEchoLevel(EchoLevel), mOutputFormat(OutputFormat), mPrecision(Precision) { - const auto& r_communicator = rModelPart.GetCommunicator(); + AddUnstructuredGridData(mUnstructuredGridDataList, rModelPart, mEchoLevel, OutputSubModelParts); + + // sort the order of output to be consistent between different compilers + std::sort(mUnstructuredGridDataList.begin(), mUnstructuredGridDataList.end(), + [](const auto& rV1, const auto& rV2) { + return rV1.mpModelPart->FullName() < rV2.mpModelPart->FullName(); + }); + + if (WriteIds) { + // Adds a dummy place holder called "KRATOS_ID" to every container type + // so the user is prohibited from adding any tensor adaptors + // with the name KRATOS_ID in future. This will be treated + // separately, hence the use of nullptr. + mFlags[static_cast(Globals::DataLocation::NodeNonHistorical)]["KRATOS_ID"] = nullptr; + mFlags[static_cast(Globals::DataLocation::Condition)]["KRATOS_ID"] = nullptr; + mFlags[static_cast(Globals::DataLocation::Element)]["KRATOS_ID"] = nullptr; + } +} - mIsConditionsConsidered = r_communicator.GlobalNumberOfConditions() > 0; - mIsElementsConsidered = r_communicator.GlobalNumberOfElements() > 0; +const ModelPart& VtuOutput::GetModelPart() const +{ + return mrModelPart; +} - KRATOS_WARNING_IF("VtuOutput", mIsElementsConsidered && mIsConditionsConsidered) - << "Conditions and Elements vtu output chosen for " << mrModelPart.FullName() - << " which is not supported. Giving priority to elements.\n"; +std::vector VtuOutput::GetOutputContainerList() const +{ + std::vector result; + for (const auto& r_unstructured_grid : mUnstructuredGridDataList) { + if (r_unstructured_grid.UsePointsForDataFieldOutput) { + result.push_back(r_unstructured_grid.mpPoints); + + if (!r_unstructured_grid.mpModelPart->GetRootModelPart().IsDistributed()) { + // since local mesh and the mesh are the same in the case of non-distributed + // run. + result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pNodes()); + } + } - mIsConditionsConsidered = mIsElementsConsidered ? false : mIsConditionsConsidered; + if (r_unstructured_grid.mpCells.has_value()) { + std::visit([&result, &r_unstructured_grid](auto p_cells) { + result.push_back(p_cells); - if (mIsConditionsConsidered || mIsElementsConsidered) { - // we first always use the local mesh - IndexType vtu_index = 0; - for (const auto& r_node : mrModelPart.GetCommunicator().LocalMesh().Nodes()) { - mKratosVtuIndicesMap[r_node.Id()] = vtu_index++; + // since local mesh and the mesh are the same. + using container_type = BareType; + if constexpr(std::is_same_v) { + result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pConditions()); + } else if constexpr(std::is_same_v) { + result.push_back(r_unstructured_grid.mpModelPart->GetCommunicator().LocalMesh().pElements()); + } + }, r_unstructured_grid.mpCells.value()); } + } + return result; +} - // then we add the ghost mesh - for (const auto& r_node : mrModelPart.GetCommunicator().GhostMesh().Nodes()) { - mKratosVtuIndicesMap[r_node.Id()] = vtu_index++; - } +void VtuOutput::AddFlag( + const std::string& rFlagName, + const Flags& rFlagVariable, + const Globals::DataLocation& DataLocation) +{ + KRATOS_TRY + + KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) + << "Flags can be added only before the first call to the PrintOutput [ flag name = " + << rFlagName << " ].\n"; + + switch (DataLocation) { + case Globals::DataLocation::NodeNonHistorical: + // user is trying to add a flag to nodes. now we are checking + // whether there are variables with the same name in the variables + // from the nodal historical. + // note: there is no break here. + CheckDataArrayName(rFlagName, Globals::DataLocation::NodeHistorical, mFlags); + CheckDataArrayName(rFlagName, Globals::DataLocation::NodeHistorical, mVariables); + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: + // The following code block will be executed for Globals::DataLocation::NodeHistorical, Globals::DataLocation::Condition, and Globals::DataLocation::Element. + + // user is trying to add a flag variable to nodes, conditions or elements. + // here we check if the given flag name is there in the existing flags for user specified data location, + // and also in the variables. + CheckDataArrayName(rFlagName, DataLocation, mFlags); + CheckDataArrayName(rFlagName, DataLocation, mVariables); + + // since specified flags are used to output in every unstructured grid. We check here whether + // any of the tensor adaptors in the given data location contains the same name as rFlagName. + CheckDataArrayName(rFlagName, DataLocation, mUnstructuredGridDataList); + + // If there are no conflicts, we add the flag variable. + mFlags[static_cast(DataLocation)][rFlagName] = &rFlagVariable; + break; + default: + KRATOS_ERROR << "Flags can be only added to NodeNonHistorical, Condition, and Element data locations."; + break; } + + KRATOS_CATCH(""); } template -void VtuOutput::AddHistoricalVariable(const Variable& rVariable) +void VtuOutput::AddVariable( + const Variable& rVariable, + const Globals::DataLocation& DataLocation) { - VtuOutputHelperUtilities::CheckDataArrayName( - rVariable.Name(), mNonHistoricalNodalVariablesMap, mNodalFlagsMap, mPointContainerExpressionsMap); - mHistoricalVariablesMap[rVariable.Name()] = &rVariable; + KRATOS_TRY + + KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) + << "Variables can be added only before the first call to the PrintOutput [ variable name = " + << rVariable.Name() << " ].\n"; + + switch (DataLocation) { + case Globals::DataLocation::NodeHistorical: + // Now the user is adding a nodal historical variable. So, this checks whether + // the a variable with the same name exists in the nodal non-historical variables map. + // note: there is no break in here. + CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeNonHistorical, mFlags); + CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeNonHistorical, mVariables); + case Globals::DataLocation::NodeNonHistorical: + // Now the user is adding a nodal non-historical variable. So this checks whether + // a variable with the same name exists in the nodal historical variables map. + // not: there is no break in here. + CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeHistorical, mFlags); + CheckDataArrayName(rVariable.Name(), Globals::DataLocation::NodeHistorical, mVariables); + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: + // The following code block will be executed for Globals::DataLocation::NodeHistorical, Globals::DataLocation::NodeNonHistorical, Globals::DataLocation::Condition, and Globals::DataLocation::Element. + + // Now the user is trying to add a nodal-historical, nodal-non-historical, element or condition variable. + // so now we check whether another variable with the same name exists + // in the user specified container in flags and variables maps. + CheckDataArrayName(rVariable.Name(), DataLocation, mFlags); + CheckDataArrayName(rVariable.Name(), DataLocation, mVariables); + + // this checks whether there is already a tensor adaptor added with a name equal to the variable name + // in any of the unstructured grids. Since these variables will be used to output data in all the unstructured grids, + // non-of them should have any tensor adaptors with this name. + CheckDataArrayName(rVariable.Name(), DataLocation, mUnstructuredGridDataList); // checks in the tensor adaptors list + + // if there are no conflicts, adding the variable. + mVariables[static_cast(DataLocation)][rVariable.Name()] = &rVariable; + break; + default: + KRATOS_ERROR << "Variables can be only added to NodeHistorical, NodeNonHistorical, Condition, and Element data locations."; + break; + } + + KRATOS_CATCH(""); } template -void VtuOutput::AddNonHistoricalVariable( +void VtuOutput::AddIntegrationPointVariable( const Variable& rVariable, - const Flags& rEntityFlags) + const Globals::DataLocation& DataLocation) { - if (rEntityFlags.Is(NODES)) { - VtuOutputHelperUtilities::CheckDataArrayName( - rVariable.Name(), mHistoricalVariablesMap, mNodalFlagsMap, - mPointContainerExpressionsMap); - mNonHistoricalNodalVariablesMap[rVariable.Name()] = &rVariable; - } else { - KRATOS_ERROR_IF_NOT(!rEntityFlags.Is(CONDITIONS) || (rEntityFlags.Is(CONDITIONS) && mIsConditionsConsidered)) - << "Condition variable \"" - << rVariable.Name() << "\" cannot be written for a model part with elements [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; + KRATOS_TRY + + KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) + << "Integration point variables can be added only before the first call to the PrintOutput [ integration point variable name = " + << rVariable.Name() << " ].\n"; + + switch (DataLocation) { + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: + // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. + + // checks if the integration point variable name already exists on the + // list of integration point variables. + CheckDataArrayName(rVariable.Name(), DataLocation, mIntegrationPointVariables); + + // If no conflicts in the naming is found, then put integration point variable for the output. + mIntegrationPointVariables[static_cast(DataLocation)][rVariable.Name()] = &rVariable; + break; + default: + KRATOS_ERROR << "Integration point variables can be only added to Condition, and Element data locations."; + break; + } - KRATOS_ERROR_IF_NOT(!rEntityFlags.Is(ELEMENTS) || (rEntityFlags.Is(ELEMENTS) && mIsElementsConsidered)) - << "Element variable \"" - << rVariable.Name() << "\" cannot be written for a model part with only conditions [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; + KRATOS_CATCH(""); +} - VtuOutputHelperUtilities::CheckDataArrayName( - rVariable.Name(), mCellFlagsMap, mCellContainerExpressionsMap); - mNonHistoricalCellVariablesMap[rVariable.Name()] = &rVariable; - } +template +void VtuOutput::AddTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor) +{ + KRATOS_TRY + + KRATOS_ERROR_IF(mIsPVDFileHeaderWritten) + << "TensorAdaptors can be added only before the first call to the PrintOutput [ tensor adaptor name = " + << rTensorAdaptorName << " ].\n"; + + // a visitor for NodesContainer::Pointer, ConditionsContainer::Pointer, ElementsContainerPointer + // of the given pTensorAdaptor + std::visit([this, &rTensorAdaptorName, &pTensorAdaptor](auto pContainer){ + // finds the unstructured grid for which the given tensor adaptor's pContainer refers to. + // mesh_type is of Kratos::Globals::DataLocation enum + // itr points to the unstructured grid which is referring to the given pContainer. + // if not found, mesh_type is returned with Kratos::Globals::DataLocation::ModelPart + // enum value, which will throw an error. + [[maybe_unused]] auto [mesh_type, itr] = FindUnstructuredGridData(*pContainer, this->mUnstructuredGridDataList); + + switch (mesh_type) { + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: { + // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. + + // here we have to check if the specified tensor adaptor name is there in the found unstructured grid + // referred by the itr. + + // checks in the condition or element maps of flags and variables whether the rTensorAdaptorName already + // exists. + CheckDataArrayName(rTensorAdaptorName, mesh_type, mFlags); // checks in the current data location of mFlags map + CheckDataArrayName(rTensorAdaptorName, mesh_type, mVariables); // checks in the current data location of mVariables map + + // checks in either Condition or Element map of tensor adaptors whether the given rTensorAdaptorName + // exists + CheckDataArrayName(rTensorAdaptorName, mesh_type, *itr); + + // If no conflicts in the naming is found, then put the tensor adaptor for output. + itr->mMapOfCellTensorAdaptors[rTensorAdaptorName] = pTensorAdaptor; + break; + } + case Globals::DataLocation::NodeNonHistorical: { + // checks if the given rTensorAdaptorName is already there in the nodal non-historical + // variables list, nodal-non-historical variables list and flags list. + CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, mFlags); + CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, mVariables); + CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeHistorical, mFlags); + CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeHistorical, mVariables); + + // checks if the given rTensorAdaptorName is already there in the list of nodal tensor adaptors + // of the unstructured grid referred by itr. + CheckDataArrayName(rTensorAdaptorName, Globals::DataLocation::NodeNonHistorical, *itr); + + // If no conflicts in the naming is found, then put the tensor adaptor for output. + itr->mMapOfPointTensorAdaptors[rTensorAdaptorName] = pTensorAdaptor; + break; + } + default: + KRATOS_ERROR + << "The container in the TensorAdaptor is not referring to any of the containers " + << "written by this Vtu output [ tensor adaptor name = " << rTensorAdaptorName + << ", tensor_adaptor = " << *pTensorAdaptor << " ]\n" + << *this; + break; + } + }, pTensorAdaptor->GetContainer()); + + KRATOS_CATCH(""); } -void VtuOutput::AddFlagVariable( - const std::string& rFlagName, - const Flags& rFlagVariable, - const Flags& rEntityFlags) +template +void VtuOutput::ReplaceTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor) { - if (rEntityFlags.Is(NODES)) { - VtuOutputHelperUtilities::CheckDataArrayName( - rFlagName, mHistoricalVariablesMap, mNonHistoricalNodalVariablesMap, - mPointContainerExpressionsMap); - mNodalFlagsMap[rFlagName] = &rFlagVariable; - } else { - KRATOS_ERROR_IF_NOT(!rEntityFlags.Is(CONDITIONS) || (rEntityFlags.Is(CONDITIONS) && mIsConditionsConsidered)) - << "Condition flag \"" - << rFlagName << "\" cannot be written for a model part with elements [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; + KRATOS_TRY + + // a visitor for NodesContainer::Pointer, ConditionsContainer::Pointer, ElementsContainerPointer + // of the given pTensorAdaptor + std::visit([this, &rTensorAdaptorName, &pTensorAdaptor](auto pContainer){ + // finds the unstructured grid for which the given tensor adaptor's pContainer refers to. + // mesh_type is of Kratos::Globals::DataLocation enum + // itr points to the unstructured grid which is referring to the given pContainer. + // if not found, mesh_type is returned with Kratos::Globals::DataLocation::ModelPart + // enum value, which will throw an error. + [[maybe_unused]] auto [mesh_type, itr] = FindUnstructuredGridData(*pContainer, this->mUnstructuredGridDataList); + + switch (mesh_type) { + case Globals::DataLocation::Condition: + case Globals::DataLocation::Element: { + // The following code block will be executed for Globals::DataLocation::Condition and Globals::DataLocation::Element. + auto data_field_itr = itr->mMapOfCellTensorAdaptors.find(rTensorAdaptorName); + + KRATOS_ERROR_IF(data_field_itr == itr->mMapOfCellTensorAdaptors.end()) + << "TensorAdaptor name = \"" + << rTensorAdaptorName << "\" not found in the existing data fields. It is only allowed to update existing data fields. VtuOutput: \n" + << *this; + + data_field_itr->second = pTensorAdaptor; + break; + } + case Globals::DataLocation::NodeNonHistorical: { + auto data_field_itr = itr->mMapOfPointTensorAdaptors.find(rTensorAdaptorName); - KRATOS_ERROR_IF_NOT(!rEntityFlags.Is(ELEMENTS) || (rEntityFlags.Is(ELEMENTS) && mIsElementsConsidered)) - << "Element flag \"" - << rFlagName << "\" cannot be written for a model part with only conditions [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; + KRATOS_ERROR_IF(data_field_itr == itr->mMapOfPointTensorAdaptors.end()) + << "TensorAdaptor name = \"" + << rTensorAdaptorName << "\" not found in the existing data fields. It is only allowed to update existing data fields. VtuOutput: \n" + << *this; - VtuOutputHelperUtilities::CheckDataArrayName( - rFlagName, mNonHistoricalCellVariablesMap, mCellContainerExpressionsMap); - mCellFlagsMap[rFlagName] = &rFlagVariable; - } + data_field_itr->second = pTensorAdaptor; + break; + } + default: + KRATOS_ERROR + << "The container in the TensorAdaptor is not referring to any of the containers " + << "written by this Vtu output [ tensor adaptor name = " << rTensorAdaptorName + << ", tensor_adaptor = " << *pTensorAdaptor << " ]\n" + << *this; + break; + } + }, pTensorAdaptor->GetContainer()); + + KRATOS_CATCH(""); } -template -void VtuOutput::AddContainerExpression( - const std::string& rExpressionName, - const typename ContainerExpression::Pointer pContainerExpression) -{ - if constexpr(std::is_same_v) { - KRATOS_ERROR_IF_NOT(mIsConditionsConsidered) - << "Conditions container expression \"" << rExpressionName - << "\" cannot be written for a model part with elements [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; - } else if constexpr(std::is_same_v) { - KRATOS_ERROR_IF_NOT(mIsElementsConsidered) - << "Elements container expression \"" << rExpressionName - << "\" cannot be written for a model part with only conditions [ model part name = \"" - << mrModelPart.FullName() << "\" ].\n"; - } - - KRATOS_ERROR_IF_NOT(&pContainerExpression->GetModelPart() == &mrModelPart) - << "Model part mismatch in container expression addition. [ Vtu output model part name = \"" - << mrModelPart.FullName() << "\", container expression model part name = \"" - << pContainerExpression->GetModelPart().FullName() << "\" ].\n"; - - if constexpr (std::is_same_v) { - VtuOutputHelperUtilities::CheckDataArrayName( - rExpressionName, mHistoricalVariablesMap, - mNonHistoricalNodalVariablesMap, mNodalFlagsMap); - mPointContainerExpressionsMap[rExpressionName] = pContainerExpression; +template +void VtuOutput::EmplaceTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor) +{ + if (!mIsPVDFileHeaderWritten) { + AddTensorAdaptor(rTensorAdaptorName, pTensorAdaptor); } else { - VtuOutputHelperUtilities::CheckDataArrayName( - rExpressionName, mNonHistoricalCellVariablesMap, mCellFlagsMap); - mCellContainerExpressionsMap[rExpressionName] = pContainerExpression; + ReplaceTensorAdaptor(rTensorAdaptorName, pTensorAdaptor); } } -void VtuOutput::PrintModelPart( +template +std::pair VtuOutput::WriteUnstructuredGridData( + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, const std::string& rOutputFileNamePrefix, - ModelPart& rModelPart) const + const IndexType Step) const { + const auto& r_data_communicator = mrModelPart.GetCommunicator().GetDataCommunicator(); + auto p_nodes = rUnstructuredGridData.mpPoints; + // create the vtk file - auto vtk_file_element = Kratos::make_shared("VTKFile"); - vtk_file_element->AddAttribute("type", "UnstructuredGrid"); - vtk_file_element->AddAttribute("version", "0.1"); - vtk_file_element->AddAttribute("byte_order", VtuOutputHelperUtilities::GetEndianness()); + XmlElementsArray vtk_file_element("VTKFile"); + vtk_file_element.AddAttribute("type", "UnstructuredGrid"); + vtk_file_element.AddAttribute("version", "0.1"); + vtk_file_element.AddAttribute("byte_order", GetEndianness()); // create the unstructured grid - auto unstructured_grid_element = Kratos::make_shared("UnstructuredGrid"); - vtk_file_element->AddElement(unstructured_grid_element); + auto unstructured_grid_element = Kratos::make_shared("UnstructuredGrid"); + vtk_file_element.AddElement(unstructured_grid_element); + + auto p_xml_data_element_wrapper = rElementDataWrapperCreateFunctor(); + rElementDataWrapperAppendFunctor(vtk_file_element, p_xml_data_element_wrapper); // create the piece element - auto piece_element = Kratos::make_shared("Piece"); - piece_element->AddAttribute("NumberOfPoints", - std::to_string(rModelPart.NumberOfNodes())); - piece_element->AddAttribute( - "NumberOfCells", - std::to_string(mIsElementsConsidered ? rModelPart.NumberOfElements() - : rModelPart.NumberOfConditions())); + auto piece_element = Kratos::make_shared("Piece"); + // adding number of points + piece_element->AddAttribute("NumberOfPoints", std::to_string(p_nodes->size())); unstructured_grid_element->AddElement(piece_element); + // create the position element + KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting nodal " << (mConfiguration == Globals::Configuration::Initial ? "initial" : "current") << " position data...\n"; + NodePositionTensorAdaptor node_position_tensor_adaptor(p_nodes, mConfiguration); + node_position_tensor_adaptor.CollectData(); + // create the points element - auto points_element = VtuOutputHelperUtilities::CreatePointsXmlElement( - rModelPart, mIsInitialConfiguration); + auto points_element = Kratos::make_shared("Points"); + points_element->AddElement(p_xml_data_element_wrapper->Get("Position", node_position_tensor_adaptor.pGetStorage())); piece_element->AddElement(points_element); // create the cells element - XmlExpressionElement::Pointer cells_element; - if (mIsElementsConsidered) { - cells_element = VtuOutputHelperUtilities::CreateCellsXmlElement( - rModelPart.GetCommunicator().LocalMesh().Elements(), mKratosVtuIndicesMap); - } else { - cells_element = VtuOutputHelperUtilities::CreateCellsXmlElement( - rModelPart.GetCommunicator().LocalMesh().Conditions(), mKratosVtuIndicesMap); + auto cells_element = Kratos::make_shared("Cells"); + std::vector writing_indices; + if (rUnstructuredGridData.mpCells.has_value()) { + KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting " << GetEntityName(rUnstructuredGridData.mpCells) << " connectivity data...\n"; + AddConnectivityData(*cells_element, writing_indices, *rUnstructuredGridData.mpPoints, rUnstructuredGridData.mpCells.value(), *p_xml_data_element_wrapper, mEchoLevel); } + piece_element->AddAttribute("NumberOfCells", std::to_string(writing_indices.size())); piece_element->AddElement(cells_element); // create the point data - auto point_data_element = Kratos::make_shared("PointData"); + auto point_data_element = Kratos::make_shared("PointData"); piece_element->AddElement(point_data_element); - VtuOutputHelperUtilities::AddListOfVariables( - point_data_element, rModelPart, mHistoricalVariablesMap); - VtuOutputHelperUtilities::AddListOfVariables( - point_data_element, rModelPart, mNonHistoricalNodalVariablesMap); - VtuOutputHelperUtilities::AddListOfFlags( - point_data_element, rModelPart, mNodalFlagsMap); - VtuOutputHelperUtilities::AddListOfContainerExpressions( - point_data_element, rModelPart, mKratosVtuIndicesMap, mPointContainerExpressionsMap); + + if (rUnstructuredGridData.UsePointsForDataFieldOutput) { + KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting nodal data fields...\n"; + // generate and add point field data + std::vector all_indices(p_nodes->size()); + std::iota(all_indices.begin(), all_indices.end(), 0); + AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mFlags[static_cast(Globals::DataLocation::NodeNonHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel); + AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mVariables[static_cast(Globals::DataLocation::NodeNonHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel); + AddFieldsUsingTensorAdaptor(*point_data_element, p_nodes, mVariables[static_cast(Globals::DataLocation::NodeHistorical)], *p_xml_data_element_wrapper, r_data_communicator, all_indices, mEchoLevel, 0); + AddFields(*point_data_element, rUnstructuredGridData.mMapOfPointTensorAdaptors, *p_xml_data_element_wrapper, all_indices, r_data_communicator, mEchoLevel); + } // create cell data - auto cell_data_element = Kratos::make_shared("CellData"); + auto cell_data_element = Kratos::make_shared("CellData"); piece_element->AddElement(cell_data_element); - if (mIsElementsConsidered) { - VtuOutputHelperUtilities::AddListOfVariables( - cell_data_element, rModelPart, mNonHistoricalCellVariablesMap); - VtuOutputHelperUtilities::AddListOfFlags( - cell_data_element, rModelPart, mCellFlagsMap); - } else if (mIsConditionsConsidered) { - VtuOutputHelperUtilities::AddListOfVariables( - cell_data_element, rModelPart, mNonHistoricalCellVariablesMap); - VtuOutputHelperUtilities::AddListOfFlags( - cell_data_element, rModelPart, mCellFlagsMap); + + // generate and add cell field data + if (rUnstructuredGridData.mpCells.has_value()) { + KRATOS_INFO_IF("VtuOutput", mEchoLevel > 2) << "--- Collecting " << GetEntityName(rUnstructuredGridData.mpCells) << " data fields...\n"; + std::visit([this, &rUnstructuredGridData, &cell_data_element, &p_xml_data_element_wrapper, &r_data_communicator, &writing_indices](auto p_container){ + AddFieldsUsingTensorAdaptor(*cell_data_element, p_container, GetContainerMap(this->mVariables, rUnstructuredGridData.mpCells.value()), *p_xml_data_element_wrapper, r_data_communicator, writing_indices, mEchoLevel); + AddFieldsUsingTensorAdaptor(*cell_data_element, p_container, GetContainerMap(this->mFlags, rUnstructuredGridData.mpCells.value()), *p_xml_data_element_wrapper, r_data_communicator, writing_indices, mEchoLevel); + }, rUnstructuredGridData.mpCells.value()); + AddFields(*cell_data_element, rUnstructuredGridData.mMapOfCellTensorAdaptors, *p_xml_data_element_wrapper, writing_indices, r_data_communicator, mEchoLevel); } - VtuOutputHelperUtilities::AddListOfContainerExpressions( - cell_data_element, rModelPart, mKratosVtuIndicesMap, mCellContainerExpressionsMap); + std::stringstream output_vtu_file_name; + output_vtu_file_name << rOutputFileNamePrefix << "/" << rUnstructuredGridData.mpModelPart->FullName(); - const auto& r_communiator = rModelPart.GetCommunicator(); + // identify suffix with the entity type. + const std::string& suffix = "_" + GetEntityName(rUnstructuredGridData.mpCells) + "s"; - std::stringstream output_vtu_file_name; - output_vtu_file_name << rOutputFileNamePrefix; - if (r_communiator.IsDistributed()) { - output_vtu_file_name << "_" << r_communiator.MyPID(); - } - output_vtu_file_name << ".vtu"; + const std::string pvd_data_set_name = rUnstructuredGridData.mpModelPart->FullName() + suffix; + + // append with the step value and rank and extension + output_vtu_file_name << suffix << "_" << Step + << (r_data_communicator.IsDistributed() + ? "_" + std::to_string(r_data_communicator.Rank()) + : "") + << ".vtu"; + // write the vtu file. std::ofstream output_file; - output_file.open(output_vtu_file_name.str(), std::ios::out | std::ios::trunc); + output_file.open(output_vtu_file_name.str(), std::ios::out | std::ios::trunc | std::ios::binary); + output_file << "" << std::endl; + vtk_file_element.Write(output_file); + output_file.close(); - switch (mOutputFormat) { - case WriterFormat::ASCII: - { - XmlOStreamAsciiWriter writer(output_file, mPrecision); - writer.WriteElement(*vtk_file_element); - } - break; - case WriterFormat::BINARY: - { - XmlOStreamBase64BinaryWriter writer(output_file); - writer.WriteElement(*vtk_file_element); + // if it is run on a distributed system, create the pvtu file. + if (r_data_communicator.IsDistributed()) { + return std::make_pair(pvd_data_set_name, + WritePartitionedUnstructuredGridData( + *point_data_element, *cell_data_element, + output_vtu_file_name.str(), r_data_communicator)); + } + + // return the final file name for + return std::make_pair(pvd_data_set_name, output_vtu_file_name.str()); +} + +template +std::pair VtuOutput::WriteIntegrationPointData( + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, + const std::string& rOutputFileNamePrefix, + const IndexType Step) const +{ + if (!rUnstructuredGridData.mpCells.has_value()) { + // nothing to do here. + return std::make_pair("", ""); + } + + const auto& integration_point_vars = GetContainerMap( + mIntegrationPointVariables, rUnstructuredGridData.mpCells.value()); + + if (integration_point_vars.empty()) { + // nothing to do here. + return std::make_pair("", ""); + } + + // create the vtk file + XmlElementsArray vtk_file_element("VTKFile"); + vtk_file_element.AddAttribute("type", "UnstructuredGrid"); + vtk_file_element.AddAttribute("version", "0.1"); + vtk_file_element.AddAttribute("byte_order", GetEndianness()); + + // create the unstructured grid + auto unstructured_grid_element = Kratos::make_shared("UnstructuredGrid"); + vtk_file_element.AddElement(unstructured_grid_element); + + auto p_xml_data_element_wrapper = rElementDataWrapperCreateFunctor(); + rElementDataWrapperAppendFunctor(vtk_file_element, p_xml_data_element_wrapper); + + DenseVector offsets; + + const auto total_gauss_points = std::visit([&offsets](auto p_container) { + // resize the offsets + offsets.resize(p_container->size(), false); + + IndexType total_number_of_gauss_points = 0; + + // now compute the offsets for each entity. This allows + // having different number of gps in different entities. + // which is the case if we have a model part with mixed type + // of elements. + for (IndexType i = 0; i < p_container->size(); ++i) { + const auto& r_entity = *(p_container->begin() + i); + const auto number_of_gps = r_entity.GetGeometry().IntegrationPointsNumber(r_entity.GetIntegrationMethod()); + total_number_of_gauss_points += number_of_gps; + offsets[i] = total_number_of_gauss_points - number_of_gps; } - break; + + return total_number_of_gauss_points; + }, rUnstructuredGridData.mpCells.value()); + + // create the piece element + auto piece_element = Kratos::make_shared("Piece"); + piece_element->AddAttribute("NumberOfPoints", std::to_string(total_gauss_points)); + piece_element->AddAttribute("NumberOfCells", "0"); + unstructured_grid_element->AddElement(piece_element); + + // construct the gauss point position data + DenseVector gauss_point_nd_data_shape(2); + gauss_point_nd_data_shape[0] = total_gauss_points; + gauss_point_nd_data_shape[1] = 3; + auto gauss_point_positions = Kratos::make_shared>(gauss_point_nd_data_shape); + const auto span = gauss_point_positions->ViewData(); + + std::visit([&span, &offsets](auto p_container){ + IndexPartition(p_container->size()).for_each(array_1d{}, [&span, &p_container, &offsets](const auto Index, auto& rTLS) { + const auto& r_entity = *(p_container->begin() + Index); + const auto number_of_gauss_points = r_entity.GetGeometry().IntegrationPointsNumber(r_entity.GetIntegrationMethod()); + for (IndexType i = 0; i < number_of_gauss_points; ++i) { + r_entity.GetGeometry().GlobalCoordinates(rTLS, i); + std::copy(rTLS.begin(), rTLS.end(), span.begin() + offsets[Index] * 3 + i * 3); + } + + }); + }, rUnstructuredGridData.mpCells.value()); + + // create the gauss points element + auto points_element = Kratos::make_shared("Points"); + points_element->AddElement(p_xml_data_element_wrapper->Get("Position", gauss_point_positions)); + piece_element->AddElement(points_element); + + auto cells_element = Kratos::make_shared("Cells"); + piece_element->AddElement(cells_element); + + // create the point data + auto point_data_element = Kratos::make_shared("PointData"); + piece_element->AddElement(point_data_element); + + const auto& r_data_communicator = mrModelPart.GetCommunicator().GetDataCommunicator(); + + // add the gauss point data + bool is_gauss_point_data_available = false; + for (const auto& r_pair : integration_point_vars) { + std::visit([&offsets, &point_data_element, &p_xml_data_element_wrapper, &rUnstructuredGridData, &is_gauss_point_data_available, &r_data_communicator, total_gauss_points](auto pVariable, auto pContainer) { + // type information of the variable + using data_type = typename BareType::Type; + using data_type_traits = DataTypeTraits; + using primitive_data_type = typename data_type_traits::PrimitiveType; + + if constexpr(std::is_same_v) { + // here we cannot use GaussPointVariableTensorAdaptor because + // it does not allow recording gauss point information if different + // entities have different number of gauss points. + // hence we do the computation here manually. + + std::vector output; + + // first we need to find out the shape of the gauss point data + std::vector local_shape(data_type_traits::Dimension, 0u); + if (!pContainer->empty()) { + pContainer->front().CalculateOnIntegrationPoints( + *pVariable, output, rUnstructuredGridData.mpModelPart->GetProcessInfo()); + + if (!output.empty()) { + // if there are available gauss point information + data_type_traits::Shape(output.front(), local_shape.data(), + local_shape.data() + local_shape.size()); + } + } + + // now do the communication between ranks to get the correct size + const auto& max_local_shape = r_data_communicator.MaxAll(local_shape); + + // now we construct the nd_data_shape + DenseVector nd_data_shape(local_shape.size() + 1); + std::copy(max_local_shape.begin(), max_local_shape.end(), nd_data_shape.begin() + 1); + nd_data_shape[0] = total_gauss_points; + + const auto total_number_of_components = std::accumulate(max_local_shape.begin(), max_local_shape.end(), 1u, std::multiplies{}); + + auto p_gauss_data = Kratos::make_shared>(nd_data_shape); + auto span = p_gauss_data->ViewData(); + + if (r_data_communicator.SumAll(static_cast(span.size())) > 0) { + is_gauss_point_data_available = true; + IndexPartition(pContainer->size()).for_each(std::vector{}, [&span, &pContainer, &pVariable, &rUnstructuredGridData, &offsets, total_number_of_components](const auto Index, auto& rTLS) { + auto& r_entity = *(pContainer->begin() + Index); + r_entity.CalculateOnIntegrationPoints(*pVariable, rTLS, rUnstructuredGridData.mpModelPart->GetProcessInfo()); + DataTypeTraits>::CopyToContiguousData(span.begin() + offsets[Index] * total_number_of_components, rTLS); + }); + point_data_element->AddElement(p_xml_data_element_wrapper->Get(pVariable->Name(), p_gauss_data)); + } + } + }, r_pair.second, rUnstructuredGridData.mpCells.value()); } - output_file.close(); + if (is_gauss_point_data_available) { + std::stringstream output_vtu_file_name; + output_vtu_file_name + << rOutputFileNamePrefix << "/" << rUnstructuredGridData.mpModelPart->FullName() << "_" + << GetEntityName(rUnstructuredGridData.mpCells) + << "_gauss_" << Step + << (r_data_communicator.IsDistributed() + ? "_" + std::to_string(r_data_communicator.Rank()) + : "") + << ".vtu"; + + std::ofstream output_file; + output_file.open(output_vtu_file_name.str(), std::ios::out | std::ios::trunc); + output_file << "" << std::endl; + vtk_file_element.Write(output_file); + output_file.close(); + + if (r_data_communicator.IsDistributed()) { + return std::make_pair( + rUnstructuredGridData.mpModelPart->FullName() + "_" + GetEntityName(rUnstructuredGridData.mpCells) + "_gauss", + WritePartitionedUnstructuredGridData( + *point_data_element, *Kratos::make_shared(""), + output_vtu_file_name.str(), r_data_communicator)); + } - if (r_communiator.IsDistributed()) { - VtuOutputHelperUtilities::WritePvtuFile(vtk_file_element, rModelPart, rOutputFileNamePrefix, - output_vtu_file_name.str()); + return std::make_pair(rUnstructuredGridData.mpModelPart->FullName() + "_" + GetEntityName(rUnstructuredGridData.mpCells) + "_gauss", + output_vtu_file_name.str()); + } + else { + return std::make_pair("", ""); } } -void VtuOutput::ClearHistoricalVariables() +template +void VtuOutput::WriteData( + std::vector>& rPVDFileNameInfo, + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, + const std::string& rOutputPrefix, + const IndexType Step) const { - mHistoricalVariablesMap.clear(); -} + KRATOS_TRY -void VtuOutput::ClearNodalNonHistoricalVariables() -{ - mNonHistoricalNodalVariablesMap.clear(); -} + rPVDFileNameInfo.push_back(WriteUnstructuredGridData( + rElementDataWrapperCreateFunctor, rElementDataWrapperAppendFunctor, + rUnstructuredGridData, rOutputPrefix, Step)); -void VtuOutput::ClearCellNonHistoricalVariables() -{ - mNonHistoricalCellVariablesMap.clear(); -} + rPVDFileNameInfo.push_back(WriteIntegrationPointData( + rElementDataWrapperCreateFunctor, rElementDataWrapperAppendFunctor, + rUnstructuredGridData, rOutputPrefix, Step)); -void VtuOutput::ClearNodalFlags() -{ - mNodalFlagsMap.clear(); + KRATOS_CATCH(""); } -void VtuOutput::ClearCellFlags() +void VtuOutput::PrintOutput(const std::string& rOutputFileNamePrefix) { - mCellFlagsMap.clear(); -} + KRATOS_TRY -void VtuOutput::ClearNodalContainerExpressions() -{ - mPointContainerExpressionsMap.clear(); + const auto& r_process_info = mrModelPart.GetProcessInfo(); + + // here we do not check whether the r_process_info has the time variable specified + // because, in a const DataValueContainer, if the variable is not there, it returns the + // zero value of the variable. + const double time = r_process_info[TIME]; + + const IndexType step = r_process_info[STEP]; + + std::filesystem::create_directories(rOutputFileNamePrefix); + + std::vector> pvd_file_name_info; + + for (auto& r_unstructured_grid_data : mUnstructuredGridDataList) { + switch (mOutputFormat) { + case ASCII: + { + WriteData( + pvd_file_name_info, + [this](){ return Kratos::make_shared(XmlInPlaceDataElementWrapper::ASCII, this->mPrecision); }, + [](auto& rVtkFileElement, auto pXmlDataElementWrapper) {}, + r_unstructured_grid_data, + rOutputFileNamePrefix, + step); + break; + } + case BINARY: + { + WriteData( + pvd_file_name_info, + [this](){ return Kratos::make_shared(XmlInPlaceDataElementWrapper::BINARY, this->mPrecision); }, + [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddAttribute("header_type", "UInt64"); }, + r_unstructured_grid_data, + rOutputFileNamePrefix, + step); + break; + } + case RAW: + { + WriteData( + pvd_file_name_info, + [](){ return Kratos::make_shared(XmlAppendedDataElementWrapper::RAW); }, + [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddElement(pXmlDataElementWrapper); rVtkFileElement.AddAttribute("header_type", "UInt64"); }, + r_unstructured_grid_data, + rOutputFileNamePrefix, + step); + break; + } + case COMPRESSED_RAW: + { + WriteData( + pvd_file_name_info, + [](){ return Kratos::make_shared(XmlAppendedDataElementWrapper::COMPRESSED_RAW); }, + [](auto& rVtkFileElement, auto pXmlDataElementWrapper) { rVtkFileElement.AddElement(pXmlDataElementWrapper); rVtkFileElement.AddAttribute("header_type", "UInt64"); rVtkFileElement.AddAttribute("compressor", "vtkZLibDataCompressor"); }, + r_unstructured_grid_data, + rOutputFileNamePrefix, + step); + break; + } + } + } + + // now generate the *.pvd file + if (mrModelPart.GetCommunicator().MyPID() == 0) { + KRATOS_INFO_IF("VtuOutput", mEchoLevel > 1) + << "Writing \"" << mrModelPart.FullName() + << "\" PVD file...\n"; + // Single pvd file links all the vtu files from sum-model parts + // partitioned model_parts and time step vtu files together. + + if (!mIsPVDFileHeaderWritten) { + mIsPVDFileHeaderWritten = true; + + // creates the pvd file element + XmlElementsArray pvd_file_element("VTKFile"); + pvd_file_element.AddAttribute("type", "Collection"); + pvd_file_element.AddAttribute("version", "1.0"); + pvd_file_element.AddAttribute("byte_order", GetEndianness()); + + // creates the collection element + auto collection_element = Kratos::make_shared("Collection"); + pvd_file_element.AddElement(collection_element); + + // now iterate through all the time steps and correctly write + // the file names for each time step. + IndexType local_index = 0; + for (IndexType i = 0; i < pvd_file_name_info.size(); ++i) { + if (pvd_file_name_info[i].second != "") { + auto current_element = Kratos::make_shared("DataSet"); + + // write the time with the specified precision. + std::stringstream str_time; + str_time << std::scientific << std::setprecision(mPrecision) << time; + + current_element->AddAttribute("timestep", str_time.str()); + current_element->AddAttribute("name", pvd_file_name_info[i].first); + current_element->AddAttribute("part", std::to_string(local_index++)); + current_element->AddAttribute( + "file", std::filesystem::relative( + std::filesystem::absolute(pvd_file_name_info[i].second), + std::filesystem::absolute(rOutputFileNamePrefix).parent_path()) + .generic_string()); + collection_element->AddElement(current_element); + } + } + + std::ofstream output_file; + output_file.open(rOutputFileNamePrefix + ".pvd", std::ios::out | std::ios::trunc); + output_file << "" << std::endl; + pvd_file_element.Write(output_file); + output_file.close(); + } else { + std::ofstream output_file; + output_file.open(rOutputFileNamePrefix + ".pvd", std::ios::in | std::ios::out); + output_file.seekp(-28, std::ios::end); + + // now iterate through all the time steps and correctly write + // the file names for each time step. + IndexType local_index = 0; + for (IndexType i = 0; i < pvd_file_name_info.size(); ++i) { + if (pvd_file_name_info[i].second != "") { + auto current_element = Kratos::make_shared("DataSet"); + + // write the time with the specified precision. + std::stringstream str_time; + str_time << std::scientific << std::setprecision(mPrecision) << time; + + current_element->AddAttribute("timestep", str_time.str()); + current_element->AddAttribute("name", pvd_file_name_info[i].first); + current_element->AddAttribute("part", std::to_string(local_index++)); + current_element->AddAttribute( + "file", std::filesystem::relative( + std::filesystem::absolute(pvd_file_name_info[i].second), + std::filesystem::absolute(rOutputFileNamePrefix).parent_path()) + .generic_string()); + + current_element->Write(output_file, 2); + } + } + + output_file << " " << std::endl <<"" << std::endl; + output_file.close(); + } + + } + + KRATOS_CATCH(""); } -void VtuOutput::ClearCellContainerExpressions() +std::string VtuOutput::Info() const { - mCellContainerExpressionsMap.clear(); + std::stringstream info; + info << "VtuOutput: " << mrModelPart.FullName() << " [ writer = "; + switch (mOutputFormat) { + case ASCII: + info << "ASCII"; + break; + case BINARY: + info << "BINARY"; + break; + case RAW: + info << "RAW"; + break; + case COMPRESSED_RAW: + info << "COMPRESSED_RAW"; + break; + } + + info << ", precision = " << mPrecision << ", configuration = "; + + switch (mConfiguration){ + case Globals::Configuration::Initial: + info << "initial"; + break; + case Globals::Configuration::Current: + info << "current"; + break; + } + + info << ", echo level = " << mEchoLevel << " ]"; + + return info.str(); } -const ModelPart& VtuOutput::GetModelPart() const +void VtuOutput::PrintInfo(std::ostream& rOStream) const { - return mrModelPart; + rOStream << this->Info(); } -void VtuOutput::PrintOutput(const std::string& rOutputFilenamePrefix) +void VtuOutput::PrintData(std::ostream& rOStream) const { - PrintModelPart(rOutputFilenamePrefix, mrModelPart); + PrintLocationData(rOStream, "flag", mFlags); + rOStream << "\n"; + PrintLocationData(rOStream, "variable", mVariables); + rOStream << "\n"; + PrintLocationData(rOStream, "integration variable", mIntegrationPointVariables); + rOStream << "\n"; + + rOStream << "List of model part info:"; + for (const auto& r_model_part_data : mUnstructuredGridDataList) { + rOStream << "\n\tModel part: \"" << r_model_part_data.mpModelPart->FullName() << "\"" + << " with " << GetEntityName(r_model_part_data.mpCells) << "s" + << ", used for point fields = " << (r_model_part_data.UsePointsForDataFieldOutput ? "yes" : "no"); + + if (r_model_part_data.UsePointsForDataFieldOutput) { + rOStream << "\n\t\t" << "Point fields:"; + for (const auto& r_pair : r_model_part_data.mMapOfPointTensorAdaptors) { + std::visit([&rOStream, &r_pair](auto pNDData){ + rOStream << "\n\t\t\t" << r_pair.first << ": " << *pNDData; + }, r_pair.second); + } + } + + rOStream << "\n\t\t" << "Cell fields:"; + for (const auto& r_pair : r_model_part_data.mMapOfCellTensorAdaptors) { + std::visit([&rOStream, &r_pair](auto pNDData){ + rOStream << "\n\t\t\t" << r_pair.first << ": " << *pNDData; + }, r_pair.second); + } + } } // template instantiations -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable>&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable>&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable>&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddHistoricalVariable(const Variable>&); - -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable&, const Flags&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable&, const Flags&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable>&, const Flags&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable>&, const Flags&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable>&, const Flags&); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddNonHistoricalVariable(const Variable>&, const Flags&); - -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddContainerExpression(const std::string&, const typename ContainerExpression::Pointer); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddContainerExpression(const std::string&, const typename ContainerExpression::Pointer); -template KRATOS_API(KRATOS_CORE) void VtuOutput::AddContainerExpression(const std::string&, const typename ContainerExpression::Pointer); +#ifndef KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION +#define KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(...) \ + template KRATOS_API(KRATOS_CORE) void VtuOutput::AddVariable<__VA_ARGS__>(const Variable<__VA_ARGS__>&, const Globals::DataLocation&); \ + template KRATOS_API(KRATOS_CORE) void VtuOutput::AddIntegrationPointVariable<__VA_ARGS__>(const Variable<__VA_ARGS__>&, const Globals::DataLocation&); \ + +#endif + +#ifndef KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION +#define KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(DATA_TYPE) \ + template KRATOS_API(KRATOS_CORE) void VtuOutput::AddTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ + template KRATOS_API(KRATOS_CORE) void VtuOutput::ReplaceTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ + template KRATOS_API(KRATOS_CORE) void VtuOutput::EmplaceTensorAdaptor::Pointer>(const std::string&, TensorAdaptor::Pointer); \ + +#endif + +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(int) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(double) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(array_1d) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(Vector) +KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION(Matrix) + +KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(bool) +KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(int) +KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION(double) + +#undef KRATOS_VTU_OUTPUT_VARIABLE_METHOD_INSTANTIATION +#undef KRATOS_VTU_OUTPUT_TENSOR_METHOD_INSTANTIATION } // namespace Kratos diff --git a/kratos/input_output/vtu_output.h b/kratos/input_output/vtu_output.h index 50e56382dd4d..b711bc4395a7 100644 --- a/kratos/input_output/vtu_output.h +++ b/kratos/input_output/vtu_output.h @@ -13,30 +13,48 @@ #pragma once // System includes +#include #include #include -#include -#include // External includes // Project includes +#include "containers/flags.h" +#include "containers/nd_data.h" +#include "containers/variable.h" #include "includes/define.h" +#include "includes/global_variables.h" #include "includes/io.h" #include "includes/model_part.h" -#include "containers/variable.h" -#include "containers/flags.h" -#include "expression/container_expression.h" +#include "tensor_adaptors/tensor_adaptor.h" +#include "utilities/xml_utilities/xml_data_element_wrapper.h" namespace Kratos { + /** * @class VtuOutput - * @brief Class to output Kratos Flags, Variables and ContainerExpressions - * to vtu. Supports both shared and distributed memory architectures. - * - * @details This class does not create or destroy any folder structures, hence the output - * file name prefix should have a valid parent directory. + * @brief Handles VTU (Visualization Toolkit Unstructured grid) output for Kratos ModelParts. * @author Suneth Warnakulasuriya + * @ingroup KratosCore + * + * This class provides functionality to export simulation data from a Kratos ModelPart to VTU files, + * supporting both ASCII, BINARY, RAW and COMPRESSED_RAW with zlib compression. It allows users to register @ref Variable , @ref Flags , + * and @ref TensorAdaptor for output, and supports writing data on nodes, elements, conditions, and integration points. + * The output can be configured to include submodel parts and supports parallel execution (MPI). + * + * @section vtu_output_usage Usage + * This output put process can be used at any point in the simulation (static or dynamic). But, upon construction of an object of + * @ref VtuOutput, all the variables, flags, integration point variables and tensor adaptors should be added + * using @ref AddFlag, @ref AddVariable, @ref AddIntegrationPointVariable or @ref AddTensorAdaptor . Once the + * @ref PrintOutput is called, no more data fields can be added because Vtk library does not support varying fields. + * + * But, already added @ref TensorAdaptor objects may be replaced with new @ref TensorAdaptor objects after calling @ref PrintOutput + * by using @ref ReplaceTensorAdaptor method. + * + * A convenience method called @ref EmplaceTensorAdaptor is there to add the @ref TensorAdaptor if it is not existing and if the call is + * before the first call of @ref PrintOutput. Otherwise, it will try replacing an existing @ref TensorAdaptor. + * */ class KRATOS_API(KRATOS_CORE) VtuOutput : public IO { @@ -44,26 +62,48 @@ class KRATOS_API(KRATOS_CORE) VtuOutput : public IO ///@name Type definitions ///@{ + // Index type definition using IndexType = std::size_t; - using SupportedVariables = std::variant< - const Variable*, - const Variable*, - const Variable>*, - const Variable>*, - const Variable>*, - const Variable>*>; - - using SupportedCellContainerExpressions = std::variant< - ContainerExpression::Pointer, - ContainerExpression::Pointer>; + // Variant defining supported container (i.e. @ref PointerVectorSet ) type pointers. + using SupportedContainerPointerType = std::variant< + ModelPart::NodesContainerType::Pointer, + ModelPart::ConditionsContainerType::Pointer, + ModelPart::ElementsContainerType::Pointer + >; + + // Variant defining supported cell type @ref PointerVectorSte which can be visualized with cell data with vtk library. + using CellContainerPointerType = std::variant< + ModelPart::ConditionsContainerType::Pointer, + ModelPart::ElementsContainerType::Pointer + >; + + // Variant defining all the @ref Variable types which are supported to be visualized at point or cell data with vtk library. + using SupportedVariablePointerType = std::variant< + Variable const *, + Variable const *, + Variable> const *, + Variable> const *, + Variable> const *, + Variable> const *, + Variable const *, + Variable const * + >; + + // Variant definining all the supported @ref TensorAdaptor which can be used to pass data fields to point or cell data using the vtk library. + using SupportedTensorAdaptorPointerType = std::variant< + TensorAdaptor::Pointer, + TensorAdaptor::Pointer, + TensorAdaptor::Pointer + >; + + + // A list of maps of name and a @p T for different locations ( @ref Globals::DataLocation ) which are used for output at later time. + template + using DataList = std::array, static_cast(Kratos::Globals::DataLocation::NumberOfDataLocations)>; KRATOS_CLASS_POINTER_DEFINITION(VtuOutput); - KRATOS_DEFINE_LOCAL_FLAG( NODES ); - KRATOS_DEFINE_LOCAL_FLAG( CONDITIONS ); - KRATOS_DEFINE_LOCAL_FLAG( ELEMENTS ); - ///@} ///@name Public enums ///@{ @@ -71,8 +111,20 @@ class KRATOS_API(KRATOS_CORE) VtuOutput : public IO /// Enumerations for the output writer format. enum WriterFormat { - ASCII, /// ASCII format. - BINARY /// Binary format. + ASCII, ///< ASCII format. + BINARY, ///< Binary format. + RAW, ///< Raw format. All data is appended to one stream. + COMPRESSED_RAW ///< Data is first compressed with zlib and the appended to one stream. + }; + + struct UnstructuredGridData + { + bool UsePointsForDataFieldOutput; // If true, then the mpPoints represents a container in the model part, otherwise, mpPoints refers to a container which is on the fly generated. + ModelPart * mpModelPart; // Model part associated with the unstructured grid data. + ModelPart::NodesContainerType::Pointer mpPoints; // Points to be used in the unstructured grid. + std::optional mpCells; // Cells to be used in the unstructured grid. + std::map mMapOfPointTensorAdaptors; // Point data tensor adaptors. + std::map mMapOfCellTensorAdaptors; // Cell data tensor adaptors. }; ///@} @@ -80,108 +132,153 @@ class KRATOS_API(KRATOS_CORE) VtuOutput : public IO ///@{ /** - * @brief Construct a new Vtu Output IO - * @details Constructs a new VtuOuput IO instance with the given parameters. - * @param rModelPart Model part to be used. - * @param IsInitialConfiguration If true, the initial configuration is written. - * @param OutputFormat Output format. Either ASCII or BINARY supported. - * @param Precision Precision of the double output. + * @brief Construct a new Vtu Output + * + * @param rModelPart Model part to be used in the vtu output. + * @param IsInitialConfiguration Which nodal positions to be written out. + * @param OutputFormat The format of the output. + * @param Precision Precision of the double values to be used when writing the doubles as ASCII. + * @param OutputSubModelParts To consider all the submodel parts recursively for output. + * @param WriteIds To write ids under the name "KRATOS_ID" to be visualized. + * @param EchoLevel Echo level for to print information. */ VtuOutput( ModelPart& rModelPart, const bool IsInitialConfiguration = true, - const WriterFormat OutputFormat = WriterFormat::BINARY, - const IndexType Precision = 9); + const WriterFormat OutputFormat = WriterFormat::COMPRESSED_RAW, + const IndexType Precision = 9, + const bool OutputSubModelParts = false, + const bool WriteIds = false, + const IndexType EchoLevel = 0); ///@} ///@name Public operations ///@{ /** - * @brief Adds historical variables to the output. + * @brief Adds a flag to the VTU output. * - * @tparam TDataType - * @param rVariable + * This method registers a flag @p rFlagVariable to be included in the VTU output file. + * The flag will be associated with the specified data location (e.g., node, element, condition, refer @ref Globals::DataLocation ) + * given by @p DataLocation . This allows the Flag's values to be written to the output file + * when @ref PrintOutput is called with the name @p rFlagName. + * + * @throws std::runtime_error if @ref AddFlag is called after @ref PrintOutput. + * @throws std::runtime_error if tries to add the same @p rFlagName more than ones. + * @throws std::runtime_error if there already exist a field name same as @p rFlagName in one of the compatible data locations with @p DataLocation . + * @throws std::runtime_error if @p DataLocation is not NodeNonHistorical, Condition, or Element. + * + * @param rFlagName The name of the flag to be added. + * @param rFlagVariable The flag variable to be added. + * @param DataLocation The location where the flag data is stored (e.g., NodeNonHistorical, Condition, Element). + * + * @see @ref FlagsTensorAdaptor */ - template - void AddHistoricalVariable(const Variable& rVariable); + void AddFlag( + const std::string& rFlagName, + const Flags& rFlagVariable, + const Globals::DataLocation& DataLocation); /** - * @brief Adds non historical variables to the output. + * @brief Adds a variable to the output for a specified data location. + * + * Registers the given @p rVariable to be included in the VTU output at the specified + * @p DataLocation (e.g., NodeHistorical, NodeNonHistorical, Condition, or Element, refer @ref Globals::DataLocation). + * This allows the variable's values to be written to the output file when @ref PrintOutput is called. * - * @tparam TDataType + * @throws std::runtime_error if @ref AddVariable is called after @ref PrintOutput. + * @throws std::runtime_error if tries to add the same @p rVariable more than ones. + * @throws std::runtime_error if there already exist a field name same as @p rVariable in one of the compatible data locations with @p DataLocation . + * @throws std::runtime_error if @p DataLocation is not NodeHistorical, NodeNonHistorical, Condition, or Element. + * + * @tparam TDataType Data type of the variable. * @param rVariable Variable to be added. - * @param rEntityFlags Considered container for the variable. Either NODES, CONDITIONS or ELEMENTS + * @param DataLocation The location in the model where the variable is defined (e.g., NodeHistorical, NodeNonHistorical, Condition, or Element). + * + * @see @ref VariableTensorAdaptor + * @see @ref HistoricalVariableTensorAdaptor */ template - void AddNonHistoricalVariable( + void AddVariable( const Variable& rVariable, - const Flags& rEntityFlags); + const Globals::DataLocation& DataLocation); /** - * @brief Adds flag output. + * @brief Adds a variable to be output at integration points. * - * @param rFlagName Flag name. - * @param rFlagVariable Variable to be added. - * @param rEntityFlags Considered container for the variable. Either NODES, CONDITIONS or ELEMENTS + * This method registers a @p rVariable for output at the integration points of the mesh elements or conditions + * specified by @p DataLocation (refer @ref Globals::DataLocation ). This allows the entities variable's integration point values to + * be written to the output file when @ref PrintOutput is called. + * + * @throws std::runtime_error if @ref AddIntegrationPointVariable is called after @ref PrintOutput. + * @throws std::runtime_error if tries to add the same @p rVariable more than ones. + * @throws std::runtime_error if there already exist a field name same as @p rVariable in one of the compatible data locations with @p DataLocation . + * @throws std::runtime_error if @p DataLocation is not Condition or Element. + * + * @tparam TDataType Data type of the variable. + * @param rVariable Variable to be added. + * @param DataLocation Specifies the location (e.g., Condition or Element) where the variable is used to calculate integration point values. */ - void AddFlagVariable( - const std::string& rFlagName, - const Flags& rFlagVariable, - const Flags& rEntityFlags); + template + void AddIntegrationPointVariable( + const Variable& rVariable, + const Globals::DataLocation& DataLocation); /** - * @brief Adds container expressions to the vtu output. + * @brief Adds a tensor adaptor to the output. * - * This adds container expressions to the output. Proper care should be taken when updating ContainerExpressions because - * In python, when a container expression is assigned with a new container expression, it does not call the assignment operator. - * Hence, the new expression takes place. Therefore, when container expressions required to be outputted, then it is best - * to always clear the existing container expressions and add the new ones. Otherwise, the vtu output may be writing not the - * latest container expression. + * Registers a @p pTensorAdaptor with the specified @p TensorAdaptorName for the the vtu output. this does not + * copy the tensor adaptor. When @ref PrintOutput is called, the values of the @p pTensorAdaptor at this point will + * be written to vtu. * - * @tparam TContainerType - * @param rExpressionName Name for the container expression. - * @param pContainerExpression Container expression. + * @throws std::runtime_error if @ref AddTensorAdaptor is called after @ref PrintOutput. + * @throws std::runtime_error if tries to add the same @p rTensorAdaptorName more than ones. + * @throws std::runtime_error if there already exist a field name same as @p rTensorAdaptorName in one of the compatible data locations represented by the container of @p pTensorAdaptor . + * @throws std::runtime_error if @p pTensorAdaptor does not corresponds to any of the containers which is written by this @ref VtuOutput . + * + * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. + * @param rTensorAdaptorName The name to associate with the tensor adaptor. + * @param pTensorAdaptor Pointer to the tensor adaptor to be added. */ - template - void AddContainerExpression( - const std::string& rExpressionName, - const typename ContainerExpression::Pointer pContainerExpression); - - /** - * @brief Clears the historical variables. - */ - void ClearHistoricalVariables(); - - /** - * @brief Clears the nodal non-historical variables. - */ - void ClearNodalNonHistoricalVariables(); + template + void AddTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor); /** - * @brief Clears the cell non-historical variables. - */ - void ClearCellNonHistoricalVariables(); - - /** - * @brief Clears the nodal flags. - */ - void ClearNodalFlags(); - - /** - * @brief Clears the cell flags. - */ - void ClearCellFlags(); - - /** - * @brief Clears the nodal container expressions. - */ - void ClearNodalContainerExpressions(); + * @brief Updates the tensor adaptor associated with the given name. + * + * This method assigns a new tensor adaptor to the specified name, allowing + * for dynamic changes to the tensor adaptor used in the @ref VtuOutput process. + * This also copies the internal data of @p pTensorAdaptor to vtu output's internal data. + * + * @throws std::runtime_error if there is no field name same as @p rTensorAdaptorName in one of the compatible data locations represented by the container of @p pTensorAdaptor . + * @throws std::runtime_error if @p pTensorAdaptor does not corresponds to any of the containers which is written by this @ref VtuOutput . + * + * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. + * @param rTensorAdaptorName The name identifying the tensor adaptor to update. + * @param pTensorAdaptor Pointer to the new tensor adaptor to be associated. + */ + template + void ReplaceTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor); /** - * @brief Clears the cell container expressions. - */ - void ClearCellContainerExpressions(); + * @brief Inserts a @ref TensorAdaptor into the internal storage with the specified name. + * + * This method: + * - If PrintOutput is not called at all, then calls @ref AddTensorAdaptor + * - If PrintOutput is at least once called, then calls @ref ReplaceTensorAdaptor + * + * @tparam TTensorAdaptorPointerType Pointer type of the tensor adaptor. + * @param rTensorAdaptorName The name to associate with the @ref TensorAdaptor. + * @param pTensorAdaptor Pointer to the @ref TensorAdaptor to be stored. + */ + template + void EmplaceTensorAdaptor( + const std::string& rTensorAdaptorName, + TTensorAdaptorPointerType pTensorAdaptor); /** * @brief Returns the model part. @@ -190,62 +287,96 @@ class KRATOS_API(KRATOS_CORE) VtuOutput : public IO const ModelPart& GetModelPart() const; /** - * @brief Writes the Vtu file. - * @details This writes the final vtu file. If this is a transient output, then @ref rOutputFilenamePrefix - * should have indication of the step, otherwise this will overwrite the same file. - * In the MPI case, this will create one .vtu file per rank, and a .pvtu file to combine them. - * @param rOutputFilenamePrefix Output file name prefix. + * @brief Get the list of output containers + * @details This method returns containers of the model part which are used when writing fields. + * @return std::vector List of container which are used in when writing fields. + */ + std::vector GetOutputContainerList() const; + + /** + * @brief Prints the vtu output data to a file with the specified filename prefix. + * + * Will create the folder with the provided @p rOutputFilenamePrefix . In this folder, following files will be created. + * - One vtu file per timestep, per model part's container (Including sub model parts if @p OutputSubModelParts is true) (in MPI, per rank as well). + * - If it find any gauss point fields, then there will be a vtu file per time step, per model part's container (in MPI, per rank as well). + * - If this is called in MPI, then this will create one pvtu file per timestep, per model part's container (will be having information of all the corresponding rank vtu files) + * - If this is called in MPI, then this will create one pvtu file per timestep, per model part's gauss point container (will be having information of all the corresponding rank vtu files) + * + * Finally it will create one pvd ( @p rOutputFilenamePrefix .pvd ) file for all the model parts, all the timesteps all the gauss point container linking + * - In MPI the pvtu files created. + * - In shared memory parallelism the vtu files created. + * + * @param rOutputFilenamePrefix The prefix to use for the output filename. */ void PrintOutput(const std::string& rOutputFilenamePrefix); ///@} -private: - ///@name Private member variables + ///@name Input and output ///@{ - ModelPart& mrModelPart; /// Reference to the model part. + /// Turn back information as a string. + std::string Info() const override; - const bool mIsInitialConfiguration; /// Flag indicating if it is the initial configuration. + /// Print information about this object. + void PrintInfo(std::ostream& rOStream) const override; - const WriterFormat mOutputFormat; /// The output format for writing the model part. + /// Print object's data. + void PrintData(std::ostream& rOStream) const override; - const IndexType mPrecision; /// The precision used for writing floating-point values. + ///@} - bool mIsConditionsConsidered; /// Flag indicating if conditions are considered. +private: + ///@name Private member variables + ///@{ - bool mIsElementsConsidered; /// Flag indicating if elements are considered. + bool mIsPVDFileHeaderWritten; - // TODO: In the future study to replace the std::map - // TODO: Study replace string, expensive, with hashes or keys + ModelPart& mrModelPart; - std::unordered_map mKratosVtuIndicesMap; /// Map to store Kratos VTU indices. + const Globals::Configuration mConfiguration; - std::map mHistoricalVariablesMap; /// Map to store supported historical variables. + const IndexType mEchoLevel; - std::map mNonHistoricalNodalVariablesMap; /// Map to store supported non-historical nodal variables. + const WriterFormat mOutputFormat; - std::map mNonHistoricalCellVariablesMap; /// Map to store supported non-historical cell variables. + const IndexType mPrecision; - std::map mNodalFlagsMap; /// Map to store nodal flags. + DataList mFlags; - std::map mCellFlagsMap; /// Map to store cell flags. + DataList mVariables; - std::map::Pointer> mPointContainerExpressionsMap; /// Map to store point container expressions. + DataList mIntegrationPointVariables; - std::map mCellContainerExpressionsMap; /// Map to store supported cell container expressions. + std::vector mUnstructuredGridDataList; ///@} ///@name Private operations ///@{ - /** - * @brief Writes the model part to a file. - * @param rOutputFileNamePrefix The output file name prefix. - * @param rModelPart The model part to write. - */ - void PrintModelPart( - const std::string& rOutputFileNamePrefix, - ModelPart& rModelPart) const; + template + void WriteData( + std::vector>& rPVDFileNameInfo, + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, + const std::string& rOutputPrefix, + const IndexType Step) const; + + template + std::pair WriteUnstructuredGridData( + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, + const std::string& rOutputPrefix, + const IndexType Step) const; + + template + std::pair WriteIntegrationPointData( + TXmlElementDataWrapperCreateFunctor&& rElementDataWrapperCreateFunctor, + TXmlElementDataWrapperAppendFunctor&& rElementDataWrapperAppendFunctor, + UnstructuredGridData& rUnstructuredGridData, + const std::string& rOutputPrefix, + const IndexType Step) const; ///@} }; diff --git a/kratos/python/add_io_to_python.cpp b/kratos/python/add_io_to_python.cpp index 71c5d3c35509..59afd43cf832 100644 --- a/kratos/python/add_io_to_python.cpp +++ b/kratos/python/add_io_to_python.cpp @@ -209,40 +209,51 @@ void AddIOToPython(pybind11::module& m) py::enum_(vtu_output, "WriterFormat") .value("ASCII", VtuOutput::WriterFormat::ASCII) .value("BINARY", VtuOutput::WriterFormat::BINARY) - .export_values(); + .value("RAW", VtuOutput::WriterFormat::RAW) + .value("COMPRESSED_RAW", VtuOutput::WriterFormat::COMPRESSED_RAW) + .export_values() + ; vtu_output - .def(py::init(), py::arg("model_part"), py::arg("is_initial_configuration_considered") = true, py::arg("binary_output") = VtuOutput::WriterFormat::BINARY, py::arg("precision") = 9) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable, py::arg("int_variable")) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable, py::arg("double_variable")) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable>, py::arg("array3_variable")) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable>, py::arg("array4_variable")) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable>, py::arg("array6_variable")) - .def("AddHistoricalVariable", &VtuOutput::AddHistoricalVariable>, py::arg("array9_variable")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable, py::arg("int_variable"), py::arg("entity_flags")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable, py::arg("double_variable"), py::arg("entity_flags")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable>, py::arg("array3_variable"), py::arg("entity_flags")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable>, py::arg("array4_variable"), py::arg("entity_flags")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable>, py::arg("array6_variable"), py::arg("entity_flags")) - .def("AddNonHistoricalVariable", &VtuOutput::AddNonHistoricalVariable>, py::arg("array9_variable"), py::arg("entity_flags")) - .def("AddFlagVariable", &VtuOutput::AddFlagVariable, py::arg("flag_variable_name"), py::arg("flag"), py::arg("entity_flags")) - .def("AddContainerExpression", &VtuOutput::AddContainerExpression, py::arg("container_expression_name"), py::arg("container_expression")) - .def("AddContainerExpression", &VtuOutput::AddContainerExpression, py::arg("container_expression_name"), py::arg("container_expression")) - .def("AddContainerExpression", &VtuOutput::AddContainerExpression, py::arg("container_expression_name"), py::arg("container_expression")) - .def("ClearHistoricalVariables", &VtuOutput::ClearHistoricalVariables) - .def("ClearNodalNonHistoricalVariables", &VtuOutput::ClearNodalNonHistoricalVariables) - .def("ClearNodalFlags", &VtuOutput::ClearNodalFlags) - .def("ClearCellNonHistoricalVariables", &VtuOutput::ClearCellNonHistoricalVariables) - .def("ClearCellFlags", &VtuOutput::ClearCellFlags) - .def("ClearNodalContainerExpressions", &VtuOutput::ClearNodalContainerExpressions) - .def("ClearCellContainerExpressions", &VtuOutput::ClearCellContainerExpressions) + .def(py::init(), + py::arg("model_part"), + py::arg("is_initial_configuration") = true, + py::arg("output_format") = VtuOutput::WriterFormat::COMPRESSED_RAW, + py::arg("precision") = 9, + py::arg("output_sub_model_parts") = false, + py::arg("write_ids") = false, + py::arg("echo_level") = 0) + .def("AddFlag", &VtuOutput::AddFlag, py::arg("flag_name"), py::arg("flag"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) + .def("AddVariable", &VtuOutput::AddVariable, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable>, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) + .def("AddIntegrationPointVariable", &VtuOutput::AddIntegrationPointVariable, py::arg("variable"), py::arg("data_location")) + .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("AddTensorAdaptor", &VtuOutput::AddTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("ReplaceTensorAdaptor", &VtuOutput::ReplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) + .def("EmplaceTensorAdaptor", &VtuOutput::EmplaceTensorAdaptor::Pointer>, py::arg("tensor_adaptor_name"), py::arg("tensor_adaptor")) .def("GetModelPart", &VtuOutput::GetModelPart, py::return_value_policy::reference) + .def("GetOutputContainerList", &VtuOutput::GetOutputContainerList) .def("PrintOutput", &VtuOutput::PrintOutput, py::arg("output_file_name_prefix")) + .def("__str__", PrintObject) ; - - vtu_output.attr("NODES") = VtuOutput::NODES; - vtu_output.attr("CONDITIONS") = VtuOutput::CONDITIONS; - vtu_output.attr("ELEMENTS") = VtuOutput::ELEMENTS; } } // namespace Kratos::Python. diff --git a/kratos/python_scripts/compare_two_files_check_process.py b/kratos/python_scripts/compare_two_files_check_process.py index d4895bacbcaf..25575014dd0c 100644 --- a/kratos/python_scripts/compare_two_files_check_process.py +++ b/kratos/python_scripts/compare_two_files_check_process.py @@ -10,6 +10,7 @@ import filecmp import os import math +import xml.etree.ElementTree def Factory(settings, current_model): if not isinstance(settings, KratosMultiphysics.Parameters): @@ -104,6 +105,8 @@ def ExecuteFinalize(self): self.__CompareDatFileVariablesTimeHistory() elif (self.comparison_type == "vtk"): self.__CompareVtkFile() + elif (self.comparison_type == "vtu") or (self.comparison_type == "xml"): + self.__CompareXmlFile() else: raise NameError('Requested comparison type "' + self.comparison_type + '" not implemented yet') @@ -532,6 +535,32 @@ def CompareFieldData(lines_ref, lines_out, line_counter, num_entities): if line_ref.startswith("POINT_DATA") or line_ref.startswith("CELL_DATA"): CompareData(lines_ref, lines_out, line_counter) + def __CompareXmlFile(self): + """This function compares vtu files + """ + if not os.path.isfile(self.reference_file_name): + raise RuntimeError(f"The reference file \"{self.reference_file_name}\" is not found.") + + if not os.path.isfile(self.output_file_name): + raise RuntimeError(f"The output file \"{self.output_file_name}\" is not found.") + + ref_xml = xml.etree.ElementTree.parse(self.reference_file_name) + out_xml = xml.etree.ElementTree.parse(self.output_file_name) + + def check_element(ref_element: xml.etree.ElementTree.Element, out_element: xml.etree.ElementTree.Element): + if ref_element.tag != out_element.tag: + raise RuntimeError(f"The element tag mismatch [ ref element tag = {ref_element.tag}, output element tag = {out_element.tag} ].") + + if ref_element.attrib != out_element.attrib: + raise RuntimeError(f"The element tag mismatch [ ref element tag = {ref_element.tag}, output element tag = {out_element.tag} ].\nRef attribs:\n{ref_element.attrib}\nOut attribs:\n{out_element.attrib}") + + if ref_element.text != out_element.text: + raise RuntimeError(f"Data mismatch [ ref element tag = {ref_element.tag}, out element tag = {out_element.tag} ].\nRef attribs:\n{ref_element.attrib}\nRef data:\n{ref_element.text}\nOut attribs:\n{out_element.attrib}\nOut data:\n{out_element.text}") + + check_element(ref_xml.getroot(), out_xml.getroot()) + for ref_sub_element, out_sub_element in zip(ref_xml.getroot().iter(), out_xml.getroot().iter()): + check_element(ref_sub_element, out_sub_element) + def __CheckCloseValues(self, val_a, val_b, additional_info=""): isclosethis = t_isclose(val_a, val_b, rel_tol=self.reltol, abs_tol=self.tol) full_msg = self.info_msg + "\n" diff --git a/kratos/solving_strategies/builder_and_solvers/p_multigrid/status_stream.cpp b/kratos/solving_strategies/builder_and_solvers/p_multigrid/status_stream.cpp index 53af788cb046..8bf7654295b2 100644 --- a/kratos/solving_strategies/builder_and_solvers/p_multigrid/status_stream.cpp +++ b/kratos/solving_strategies/builder_and_solvers/p_multigrid/status_stream.cpp @@ -56,7 +56,7 @@ std::unique_ptr MakeVtuOutput(ModelPart& rModelPart, for (const std::string& r_variable_name : variable_names){ KRATOS_ERROR_IF_NOT(KratosComponents>::Has(r_variable_name)) << r_variable_name << " is not a registered variable name"; - p_output->AddHistoricalVariable(KratosComponents>::Get(r_variable_name)); + p_output->AddVariable(KratosComponents>::Get(r_variable_name), Globals::DataLocation::NodeHistorical); } KRATOS_CATCH("") diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test.FixedEdgeNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test.FixedEdgeNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test.FixedEdgeNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test.FixedEdgeNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test.MovingNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test.MovingNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test.MovingNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test.MovingNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii2D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii2D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/ascii3D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/ascii3D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary2D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary2D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test.FixedEdgeNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test.FixedEdgeNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test.FixedEdgeNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test.FixedEdgeNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test.MovingNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test.MovingNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test.MovingNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test.MovingNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary2D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary2D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary3D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary3D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary3D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary3D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/binary3D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/binary3D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/binary3D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test.MovingNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test.MovingNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test.MovingNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test.MovingNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw2D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw2D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/compressed_raw3D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/compressed_raw3D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw2D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw2D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test.FixedEdgeNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test.MovingNodes_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test.MovingNodes_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test.MovingNodes_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test.MovingNodes_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw2D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw2D/Main/test_elements_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw3D/Main.pvd b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main.pvd old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw3D/Main.pvd rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main.pvd diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw3D/Main/test_conditions_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main/test_conditions_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw3D/Main/test_conditions_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main/test_conditions_0.vtu diff --git a/kratos/future/tests/vtk_output_process_ref_files/raw3D/Main/test_elements_0.vtu b/kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main/test_elements_0.vtu old mode 100644 new mode 100755 similarity index 100% rename from kratos/future/tests/vtk_output_process_ref_files/raw3D/Main/test_elements_0.vtu rename to kratos/tests/auxiliar_files_for_python_unittest/vtk_output_process_ref_files/raw3D/Main/test_elements_0.vtu diff --git a/kratos/tests/cpp_tests/utilities/test_xml_utilities.cpp b/kratos/tests/cpp_tests/utilities/test_xml_utilities.cpp index 3f5c11563794..537fe6230e7c 100644 --- a/kratos/tests/cpp_tests/utilities/test_xml_utilities.cpp +++ b/kratos/tests/cpp_tests/utilities/test_xml_utilities.cpp @@ -12,44 +12,38 @@ // System includes #include -#include -#include // External includes // Project includes #include "testing/testing.h" -#include "utilities/xml_utilities/xml_expression_element.h" -#include "utilities/xml_utilities/xml_ostream_writer.h" -#include "utilities/xml_utilities/xml_ostream_ascii_writer.h" -#include "utilities/xml_utilities/xml_ostream_base64_binary_writer.h" -#include "expression/literal_flat_expression.h" +#include "utilities/xml_utilities/xml_elements_array.h" +#include "utilities/xml_utilities/xml_ascii_nd_data_element.h" +#include "utilities/xml_utilities/xml_base64_binary_nd_data_element.h" namespace Kratos::Testing { -KRATOS_TEST_CASE_IN_SUITE(XmlElementGetTagName, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayGetTagName, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); + XmlElementsArray element("TestElement"); KRATOS_EXPECT_EQ(element.GetTagName(), "TestElement"); } -KRATOS_TEST_CASE_IN_SUITE(XmlElementAddAndGetAttributes, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayAddAndGetAttributes, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); + XmlElementsArray element("TestElement"); element.AddAttribute("Attribute1", "Value1"); element.AddAttribute("Attribute2", "Value2"); auto attributes = element.GetAttributes(); - KRATOS_EXPECT_EQ(attributes[0].first, "Attribute1"); - KRATOS_EXPECT_EQ(attributes[0].second, "Value1"); - KRATOS_EXPECT_EQ(attributes[1].first, "Attribute2"); - KRATOS_EXPECT_EQ(attributes[1].second, "Value2"); + KRATOS_EXPECT_EQ(attributes["Attribute1"], "Value1"); + KRATOS_EXPECT_EQ(attributes["Attribute2"], "Value2"); } -KRATOS_TEST_CASE_IN_SUITE(XmlElementClearAttributes, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayClearAttributes, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); + XmlElementsArray element("TestElement"); element.AddAttribute("Attribute1", "Value1"); element.ClearAttributes(); @@ -57,33 +51,34 @@ KRATOS_TEST_CASE_IN_SUITE(XmlElementClearAttributes, KratosCoreFastSuite) KRATOS_EXPECT_EQ(attributes.size(), 0); } -KRATOS_TEST_CASE_IN_SUITE(XmlElementAddElement, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayAddElement, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); - auto childElement = Kratos::make_shared("ChildElement"); + XmlElementsArray element("TestElement"); + auto childElement = Kratos::make_shared("ChildElement"); element.AddElement(childElement); auto children = element.GetElements(); KRATOS_EXPECT_EQ(children[0]->GetTagName(), "ChildElement"); } -KRATOS_TEST_CASE_IN_SUITE(XmlElementGetElements, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayGetElements, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); - auto childElement1 = Kratos::make_shared("ChildElement"); - auto childElement2 = Kratos::make_shared("ChildElement2"); + XmlElementsArray element("TestElement"); + auto childElement1 = Kratos::make_shared("ChildElement"); + auto childElement2 = Kratos::make_shared("ChildElement2"); element.AddElement(childElement1); element.AddElement(childElement2); - auto children = element.GetElements("ChildElement"); - KRATOS_EXPECT_EQ(children.size(), 1); + auto children = element.GetElements(); + KRATOS_EXPECT_EQ(children.size(), 2); KRATOS_EXPECT_EQ(children[0]->GetTagName(), "ChildElement"); + KRATOS_EXPECT_EQ(children[1]->GetTagName(), "ChildElement2"); } -KRATOS_TEST_CASE_IN_SUITE(XmlElementClearElements, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayClearElements, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); - auto childElement = Kratos::make_shared("ChildElement"); + XmlElementsArray element("TestElement"); + auto childElement = Kratos::make_shared("ChildElement"); element.AddElement(childElement); element.ClearElements(); @@ -91,16 +86,15 @@ KRATOS_TEST_CASE_IN_SUITE(XmlElementClearElements, KratosCoreFastSuite) KRATOS_EXPECT_EQ(children.size(), 0); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWrite, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlElementsArrayWrite, KratosCoreFastSuite) { - XmlExpressionElement element("TestElement"); + XmlElementsArray element("TestElement"); element.AddAttribute("Attribute1", "Value1"); - auto childElement = Kratos::make_shared("ChildElement"); + auto childElement = Kratos::make_shared("ChildElement"); element.AddElement(childElement); std::stringstream ss; - XmlOStreamAsciiWriter writer(ss, 4); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), " \n" @@ -108,227 +102,129 @@ KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWrite, KratosCoreFastSuite) " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementAsciiChar, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlAsciiNDDataElementChar, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0U); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0U); + + XmlAsciiNDDataElement element("data_1", char_nd_data_1, 9); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamAsciiWriter writer(ss, 4); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" + " \n" " 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8\n" " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementAsciiInt, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlAsciiNDDataElementInt, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0U); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0U); + + XmlAsciiNDDataElement element("data_1", char_nd_data_1, 9); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamAsciiWriter writer(ss, 4); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" + " \n" " 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8\n" " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementAsciiDouble, KratosCoreFastSuite) -{ - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); - element.AddAttribute("attribute1", "value1"); - - std::stringstream ss; - XmlOStreamAsciiWriter writer(ss, 1); - writer.WriteElement(element, 1); - - KRATOS_EXPECT_EQ(ss.str(), - " \n" - " 0.0e+00 1.0e+00 2.0e+00 3.0e+00 4.0e+00 5.0e+00 0.0e+00 1.0e+00 2.0e+00 3.0e+00 4.0e+00 5.0e+00 6.0e+00 7.0e+00 8.0e+00\n" - " \n"); -} - -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementAsciiMixed, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlAsciiNDDataElementDouble, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0.0); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0.0); + + XmlAsciiNDDataElement element("data_1", char_nd_data_1, 1); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamAsciiWriter writer(ss, 1); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" + " \n" " 0.0e+00 1.0e+00 2.0e+00 3.0e+00 4.0e+00 5.0e+00 0.0e+00 1.0e+00 2.0e+00 3.0e+00 4.0e+00 5.0e+00 6.0e+00 7.0e+00 8.0e+00\n" " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementBinaryChar, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlBase64BinaryNDDataElementChar, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0U); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0U); + + XmlBase64BinaryNDDataElement element("data_1", char_nd_data_1); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamBase64BinaryWriter writer(ss); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" - " DwAAAAABAgMEBQABAgMEBQYHCA==\n" - " \n"); -} - -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementBinaryInt, KratosCoreFastSuite) -{ - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); - element.AddAttribute("attribute1", "value1"); - - std::stringstream ss; - XmlOStreamBase64BinaryWriter writer(ss); - writer.WriteElement(element, 1); - - KRATOS_EXPECT_EQ(ss.str(), - " \n" - " PAAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAA==\n" + " \n" + " DwAAAAAAAAAAAQIDBAUAAQIDBAUGBwg=\n" " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementBinaryDouble, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlBase64BinaryNDDataElementInt, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0U); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0U); + + XmlBase64BinaryNDDataElement element("data_1", char_nd_data_1); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamBase64BinaryWriter writer(ss); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" - " eAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAAAUQAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAAAUQAAAAAAAABhAAAAAAAAAHEAAAAAAAAAgQA==\n" + " \n" + " PAAAAAAAAAAAAAAAAQAAAAIAAAADAAAABAAAAAUAAAAAAAAAAQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAA=\n" " \n"); } -KRATOS_TEST_CASE_IN_SUITE(XmlOStreamWriterWriteDataElementBinaryMixed, KratosCoreFastSuite) +KRATOS_TEST_CASE_IN_SUITE(XmlBase64BinaryNDDataElementDouble, KratosCoreFastSuite) { - auto char_expression_1 = LiteralFlatExpression::Create(2, {3}); - std::size_t local_index = 0; - for (auto it = char_expression_1->begin(); it != char_expression_1->end(); ++it) { - *it = local_index++; - } - - auto char_expression_2 = LiteralFlatExpression::Create(3, {3}); - local_index = 0; - for (auto it = char_expression_2->begin(); it != char_expression_2->end(); ++it) { - *it = local_index++; - } - - std::vector expressions = {char_expression_1, char_expression_2}; - XmlExpressionElement element("data_1", expressions); + DenseVector shape(2, 0); + shape[0] = 5; shape[1] = 3; + auto char_nd_data_1 = Kratos::make_shared>(shape); + auto char_nd_data_1_view = char_nd_data_1->ViewData(); + std::iota(char_nd_data_1_view.begin(), char_nd_data_1_view.begin() + 6, 0U); + std::iota(char_nd_data_1_view.begin() + 6, char_nd_data_1_view.end(), 0U); + + XmlBase64BinaryNDDataElement element("data_1", char_nd_data_1); element.AddAttribute("attribute1", "value1"); std::stringstream ss; - XmlOStreamBase64BinaryWriter writer(ss); - writer.WriteElement(element, 1); + element.Write(ss, 1); KRATOS_EXPECT_EQ(ss.str(), - " \n" - " eAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAAAUQAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEAAAAAAAAAUQAAAAAAAABhAAAAAAAAAHEAAAAAAAAAgQA==\n" + " \n" + " eAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAEAAAAAAAAAIQAAAAAAAABBAAAAAAAAAFEAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAEAAAAAAAAAIQAAAAAAAABBAAAAAAAAAFEAAAAAAAAAYQAAAAAAAABxAAAAAAAAAIEA=\n" " \n"); } diff --git a/kratos/tests/test_vtu_output.py b/kratos/tests/test_vtu_output.py old mode 100644 new mode 100755 index 17680aa323f9..13a0c7015ab7 --- a/kratos/tests/test_vtu_output.py +++ b/kratos/tests/test_vtu_output.py @@ -1,8 +1,10 @@ +import math, typing +from pathlib import Path +import xml.etree.ElementTree as ET import KratosMultiphysics as Kratos - -# Import KratosUnittest import KratosMultiphysics.KratosUnittest as kratos_unittest +import KratosMultiphysics.kratos_utilities as kratos_utils from KratosMultiphysics.compare_two_files_check_process import CompareTwoFilesCheckProcess from test_vtk_output_process import SetupModelPart2D, SetupModelPart3D @@ -14,45 +16,55 @@ def SetSolution(cls): node.SetSolutionStepValue(Kratos.VELOCITY, 0,[node.X * 5, node.Y * 6, node.Z * 7]) node.SetSolutionStepValue(Kratos.PRESSURE, 0, node.Id * 8.0) + elem: Kratos.Element for i_elem, elem in enumerate(cls.model_part.Elements): elem.SetValue(Kratos.DETERMINANT, [i_elem*0.189, i_elem * 1.236, i_elem * 2.365]) + cond: Kratos.Condition for i_cond, cond in enumerate(cls.model_part.Conditions): cond.SetValue(Kratos.DENSITY, i_cond * 4.362) cond.SetValue(Kratos.YOUNG_MODULUS, i_cond * 5.326) + cond.SetValue(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Vector()) @classmethod - def setUpClass(cls, output_prefix: str, setup_method) -> None: + def setUpClass(cls, output_prefix: str, setup_method, output_sub_model_parts: bool) -> None: cls.model = Kratos.Model() cls.model_part = cls.model.CreateModelPart("test") + cls.model_part.ProcessInfo[Kratos.STEP] = 0 + cls.model_part.ProcessInfo[Kratos.TIME] = 1.0 cls.output_prefix = output_prefix + cls.output_sub_model_parts = output_sub_model_parts setup_method(cls.model_part) cls.SetSolution() - def WriteVtu(self, output_format: Kratos.VtuOutput.WriterFormat): - vtu_output = Kratos.VtuOutput(self.model_part, True, output_format, 9) - vtu_output.AddHistoricalVariable(Kratos.PRESSURE) - vtu_output.AddHistoricalVariable(Kratos.VELOCITY) - vtu_output.AddHistoricalVariable(Kratos.DISPLACEMENT) - vtu_output.AddNonHistoricalVariable(Kratos.DETERMINANT, vtu_output.ELEMENTS) - - a = Kratos.Expression.NodalExpression(self.model_part) - Kratos.Expression.VariableExpressionIO.Read(a, Kratos.PRESSURE, True) - a *= 3 - vtu_output.AddContainerExpression("hist_exp", a) - - a = Kratos.Expression.ElementExpression(self.model_part) - Kratos.Expression.VariableExpressionIO.Read(a, Kratos.DETERMINANT) - a *= 3 - vtu_output.AddContainerExpression("elem_exp", a) - - with kratos_unittest.WorkFolderScope("./auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): - if output_format == Kratos.VtuOutput.ASCII: - output_file_prefix = "ascii" + self.output_prefix + "/Main" - else: - output_file_prefix = "binary" + self.output_prefix + "/Main" - vtu_output.PrintOutput(output_file_prefix + "_temp") - self.Check(output_file_prefix + "_temp.vtu", output_file_prefix + ".vtu") + def WriteVtu(self, output_format: Kratos.VtuOutput.WriterFormat, error_check = False): + vtu_output = Kratos.VtuOutput(self.model_part, True, output_format, 9, echo_level=0, output_sub_model_parts=self.output_sub_model_parts, write_ids=True) + vtu_output.AddVariable(Kratos.PRESSURE, Kratos.Globals.DataLocation.NodeHistorical) + vtu_output.AddVariable(Kratos.VELOCITY, Kratos.Globals.DataLocation.NodeHistorical) + vtu_output.AddVariable(Kratos.DISPLACEMENT, Kratos.Globals.DataLocation.NodeHistorical) + vtu_output.AddVariable(Kratos.DETERMINANT, Kratos.Globals.DataLocation.Element) + vtu_output.AddVariable(Kratos.DENSITY, Kratos.Globals.DataLocation.Condition) + vtu_output.AddVariable(Kratos.YOUNG_MODULUS, Kratos.Globals.DataLocation.Condition) + if error_check: + # adds a vector with zero size to check for the error. Because, in vtu lib, + # if the behavior is undefined if the "NumberOfComponents = 0". + vtu_output.AddVariable(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Globals.DataLocation.Condition) + + ta_1 = Kratos.TensorAdaptors.HistoricalVariableTensorAdaptor(self.model_part.Nodes, Kratos.PRESSURE) + ta_1.CollectData() + ta_2 = Kratos.TensorAdaptors.VariableTensorAdaptor(self.model_part.Elements, Kratos.DETERMINANT) + ta_2.CollectData() + + ta_1.data *= 3 + ta_2.data *= 3 + + vtu_output.AddTensorAdaptor("hist_ta", ta_1) + vtu_output.AddTensorAdaptor("elem_ta", ta_2) + + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + output_file_prefix = output_format.name.lower() + self.output_prefix + "/Main" + vtu_output.PrintOutput("temp/" + output_file_prefix) + self.Check("temp/" + output_file_prefix, output_file_prefix) def test_WriteMeshAscii(self): self.WriteVtu(Kratos.VtuOutput.ASCII) @@ -60,27 +72,528 @@ def test_WriteMeshAscii(self): def test_WriteMeshBinary(self): self.WriteVtu(Kratos.VtuOutput.BINARY) - def Check(self, output_file, reference_file): - ## Settings string in json format - params = Kratos.Parameters("""{ - "reference_file_name" : "", - "output_file_name" : "", - "comparison_type" : "deterministic" - }""") - params["reference_file_name"].SetString(reference_file) - params["output_file_name"].SetString(output_file) - CompareTwoFilesCheckProcess(params).Execute() + def test_WriteMeshRaw(self): + self.WriteVtu(Kratos.VtuOutput.RAW) + + def test_WriteMeshCompressedRaw(self): + self.WriteVtu(Kratos.VtuOutput.COMPRESSED_RAW) + + def test_WriteMeshAsciiWithError(self): + with self.assertRaises(RuntimeError): + self.WriteVtu(Kratos.VtuOutput.ASCII, True) + + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteFileIfExisting("temp/ascii2D/Main/test_elements_0.vtu") + kratos_utils.DeleteFileIfExisting("temp/ascii3D/Main/test_elements_0.vtu") + + def test_WriteMeshBinaryWithError(self): + with self.assertRaises(RuntimeError): + self.WriteVtu(Kratos.VtuOutput.BINARY, True) + + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteFileIfExisting("temp/binary2D/Main/test_elements_0.vtu") + kratos_utils.DeleteFileIfExisting("temp/binary3D/Main/test_elements_0.vtu") + + def test_WriteMeshRawWithError(self): + with self.assertRaises(RuntimeError): + self.WriteVtu(Kratos.VtuOutput.RAW, True) + + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteFileIfExisting("temp/raw2D/Main/test_elements_0.vtu") + kratos_utils.DeleteFileIfExisting("temp/raw3D/Main/test_elements_0.vtu") + + def test_WriteMeshCompressedRawWithError(self): + with self.assertRaises(RuntimeError): + self.WriteVtu(Kratos.VtuOutput.COMPRESSED_RAW, True) + + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteFileIfExisting("temp/compressed_raw2D/Main/test_elements_0.vtu") + kratos_utils.DeleteFileIfExisting("temp/compressed_raw3D/Main/test_elements_0.vtu") + + def Check(self, output_prefix, reference_prefix): + def check_file(output_file_name: str, reference_file_name: str): + ## Settings string in json format + params = Kratos.Parameters("""{ + "reference_file_name" : "", + "output_file_name" : "", + "comparison_type" : "deterministic" + }""") + params["reference_file_name"].SetString(reference_file_name) + params["output_file_name"].SetString(output_file_name) + CompareTwoFilesCheckProcess(params).Execute() + + for file_path in Path(reference_prefix).iterdir(): + self.assertTrue((Path(output_prefix) / file_path.name).is_file(), msg=f"\"{(Path(output_prefix) / file_path.name)}\" is not a file.") + check_file(f"{output_prefix}/{file_path.name}", str(file_path)) + check_file(f"{output_prefix}.pvd", f"{reference_prefix}.pvd") class TestVtuOutput2D(TestVtuOutputBase, kratos_unittest.TestCase): @classmethod def setUpClass(cls) -> None: - super().setUpClass("2D", SetupModelPart2D) + super().setUpClass("2D", SetupModelPart2D, output_sub_model_parts = True) + + def tearDown(self): + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteDirectoryIfExistingAndEmpty("temp") class TestVtuOutput3D(TestVtuOutputBase, kratos_unittest.TestCase): @classmethod def setUpClass(cls) -> None: - super().setUpClass("3D", SetupModelPart3D) + # the method SetupModelPart3D does not create sub model parts + # with nodes which do not include nodes from its conditions or elements. It uses + # some random nodes. Hence sub_model_part output is disabled. + super().setUpClass("3D", SetupModelPart3D, output_sub_model_parts = False) + + def tearDown(self): + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteDirectoryIfExistingAndEmpty("temp") + +class TestVtuOutput(kratos_unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.data_location = Kratos.Globals.DataLocation + + cls.model = Kratos.Model() + cls.model_part = cls.model.CreateModelPart("test") + cls.model_part.AddNodalSolutionStepVariable(Kratos.STEP) + cls.model_part.AddNodalSolutionStepVariable(Kratos.PRESSURE) + cls.model_part.AddNodalSolutionStepVariable(Kratos.DISPLACEMENT) + cls.model_part.AddNodalSolutionStepVariable(Kratos.DETERMINANTS_OF_JACOBIAN_PARENT) + cls.model_part.AddNodalSolutionStepVariable(Kratos.CONSTITUTIVE_MATRIX) + + cls.model_part.ProcessInfo[Kratos.TIME] = 1 + + # creating a circular pie with origin (0, 0) + radius = 1.0 + number_of_elements_or_conditions = 50 + angle = 2 * math.pi / number_of_elements_or_conditions + + cls.model_part.CreateNewNode(1, 0, 0, 0) # origin node + for i in range(number_of_elements_or_conditions): + theta = i * angle + cls.model_part.CreateNewNode(i + 2, radius * math.cos(theta), radius * math.sin(theta), 0.0) + + prop = cls.model_part.CreateNewProperties(1) + for i in range(number_of_elements_or_conditions): + cls.model_part.CreateNewElement("Element2D3N", i + 1, [1, i + 2, (i + 1) % (number_of_elements_or_conditions) + 2], prop) + cls.model_part.CreateNewCondition("LineCondition2D2N", i + 1, [i + 2, (i + 1) % (number_of_elements_or_conditions) + 2], prop) + + # create the sub model part structure + for j in range(4): + l_1 = j // 9 + l_2 = (j // 3) % 3 + l_3 = j % 3 + model_part = cls.model_part.CreateSubModelPart(f"mp_{l_1}.mp_{l_2}.mp_{l_3}") + # fill the sub range + for i in range(number_of_elements_or_conditions): + if (j % 2 == 0): + if (i % ((l_1 + 1) * (l_2 + 1) * (l_3 + 1)) == 0): + model_part.AddCondition(cls.model_part.GetCondition(i + 1)) + else: + if (i % ((l_1 + 1) * (l_2 + 1) * (l_3 + 1)) == 1): + model_part.AddElement(cls.model_part.GetElement(i + 1)) + + # now recursively fill the nodes + def fill_nodes(model_part: Kratos.ModelPart): + list_of_node_ids: 'list[int]' = [] + for condition in model_part.Conditions: + for node in condition.GetGeometry(): + list_of_node_ids.append(node.Id) + for element in model_part.Elements: + for node in element.GetGeometry(): + list_of_node_ids.append(node.Id) + + model_part.AddNodes(list_of_node_ids) + + for sub_model_part in model_part.SubModelParts: + fill_nodes(sub_model_part) + + fill_nodes(cls.model_part) + + def add_variables(container, setter): + for entity in container: + setter(entity, Kratos.STEP, entity.Id * 2) + setter(entity, Kratos.PRESSURE, entity.Id) + setter(entity, Kratos.DISPLACEMENT, Kratos.Array3([entity.Id, entity.Id + 1, entity.Id + 2])) + setter(entity, Kratos.DETERMINANTS_OF_JACOBIAN_PARENT, Kratos.Vector([entity.Id, entity.Id + 1, entity.Id + 2, entity.Id + 3, entity.Id + 4])) + setter(entity, Kratos.CONSTITUTIVE_MATRIX, Kratos.Matrix([[entity.Id, entity.Id + 1], [entity.Id + 2, entity.Id + 3], [entity.Id + 4, entity.Id + 5]])) + + add_variables(cls.model_part.Nodes, lambda x, y, z: x.SetSolutionStepValue(y, z)) + add_variables(cls.model_part.Nodes, lambda x, y, z: x.SetValue(y, z)) + add_variables(cls.model_part.Conditions, lambda x, y, z: x.SetValue(y, z)) + add_variables(cls.model_part.Elements, lambda x, y, z: x.SetValue(y, z)) + + def setUp(self): + self.model_part.ProcessInfo[Kratos.STEP] = 0 + + def test_GetOutputContainerList(self): + unstructured_grid_list = self.GetUnstructuredGridList(self.model_part, self.model_part.GetRootModelPart().GetCommunicator().GetDataCommunicator(), True) + + vtu_output = Kratos.VtuOutput(self.model_part, output_sub_model_parts=True, output_format=Kratos.VtuOutput.BINARY) + list_of_containers = vtu_output.GetOutputContainerList() + + list_of_ref_containers = [] + for mp, is_nodes_used, cells_container in unstructured_grid_list: + if is_nodes_used: + list_of_ref_containers.append(mp.Nodes) + list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Nodes) + + if cells_container is not None: + list_of_ref_containers.append(cells_container) + if isinstance(cells_container, Kratos.ConditionsArray): + list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Conditions) + elif isinstance(cells_container, Kratos.ElementsArray): + list_of_ref_containers.append(mp.GetCommunicator().LocalMesh().Elements) + + self.assertEqual(list_of_containers, list_of_ref_containers) + + def test_PointVariableAddition(self): + vtu_output = Kratos.VtuOutput(self.model_part, output_sub_model_parts=True, output_format=Kratos.VtuOutput.BINARY) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Condition) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Element) + vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Condition) + vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Element) + + with self.assertRaises(RuntimeError): + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) + + with self.assertRaises(RuntimeError): + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeNonHistorical) + + ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Nodes, Kratos.DoubleNDData([51, 5])) + ta.Check() + with self.assertRaises(RuntimeError): + vtu_output.AddTensorAdaptor("PRESSURE", ta) + vtu_output.AddTensorAdaptor("PRESSURE_1", ta) + + with self.assertRaises(RuntimeError): + vtu_output.AddTensorAdaptor("PRESSURE_1", ta) + vtu_output.AddTensorAdaptor("PRESSURE_2", ta) + + ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Conditions, Kratos.DoubleNDData([50,2,4])) + ta.Check() + with self.assertRaises(RuntimeError): + vtu_output.AddTensorAdaptor("PRESSURE", ta) + vtu_output.AddTensorAdaptor("PRESSURE_1", ta) + vtu_output.AddTensorAdaptor("PRESSURE_2", ta) + vtu_output.AddTensorAdaptor("PRESSURE_3", ta) + + ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(self.model_part.Elements, Kratos.DoubleNDData([50,2,5])) + ta.Check() + with self.assertRaises(RuntimeError): + vtu_output.AddTensorAdaptor("PRESSURE", ta) + vtu_output.AddTensorAdaptor("PRESSURE_1", ta) + vtu_output.AddTensorAdaptor("PRESSURE_2", ta) + vtu_output.AddTensorAdaptor("PRESSURE_3", ta) + + vtu_output.PrintOutput("temp/vtu_output/variable_test") + + model_part = vtu_output.GetModelPart() + unstructured_grid_list = self.GetUnstructuredGridList(model_part, model_part.GetCommunicator().GetDataCommunicator(), True) + list_of_vtu_file_names: 'list[str]' = [] + for model_part, use_nodes, container in unstructured_grid_list: + vtu_file_name = TestVtuOutput.GetUnstructuredGridName((model_part, use_nodes, container), "temp/vtu_output/variable_test", 0, model_part.GetCommunicator().GetDataCommunicator()) + list_of_vtu_file_names.append(vtu_file_name) + if model_part.FullName() == "test": + if use_nodes: + TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "binary", + { + "PRESSURE": (1, "Float64"), + "PRESSURE_1": (5, "Float64"), + "PRESSURE_2": (5, "Float64") + }, + { + "PRESSURE": (1, "Float64") + }) + elif isinstance(container, Kratos.ConditionsArray): + TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", + {}, + { + "PRESSURE": (1, "Float64"), + "PRESSURE_1": (8, "Float64"), + "PRESSURE_2": (8, "Float64"), + "PRESSURE_3": (8, "Float64") + }) + elif isinstance(container, Kratos.ElementsArray): + TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", + { + "PRESSURE": (1, "Float64"), + "PRESSURE_1": (5, "Float64"), + "PRESSURE_2": (1, "Float64"), + "PRESSURE_3": (5, "Float64") + }, + { + "PRESSURE": (1, "Float64"), + "PRESSURE_1": (10, "Float64"), + "PRESSURE_2": (10, "Float64"), + "PRESSURE_3": (10, "Float64") + }) + else: + if use_nodes: + TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "binary", + { + "PRESSURE": (1, "Float64") + }, + { + "PRESSURE": (1, "Float64") + }) + else: + TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "binary", + { + }, + { + "PRESSURE": (1, "Float64") + }) + # check gauss + list_of_vtu_file_names.append(TestVtuOutput.CheckGaussVtuFile(self, model_part, container, "temp/vtu_output/variable_test", 0, "binary", model_part.GetCommunicator().GetDataCommunicator(), + { + "PRESSURE": (1, "Float64") + })) + TestVtuOutput.CheckPvdFile(self, "temp/vtu_output/variable_test.pvd", list_of_vtu_file_names, [1 + 1e-9]) + + def test_CellVariableAddition(self): + vtu_output = Kratos.VtuOutput(self.model_part, output_format=Kratos.VtuOutput.ASCII, output_sub_model_parts=True) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Condition) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.NodeHistorical) + vtu_output.AddVariable(Kratos.PRESSURE, self.data_location.Element) + vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Condition) + vtu_output.AddIntegrationPointVariable(Kratos.PRESSURE, self.data_location.Element) + + vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.Element) + vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.NodeHistorical) + vtu_output.AddVariable(Kratos.DISPLACEMENT, self.data_location.Condition) + vtu_output.AddIntegrationPointVariable(Kratos.DISPLACEMENT, self.data_location.Condition) + vtu_output.AddIntegrationPointVariable(Kratos.DISPLACEMENT, self.data_location.Element) + + vtu_output.PrintOutput("temp/vtu_output/time_step_test") + vtu_output.GetModelPart().ProcessInfo[Kratos.TIME] += 1e-9 + vtu_output.GetModelPart().ProcessInfo[Kratos.STEP] += 1 + vtu_output.PrintOutput("temp/vtu_output/time_step_test") + + model_part = vtu_output.GetModelPart() + unstructured_grid_list = self.GetUnstructuredGridList(model_part, model_part.GetCommunicator().GetDataCommunicator(), True) + list_of_vtu_file_names: 'list[str]' = [] + for step in range(2): + for model_part, use_nodes, container in unstructured_grid_list: + vtu_file_name = TestVtuOutput.GetUnstructuredGridName((model_part, use_nodes, container), "temp/vtu_output/time_step_test", step, model_part.GetCommunicator().GetDataCommunicator()) + list_of_vtu_file_names.append(vtu_file_name) + if use_nodes: + TestVtuOutput.CheckVtuFile(self, vtu_file_name, model_part.NumberOfNodes(), len(container), "ascii", + { + "PRESSURE": (1, "Float64"), + "DISPLACEMENT": (3, "Float64") + }, + { + "PRESSURE": (1, "Float64"), + "DISPLACEMENT": (3, "Float64") + }) + else: + TestVtuOutput.CheckVtuFile(self, vtu_file_name, TestVtuOutput.GetNumberOfNodes(container), len(container), "ascii", + { + }, + { + "PRESSURE": (1, "Float64"), + "DISPLACEMENT": (3, "Float64") + }) + + # check gauss + list_of_vtu_file_names.append(TestVtuOutput.CheckGaussVtuFile(self, model_part, container, "temp/vtu_output/time_step_test", step, "ascii", model_part.GetCommunicator().GetDataCommunicator(), + { + "DISPLACEMENT": (3, "Float64") + })) + + TestVtuOutput.CheckPvdFile(self, "temp/vtu_output/time_step_test.pvd", list_of_vtu_file_names, [1, 1 + 1e-9]) + + @staticmethod + def GetUnstructuredGridList(model_part: Kratos.ModelPart, data_communicator: Kratos.DataCommunicator, recursively: bool) -> 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]': + unstructured_grid_list: 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]' = [] + TestVtuOutput.__GetUnstructuredGridList(unstructured_grid_list, model_part, data_communicator, recursively) + return sorted(unstructured_grid_list, key = lambda x: x[0].FullName()) + + @staticmethod + def GetUnstructuredGridName(unstructured_grid: 'tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]', prefix: str, step: int, data_communicator: Kratos.DataCommunicator, entity_suffix = "s") -> str: + if data_communicator.IsDistributed(): + rank_suffix = f"_{data_communicator.Rank()}" + else: + rank_suffix = "" + + if unstructured_grid[2] is None: + entity_type = "node" + elif isinstance(unstructured_grid[2], Kratos.ConditionsArray): + entity_type = "condition" + elif isinstance(unstructured_grid[2], Kratos.ElementsArray): + entity_type = "element" + return f"{prefix}/{unstructured_grid[0].FullName()}_{entity_type}{entity_suffix}_{step}{rank_suffix}.vtu" + + @staticmethod + def GetNodes(model_part: Kratos.ModelPart, use_model_part_nodes: bool, container: 'typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]') -> 'list[Kratos.Node]': + if use_model_part_nodes: + return model_part.Nodes + else: + temp = [] + for entity in container: + for node in entity.GetGeometry(): + temp.append(node.Id) + return [model_part.GetRootModelPart().GetNode(node_id) for node_id in list(sorted(set(temp)))] + + def GetNumberOfNodes(container: 'typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]') -> int: + temp = [] + for entity in container: + for node in entity.GetGeometry(): + temp.append(node.Id) + return len(list(set(temp))) + + @staticmethod + def CheckDataArray(test_class: kratos_unittest.TestCase, xml_element: ET.Element, number_of_components: int, name: str, data_type: str, data_format: 'typing.Optional[str]' = None): + test_class.assertEqual(xml_element.get("NumberOfComponents"), str(number_of_components)) + test_class.assertEqual(xml_element.get("type"), data_type) + test_class.assertEqual(xml_element.get("Name"), name) + if data_format is not None: + test_class.assertEqual(xml_element.get("format"), data_format) + + @staticmethod + def CheckVtuFile( + test_class: kratos_unittest.TestCase, + vtu_file_name: str, + number_of_points: int, + number_of_cells: 'typing.Optional[int]', + data_format : str, + point_data_fields: 'dict[str, tuple[int, str]]', + cell_data_fields: 'dict[str, tuple[int, str]]'): + + test_class.assertTrue(Path(vtu_file_name).is_file(), f"The file {vtu_file_name} not found.") + tree = ET.parse(vtu_file_name) + root = tree.getroot() + + test_class.assertEqual(root.tag, "VTKFile") + test_class.assertEqual(root.get("type"), "UnstructuredGrid") + test_class.assertEqual(root.get("version"), "0.1") + + unstructured_grid = root.find("UnstructuredGrid") + piece = unstructured_grid.find("Piece") + + if number_of_cells is None: + local_number_of_cells = 0 + else: + local_number_of_cells = number_of_cells + + test_class.assertEqual(piece.get("NumberOfPoints"), f"{number_of_points}", f"Vtu file name = {vtu_file_name}") + test_class.assertEqual(piece.get("NumberOfCells"), f"{local_number_of_cells}", f"Vtu file name = {vtu_file_name}") + + points = piece.find("Points") + TestVtuOutput.CheckDataArray(test_class, points.find("DataArray"), 3, "Position", "Float64", data_format) + + cells = piece.find("Cells") + if not number_of_cells is None: + data_arrays = cells.findall("DataArray") + TestVtuOutput.CheckDataArray(test_class, data_arrays[0], 1, "connectivity", "Int32", data_format) + TestVtuOutput.CheckDataArray(test_class, data_arrays[1], 1, "offsets", "Int32", data_format) + TestVtuOutput.CheckDataArray(test_class, data_arrays[2], 1, "types", "UInt8", data_format) + + # now checking for point data + point_data = piece.find("PointData") + for data_field_name, (data_field_number_of_components, data_field_data_type) in point_data_fields.items(): + found = False + for point_data_array in point_data.findall("DataArray"): + if point_data_array.get("Name") == data_field_name: + TestVtuOutput.CheckDataArray(test_class, point_data_array, data_field_number_of_components, data_field_name, data_field_data_type, data_format) + found = True + break + test_class.assertTrue(found, f"Point data field \"{data_field_name}\" not found in the \"{vtu_file_name}\"") + + if not number_of_cells is None: + # now checking for cell data + cell_data = piece.find("CellData") + for data_field_name, (data_field_number_of_components, data_field_data_type) in cell_data_fields.items(): + found = False + for point_data_array in cell_data.findall("DataArray"): + if point_data_array.get("Name") == data_field_name: + TestVtuOutput.CheckDataArray(test_class, point_data_array, data_field_number_of_components, data_field_name, data_field_data_type, data_format) + found = True + break + test_class.assertTrue(found, f"Cell data field \"{data_field_name}\" not found in the \"{vtu_file_name}\"") + kratos_utils.DeleteFileIfExisting(vtu_file_name) + + @staticmethod + def CheckPvdFile(test_class: kratos_unittest.TestCase, pvd_file_name: str, vtu_file_name_list: 'list[str]', time_step_list: 'list[float]'): + test_class.assertTrue(Path(pvd_file_name).is_file(), f"The file {pvd_file_name} not found.") + tree = ET.parse(pvd_file_name) + root = tree.getroot() + + test_class.assertEqual(root.tag, "VTKFile") + test_class.assertEqual(root.get("type"), "Collection") + test_class.assertEqual(root.get("version"), "1.0") + + collection = root.find("Collection") + datasets = collection.findall("DataSet") + test_class.assertEqual(len(datasets), len(vtu_file_name_list), f"file name = {pvd_file_name}, list_of_time_steps = {time_step_list}, list_of_vtu_files = \n" + "\n\t".join(vtu_file_name_list)) + for i, dataset in enumerate(datasets): + relative_path = Path(vtu_file_name_list[i]).absolute().relative_to(Path(pvd_file_name).absolute().parent) + test_class.assertEqual(dataset.get("file"), str(relative_path)) + test_class.assertEqual(dataset.get("name"), relative_path.name[:relative_path.name.rfind("_")]) + test_class.assertEqual(dataset.get("part"), str(i % (len(vtu_file_name_list) // len(time_step_list)))) + test_class.assertEqual(dataset.get("timestep"), f"{time_step_list[i // (len(vtu_file_name_list) // len(time_step_list))]:0.9e}", f"file name = {relative_path}") + kratos_utils.DeleteFileIfExisting(pvd_file_name) + + @staticmethod + def CheckGaussVtuFile(test_class: kratos_unittest.TestCase, model_part: Kratos.ModelPart, container, prefix: str, step_id: int, output_type: str, data_communicator: Kratos.DataCommunicator, point_fields): + number_of_points = 0 + for entity in container: + if len(entity.GetGeometry()) == 4: + number_of_points += 4 + elif len(entity.GetGeometry()) == 3: + number_of_points += 1 + elif len(entity.GetGeometry()) == 2: + number_of_points += 1 + else: + raise RuntimeError("Unsupported geometry") + + if isinstance(container, Kratos.ConditionsArray): + suffix = "condition" + elif isinstance(container, Kratos.ElementsArray): + suffix = "element" + else: + raise RuntimeError("Unsupported container type.") + + if data_communicator.IsDistributed(): + rank_suffix = f"_{data_communicator.Rank()}" + else: + rank_suffix = "" + + file_name = f"{prefix}/{model_part.FullName()}_{suffix}_gauss_{step_id}{rank_suffix}.vtu" + TestVtuOutput.CheckVtuFile( + test_class, + file_name, + number_of_points, None, output_type, point_fields, {}) + kratos_utils.DeleteFileIfExisting(file_name) + return file_name + + @staticmethod + def __GetUnstructuredGridList(unstructured_grid_list: 'list[tuple[Kratos.ModelPart, bool, typing.Optional[typing.Union[Kratos.ConditionsArray, Kratos.ElementsArray]]]]', model_part: Kratos.ModelPart, data_communicator: Kratos.DataCommunicator, recursively: bool) -> None: + availability = data_communicator.MaxAll(Kratos.Array3([model_part.NumberOfNodes(), model_part.NumberOfConditions(), model_part.NumberOfElements()])) + has_nodes = availability[0] > 0 + has_conditions = availability[1] > 0 + has_elements = availability[2] > 0 + + if has_elements: + unstructured_grid_list.append((model_part, has_nodes, model_part.Elements)) + + if has_conditions: + unstructured_grid_list.append((model_part, not has_elements and has_nodes, model_part.Conditions)) + + if not has_elements and not has_conditions: + unstructured_grid_list.append((model_part, has_nodes, None)) + + if recursively: + for sub_model_part in model_part.SubModelParts: + TestVtuOutput.__GetUnstructuredGridList(unstructured_grid_list, sub_model_part, data_communicator, recursively) + + @classmethod + def tearDownClass(cls): + with kratos_unittest.WorkFolderScope("auxiliar_files_for_python_unittest/vtk_output_process_ref_files", __file__, True): + kratos_utils.DeleteDirectoryIfExistingAndEmpty("temp") if __name__ == "__main__": - Kratos.Logger.GetDefaultOutput().SetSeverity(Kratos.Logger.Severity.WARNING) + Kratos.Logger.GetDefaultOutput().SetSeverity(Kratos.Logger.Severity.INFO) kratos_unittest.main() \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp b/kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp similarity index 98% rename from kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp rename to kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp index ee8afacfd8c7..b1256ce330d9 100644 --- a/kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp +++ b/kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.cpp @@ -23,7 +23,7 @@ // Include base h #include "xml_appended_data_element_wrapper.h" -namespace Kratos::Future { +namespace Kratos { XmlAppendedDataElementWrapper::XmlAppendedDataElementWrapper(const XmlOutputType OutputType) : BaseType("AppendedData"), @@ -128,7 +128,7 @@ void XmlAppendedDataElementWrapper::Write( rOStream.write(mData.data(), mData.size()); - rOStream << "\n"; + rOStream << std::endl; this->WriteElementTagEnd(rOStream, Level); } @@ -136,4 +136,4 @@ void XmlAppendedDataElementWrapper::Write( KRATOS_CATCH(""); } -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.h b/kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.h similarity index 96% rename from kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.h rename to kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.h index 9ffe3e56889c..499379ab152c 100644 --- a/kratos/future/utilities/xml_utilities/xml_appended_data_element_wrapper.h +++ b/kratos/utilities/xml_utilities/xml_appended_data_element_wrapper.h @@ -19,7 +19,7 @@ #include "containers/nd_data.h" #include "xml_data_element_wrapper.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -82,4 +82,4 @@ class KRATOS_API(KRATOS_CORE) XmlAppendedDataElementWrapper : public XmlDataElem ///@} }; -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.cpp b/kratos/utilities/xml_utilities/xml_ascii_nd_data_element.cpp similarity index 95% rename from kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.cpp rename to kratos/utilities/xml_utilities/xml_ascii_nd_data_element.cpp index f03643be5400..8ac3eb80773a 100644 --- a/kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.cpp +++ b/kratos/utilities/xml_utilities/xml_ascii_nd_data_element.cpp @@ -20,7 +20,7 @@ // Include base h #include "xml_ascii_nd_data_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -65,7 +65,7 @@ void XmlAsciiNDDataElement::Write( } } - rOStream << "\n"; + rOStream << std::endl; this->WriteElementTagEnd(rOStream, Level); } @@ -79,4 +79,4 @@ template class XmlAsciiNDDataElement; template class XmlAsciiNDDataElement; template class XmlAsciiNDDataElement; -} // namespace Kratos::Future +} // namespace Kratos diff --git a/kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.h b/kratos/utilities/xml_utilities/xml_ascii_nd_data_element.h similarity index 95% rename from kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.h rename to kratos/utilities/xml_utilities/xml_ascii_nd_data_element.h index f6c760c2ca1b..b92e5e28a14d 100644 --- a/kratos/future/utilities/xml_utilities/xml_ascii_nd_data_element.h +++ b/kratos/utilities/xml_utilities/xml_ascii_nd_data_element.h @@ -20,7 +20,7 @@ #include "containers/nd_data.h" #include "xml_nd_data_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -67,4 +67,4 @@ class KRATOS_API(KRATOS_CORE) XmlAsciiNDDataElement : public XmlNDDataElement::Write( base64_encoder.WriteData(span.begin(), span.size()); } - rOStream << "\n"; + rOStream << std::endl; this->WriteElementTagEnd(rOStream, Level); } @@ -77,4 +77,4 @@ template class XmlBase64BinaryNDDataElement; template class XmlBase64BinaryNDDataElement; template class XmlBase64BinaryNDDataElement; -} // namespace Kratos::Future +} // namespace Kratos diff --git a/kratos/future/utilities/xml_utilities/xml_base64_binary_nd_data_element.h b/kratos/utilities/xml_utilities/xml_base64_binary_nd_data_element.h similarity index 95% rename from kratos/future/utilities/xml_utilities/xml_base64_binary_nd_data_element.h rename to kratos/utilities/xml_utilities/xml_base64_binary_nd_data_element.h index 54cfe3f3b585..9c9ec066477e 100644 --- a/kratos/future/utilities/xml_utilities/xml_base64_binary_nd_data_element.h +++ b/kratos/utilities/xml_utilities/xml_base64_binary_nd_data_element.h @@ -20,7 +20,7 @@ #include "containers/nd_data.h" #include "xml_nd_data_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -59,4 +59,4 @@ class KRATOS_API(KRATOS_CORE) XmlBase64BinaryNDDataElement : public XmlNDDataEle ///@} -} // namespace Kratos::Future +} // namespace Kratos diff --git a/kratos/future/utilities/xml_utilities/xml_data_element_wrapper.cpp b/kratos/utilities/xml_utilities/xml_data_element_wrapper.cpp similarity index 96% rename from kratos/future/utilities/xml_utilities/xml_data_element_wrapper.cpp rename to kratos/utilities/xml_utilities/xml_data_element_wrapper.cpp index 7a7f35613d59..088cba6d585f 100644 --- a/kratos/future/utilities/xml_utilities/xml_data_element_wrapper.cpp +++ b/kratos/utilities/xml_utilities/xml_data_element_wrapper.cpp @@ -20,7 +20,7 @@ // Include base h #include "xml_data_element_wrapper.h" -namespace Kratos::Future { +namespace Kratos { XmlDataElementWrapper::XmlDataElementWrapper(const std::string& rTagName) : XmlElement(rTagName) @@ -54,4 +54,4 @@ XmlElement::Pointer XmlDataElementWrapper::Get( KRATOS_CATCH(""); } -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_data_element_wrapper.h b/kratos/utilities/xml_utilities/xml_data_element_wrapper.h similarity index 96% rename from kratos/future/utilities/xml_utilities/xml_data_element_wrapper.h rename to kratos/utilities/xml_utilities/xml_data_element_wrapper.h index 777465be8f94..84d57227fd2e 100644 --- a/kratos/future/utilities/xml_utilities/xml_data_element_wrapper.h +++ b/kratos/utilities/xml_utilities/xml_data_element_wrapper.h @@ -20,7 +20,7 @@ #include "containers/nd_data.h" #include "xml_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -64,4 +64,4 @@ class KRATOS_API(KRATOS_CORE) XmlDataElementWrapper : public XmlElement ///@} }; -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_element.cpp b/kratos/utilities/xml_utilities/xml_element.cpp similarity index 90% rename from kratos/future/utilities/xml_utilities/xml_element.cpp rename to kratos/utilities/xml_utilities/xml_element.cpp index 9aafcfac9c4c..dd3a67847dd5 100644 --- a/kratos/future/utilities/xml_utilities/xml_element.cpp +++ b/kratos/utilities/xml_utilities/xml_element.cpp @@ -17,7 +17,7 @@ // Include base h #include "xml_element.h" -namespace Kratos::Future { +namespace Kratos { XmlElement::XmlElement(const std::string& rTagName) : mTagName(rTagName) @@ -58,7 +58,7 @@ void XmlElement::WriteElementTagStart( rOStream << " " << r_pair.first << "=\"" << r_pair.second << "\""; } - rOStream << ">\n"; + rOStream << ">" << std::endl; } void XmlElement::WriteElementTagEnd( @@ -66,7 +66,7 @@ void XmlElement::WriteElementTagEnd( const IndexType Level) const { const std::string tabbing(Level * 3, ' '); - rOStream << tabbing << "\n"; + rOStream << tabbing << "" << std::endl; } void XmlElement::WriteEmptyElementTag( std::ostream& rOStream, @@ -80,7 +80,7 @@ void XmlElement::WriteEmptyElementTag( rOStream << " " << r_pair.first << "=\"" << r_pair.second << "\""; } - rOStream << "/>\n"; + rOStream << "/>" << std::endl; } -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_element.h b/kratos/utilities/xml_utilities/xml_element.h similarity index 97% rename from kratos/future/utilities/xml_utilities/xml_element.h rename to kratos/utilities/xml_utilities/xml_element.h index 104f499cf5f3..6dc6dd86d8aa 100644 --- a/kratos/future/utilities/xml_utilities/xml_element.h +++ b/kratos/utilities/xml_utilities/xml_element.h @@ -19,7 +19,7 @@ // Project includes #include "includes/define.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -101,4 +101,4 @@ class KRATOS_API(KRATOS_CORE) XmlElement ///@} }; -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_elements_array.cpp b/kratos/utilities/xml_utilities/xml_elements_array.cpp similarity index 95% rename from kratos/future/utilities/xml_utilities/xml_elements_array.cpp rename to kratos/utilities/xml_utilities/xml_elements_array.cpp index f2007c1eacc1..9885fd077917 100644 --- a/kratos/future/utilities/xml_utilities/xml_elements_array.cpp +++ b/kratos/utilities/xml_utilities/xml_elements_array.cpp @@ -17,7 +17,7 @@ // Include base h #include "xml_elements_array.h" -namespace Kratos::Future { +namespace Kratos { XmlElementsArray::XmlElementsArray(const std::string& rTagName) : BaseType(rTagName) @@ -60,4 +60,4 @@ void XmlElementsArray:: Write( KRATOS_CATCH(""); } -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_elements_array.h b/kratos/utilities/xml_utilities/xml_elements_array.h similarity index 96% rename from kratos/future/utilities/xml_utilities/xml_elements_array.h rename to kratos/utilities/xml_utilities/xml_elements_array.h index 65cb97b0d513..29634ae2ad4f 100644 --- a/kratos/future/utilities/xml_utilities/xml_elements_array.h +++ b/kratos/utilities/xml_utilities/xml_elements_array.h @@ -20,7 +20,7 @@ #include "includes/define.h" #include "xml_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -78,4 +78,4 @@ class KRATOS_API(KRATOS_CORE) XmlElementsArray : public XmlElement ///@} }; -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_expression_element.cpp b/kratos/utilities/xml_utilities/xml_expression_element.cpp deleted file mode 100644 index e0248977bbb0..000000000000 --- a/kratos/utilities/xml_utilities/xml_expression_element.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -// System includes - -// Project includes -#include "expression/literal_flat_expression.h" - -// Include base h -#include "xml_expression_element.h" - -namespace Kratos { - -XmlExpressionElement::XmlExpressionElement(const std::string& rTagName) - : mTagName(rTagName) -{ -} - -XmlExpressionElement::XmlExpressionElement( - const std::string& rDataName, - const std::vector& rExpressions) - : mTagName("DataArray"), - mExpressions(rExpressions) -{ - KRATOS_ERROR_IF(rExpressions.size() == 0) - << "Empty expression lists are not allowed."; - - IndexType number_of_components = 0; - - for (const auto& p_expression : rExpressions) { - if (number_of_components == 0) { - number_of_components = p_expression->GetItemComponentCount(); - } - KRATOS_ERROR_IF(number_of_components != p_expression->GetItemComponentCount()) - << "Found expressions with mismatching shapes."; - } - - if (std::all_of(mExpressions.begin(), mExpressions.end(), [](const auto& pExpression) { - return dynamic_cast*>(&*pExpression); - })) { - AddAttribute("type", "UInt" + std::to_string(sizeof(char) * 8)); - } else if (std::all_of(mExpressions.begin(), mExpressions.end(), [](const auto& pExpression) { - return dynamic_cast*>(&*pExpression); - })) { - AddAttribute("type", "Int" + std::to_string(sizeof(int) * 8)); - } else { - AddAttribute("type", "Float" + std::to_string(sizeof(double) * 8)); - } - - AddAttribute("Name", rDataName); - - if (number_of_components > 0) { - AddAttribute("NumberOfComponents", std::to_string(number_of_components)); - } -} - - ///@} - ///@name Public operations - ///@{ - -const std::string XmlExpressionElement::GetTagName() const -{ - return mTagName; -}; - -void XmlExpressionElement::AddAttribute( - const std::string& rName, - const std::string& rValue) -{ - for (const auto& r_attribute : mAttributes) { - KRATOS_ERROR_IF(r_attribute.first == rName) - << "There exists an attribute named \"" << rName - << "\" in the xml element with value = \"" - << r_attribute.second << "\" [ given new value = \"" - << rValue << "\" ].\n"; - } - mAttributes.push_back(std::make_pair(rName, rValue)); -} - -const std::vector>& XmlExpressionElement::GetAttributes() const -{ - return mAttributes; -} - -void XmlExpressionElement::ClearAttributes() -{ - mAttributes.clear(); -} - -void XmlExpressionElement::AddElement(const XmlExpressionElement::Pointer pXmlElement) -{ - if (mExpressions.size() == 0) { - for (const auto& p_element : mXmlElements) { - KRATOS_ERROR_IF(&*(p_element) == &*(pXmlElement)) - << "The xml element is already aded."; - } - mXmlElements.push_back(pXmlElement); - } else { - KRATOS_ERROR << "Cannot add element to an Xml element which has " - "data [ current xml tag = \"" - << GetTagName() << "\", new element tag name = \"" - << pXmlElement->GetTagName() << "\" ].\n"; - } -} - -std::vector XmlExpressionElement::GetElements(const std::string& rTagName) const -{ - std::vector results; - for (const auto& p_element : mXmlElements) { - if (p_element->GetTagName() == rTagName) { - results.push_back(p_element); - } - } - return results; -} - -const std::vector& XmlExpressionElement::GetElements() const -{ - return mXmlElements; -} - -void XmlExpressionElement::ClearElements() -{ - mXmlElements.clear(); -} - -const std::vector XmlExpressionElement::GetExpressions() const -{ - return mExpressions; -} - -} // namespace Kratos diff --git a/kratos/utilities/xml_utilities/xml_expression_element.h b/kratos/utilities/xml_utilities/xml_expression_element.h deleted file mode 100644 index eb2d3f7644bb..000000000000 --- a/kratos/utilities/xml_utilities/xml_expression_element.h +++ /dev/null @@ -1,131 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -#pragma once - -// System includes -#include -#include - -// Project includes -#include "includes/define.h" -#include "expression/expression.h" - -namespace Kratos { - -///@name Kratos Classes -///@{ - -class KRATOS_API(KRATOS_CORE) XmlExpressionElement { -public: - ///@name Type definitions - ///@{ - - using IndexType = std::size_t; - - KRATOS_CLASS_POINTER_DEFINITION(XmlExpressionElement); - - ///@} - ///@name Life cycle - ///@{ - - /** - * @brief Constructor. - * @param rTagName The tag name of the XML element. - */ - XmlExpressionElement(const std::string& rTagName); - - /** - * @brief Constructor. - * @param rDataName The name of the data element. - * @param rExpressions The expressions to write as data. - */ - XmlExpressionElement( - const std::string& rDataName, - const std::vector& rExpressions); - - ///@} - ///@name Public operations - ///@{ - - /** - * @brief Get the tag name of the XML element. - * @return The tag name. - */ - const std::string GetTagName() const; - - /** - * @brief Add an attribute to the XML element. - * @param rName The name of the attribute. - * @param rValue The value of the attribute. - */ - void AddAttribute( - const std::string& rName, - const std::string& rValue); - - /** - * @brief Get the attributes of the XML element. - * @return The attributes. - */ - const std::vector>& GetAttributes() const; - - /** - * @brief Clear the attributes of the XML element. - */ - void ClearAttributes(); - - /** - * @brief Add a sub-element to the XML element. - * @param pXmlElement The sub-element to add. - */ - void AddElement(const XmlExpressionElement::Pointer pXmlElement); - - /** - * @brief Get sub-elements with a specific tag name. - * @param rTagName The tag name of the sub-elements. - * @return The vector of sub-elements. - */ - std::vector GetElements(const std::string& rTagName) const; - - /** - * @brief Get all sub-elements of the XML element. - * @return The vector of sub-elements. - */ - const std::vector& GetElements() const; - - /** - * @brief Clear all sub-elements of the XML element. - */ - void ClearElements(); - - const std::vector GetExpressions() const; - - ///@} - -private: - ///@name Private member variables - ///@{ - - const std::string mTagName; /// The tag name of the XML element. - - std::vector> mAttributes; /// The attributes of the XML element. - - std::vector mXmlElements; /// The sub-elements of the XML element. - - const std::vector mExpressions; /// The expressions to write as data. - - ///@} -}; - -///@} - -} // namespace Kratos diff --git a/kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp b/kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp similarity index 97% rename from kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp rename to kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp index 931509fd88f5..376ad2693113 100644 --- a/kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp +++ b/kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.cpp @@ -24,7 +24,7 @@ // Include base h #include "xml_in_place_data_element_wrapper.h" -namespace Kratos::Future { +namespace Kratos { XmlInPlaceDataElementWrapper::XmlInPlaceDataElementWrapper( const XmlOutputType OutputType, @@ -74,4 +74,4 @@ void XmlInPlaceDataElementWrapper::Write( KRATOS_CATCH(""); } -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.h b/kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.h similarity index 96% rename from kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.h rename to kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.h index 53348b65c686..fcf125ed2622 100644 --- a/kratos/future/utilities/xml_utilities/xml_in_place_data_element_wrapper.h +++ b/kratos/utilities/xml_utilities/xml_in_place_data_element_wrapper.h @@ -19,7 +19,7 @@ #include "containers/nd_data.h" #include "xml_data_element_wrapper.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -84,4 +84,4 @@ class KRATOS_API(KRATOS_CORE) XmlInPlaceDataElementWrapper : public XmlDataEleme ///@} }; -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_nd_data_element.cpp b/kratos/utilities/xml_utilities/xml_nd_data_element.cpp similarity index 97% rename from kratos/future/utilities/xml_utilities/xml_nd_data_element.cpp rename to kratos/utilities/xml_utilities/xml_nd_data_element.cpp index 56fa0755897e..2705e23c8ce6 100644 --- a/kratos/future/utilities/xml_utilities/xml_nd_data_element.cpp +++ b/kratos/utilities/xml_utilities/xml_nd_data_element.cpp @@ -20,7 +20,7 @@ // Include base h #include "xml_nd_data_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -66,4 +66,4 @@ template class XmlNDDataElement; template class XmlNDDataElement; template class XmlNDDataElement; -} // namespace Kratos::Future +} // namespace Kratos diff --git a/kratos/future/utilities/xml_utilities/xml_nd_data_element.h b/kratos/utilities/xml_utilities/xml_nd_data_element.h similarity index 94% rename from kratos/future/utilities/xml_utilities/xml_nd_data_element.h rename to kratos/utilities/xml_utilities/xml_nd_data_element.h index 223700ce8c10..177d1d951951 100644 --- a/kratos/future/utilities/xml_utilities/xml_nd_data_element.h +++ b/kratos/utilities/xml_utilities/xml_nd_data_element.h @@ -20,7 +20,7 @@ #include "containers/nd_data.h" #include "xml_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -56,4 +56,4 @@ class KRATOS_API(KRATOS_CORE) XmlNDDataElement : public XmlElement { ///@} -} // namespace Kratos::Future +} // namespace Kratos diff --git a/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.cpp b/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.cpp deleted file mode 100644 index 9e002703e4e0..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -// System includes -#include -#include -#include -#include - -// Project includes -#include "expression/literal_flat_expression.h" - -// Include base h -#include "xml_ostream_ascii_writer.h" - -namespace Kratos { - -namespace XmlOStreamAsciiWriterHelperUtilities -{ -template -void WriteExpression( - std::ostream& rOStream, - const std::vector& rExpressions) -{ - std::vector transformed_expressions(rExpressions.size()); - std::transform(rExpressions.begin(), rExpressions.end(), - transformed_expressions.begin(), [](auto& pExpression) { - return dynamic_cast(&*(pExpression)); - }); - - for (const auto& p_expression : transformed_expressions) { - auto itr = p_expression->cbegin(); - auto data_end = p_expression->cend(); - for (; itr != data_end; ++itr) { - if constexpr (std::is_same_v, const char>) { - rOStream << " " << static_cast(*(itr)); - } - else { - rOStream << " " << *itr; - } - } - } -} -} // namespace XmlOStreamAsciiWriterHelperUtilities - -XmlOStreamAsciiWriter::XmlOStreamAsciiWriter( - std::ostream& rOStream, - const IndexType Precision) - : XmlOStreamWriter(rOStream) -{ - mrOStream << std::scientific << std::setprecision(Precision); -} - -void XmlOStreamAsciiWriter::WriteExpressions( - const std::vector& rExpressions, - const std::string& rTabbing) -{ - mrOStream << " format=\"ascii\">\n" << rTabbing; - - if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamAsciiWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamAsciiWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamAsciiWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else { - XmlOStreamAsciiWriterHelperUtilities::WriteExpression(mrOStream, rExpressions); - } -} - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.h b/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.h deleted file mode 100644 index 1f0b31885e05..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_ascii_writer.h +++ /dev/null @@ -1,66 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -#pragma once - -// System includes -#include - -// Project includes -#include "includes/define.h" -#include "xml_ostream_writer.h" - -namespace Kratos { - -///@name Kratos Classes -///@{ - -/* @class XmlOStreamAsciiWriter - * @ingroup KratosCore - * @brief Output stream ascii writer for XML format. - * @author Suneth Warnakulasuriya - */ -class KRATOS_API(KRATOS_CORE) XmlOStreamAsciiWriter: public XmlOStreamWriter -{ -public: - ///@name Life cycle - ///@{ - - using IndexType = std::size_t; - - ///@} - ///@name Life cycle - ///@{ - - /** - * @brief Constructor. - * @param rOStream The output stream to write to. - * @param Precision The precision for floating-point numbers. - */ - XmlOStreamAsciiWriter( - std::ostream& rOStream, - const IndexType Precision); - - ///@} - -protected: - ///@name Protected operations - ///@{ - - void WriteExpressions( - const std::vector& rExpressions, - const std::string& rTabbing) override; - - ///@} -}; - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.cpp b/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.cpp deleted file mode 100644 index 51a21c5e2e58..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -// System includes -#include -#include -#include -#include - -// Project includes -#include "input_output/base_64_encoded_output.h" -#include "expression/literal_flat_expression.h" - -// Include base h -#include "xml_ostream_base64_binary_writer.h" - -namespace Kratos { - -namespace XmlOStreamBase64BinaryWriterHelperUtilities -{ -template -void WriteExpression( - std::ostream& rOStream, - const std::vector& rExpressions) -{ - std::vector transformed_expressions(rExpressions.size()); - std::transform(rExpressions.begin(), rExpressions.end(), - transformed_expressions.begin(), [](auto& pExpression) { - return dynamic_cast(&*(pExpression)); - }); - - constexpr std::size_t data_type_size = sizeof(decltype(*(transformed_expressions[0]->cbegin()))); - const std::size_t total_entities = std::accumulate(rExpressions.begin(), rExpressions.end(), 0U, [](const std::size_t LHS, const auto& pExpression) { return LHS + pExpression->NumberOfEntities();}); - const std::size_t flattened_shape_size = rExpressions[0]->GetItemComponentCount(); - const std::size_t total_number_of_values = total_entities * flattened_shape_size; - const unsigned int total_data_size = total_number_of_values * data_type_size; - - { - Base64EncodedOutput base64_encoder(rOStream); - - base64_encoder.WriteData(&total_data_size, 1); - for (const auto p_expression : transformed_expressions) { - base64_encoder.WriteData(p_expression->cbegin(), p_expression->NumberOfEntities() * flattened_shape_size); - } - } -} -} // namespace XmlOStreamBase64BinaryWriterHelperUtilities - -XmlOStreamBase64BinaryWriter::XmlOStreamBase64BinaryWriter(std::ostream& rOStream) - : XmlOStreamWriter(rOStream) -{ -} - -void XmlOStreamBase64BinaryWriter::WriteExpressions( - const std::vector& rExpressions, - const std::string& rTabbing) -{ - mrOStream << " format=\"binary\">\n" << rTabbing << " "; - - if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamBase64BinaryWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamBase64BinaryWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else if (std::all_of(rExpressions.begin(), rExpressions.end(), [](const auto& pExpression) { return dynamic_cast*>(&*pExpression); })) { - XmlOStreamBase64BinaryWriterHelperUtilities::WriteExpression>(mrOStream, rExpressions); - } else { - XmlOStreamBase64BinaryWriterHelperUtilities::WriteExpression(mrOStream, rExpressions); - } -} - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.h b/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.h deleted file mode 100644 index 62dddd5d6947..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_base64_binary_writer.h +++ /dev/null @@ -1,63 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -#pragma once - -// System includes -#include - -// Project includes -#include "includes/define.h" -#include "xml_ostream_writer.h" - -namespace Kratos { - -///@name Kratos Classes -///@{ - -/* @class XmlOStreamBase64BinaryWriter - * @ingroup KratosCore - * @brief Output stream ascii writer for XML format. - * @author Suneth Warnakulasuriya - */ -class KRATOS_API(KRATOS_CORE) XmlOStreamBase64BinaryWriter: public XmlOStreamWriter -{ -public: - ///@name Life cycle - ///@{ - - using IndexType = std::size_t; - - ///@} - ///@name Life cycle - ///@{ - - /** - * @brief Constructor. - * @param rOStream The output stream to write to. - */ - XmlOStreamBase64BinaryWriter(std::ostream& rOStream); - - ///@} - -protected: - ///@name Protected operations - ///@{ - - void WriteExpressions( - const std::vector& rExpressions, - const std::string& rTabbing) override; - - ///@} -}; - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_ostream_writer.cpp b/kratos/utilities/xml_utilities/xml_ostream_writer.cpp deleted file mode 100644 index 9b393fdf7800..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_writer.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -// System includes -#include -#include -#include - -// Project includes -#include "expression/literal_flat_expression.h" - -// Include base h -#include "xml_ostream_writer.h" - -namespace Kratos { - -XmlOStreamWriter::XmlOStreamWriter(std::ostream& rOStream) - : mrOStream(rOStream) -{ -} - -void XmlOStreamWriter::WriteElement( - const XmlExpressionElement& rElement, - const IndexType Level) -{ - const std::string tabbing(Level * 3, ' '); - - mrOStream << tabbing << "<" << rElement.GetTagName(); - const auto& r_attributes = rElement.GetAttributes(); - if (r_attributes.size() > 0) { - for (const auto& r_pair : r_attributes) { - mrOStream << " " << r_pair.first << "=\"" << r_pair.second << "\""; - } - } - - const auto& r_sub_elements = rElement.GetElements(); - const auto& r_expressions = rElement.GetExpressions(); - - if (r_sub_elements.size() > 0) { - // write sub elements - mrOStream << ">\n"; - for (const auto& p_sub_element : r_sub_elements) { - this->WriteElement(*p_sub_element, Level + 1); - } - mrOStream << tabbing << "\n"; - } else if (r_expressions.size() > 0) { - // write a data expression element - this->WriteExpressions(r_expressions, tabbing); - // close the element - mrOStream << "\n" << tabbing << "\n"; - } else { - // then it is an empty element. - mrOStream << "/>\n"; - } -} - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/utilities/xml_utilities/xml_ostream_writer.h b/kratos/utilities/xml_utilities/xml_ostream_writer.h deleted file mode 100644 index 51060ea11a5a..000000000000 --- a/kratos/utilities/xml_utilities/xml_ostream_writer.h +++ /dev/null @@ -1,92 +0,0 @@ -// | / | -// ' / __| _` | __| _ \ __| -// . \ | ( | | ( |\__ ` -// _|\_\_| \__,_|\__|\___/ ____/ -// Multi-Physics -// -// License: BSD License -// Kratos default license: kratos/license.txt -// -// Main authors: Suneth Warnakulasuriya -// - -#pragma once - -// System includes -#include -#include - -// Project includes -#include "includes/define.h" -#include "expression/literal_flat_expression.h" -#include "utilities/xml_utilities/xml_expression_element.h" - -namespace Kratos { - -///@name Kratos Classes -///@{ - -/* @class XmlOStreamWriter - * @ingroup KratosCore - * @brief Output stream writer for XML format. - * @author Suneth Warnakulasuriya - */ -class KRATOS_API(KRATOS_CORE) XmlOStreamWriter -{ -public: - ///@name Life cycle - ///@{ - - using IndexType = std::size_t; - - ///@} - ///@name Life cycle - ///@{ - - /** - * @brief Constructor. - * @param rOStream The output stream to write to. - */ - XmlOStreamWriter(std::ostream& rOStream); - - virtual ~XmlOStreamWriter() = default; - - ///@} - ///@name Public operations - ///@{ - - /** - * @brief Writes an XML expression element. - * @param XmlExpressionElement Expression xml element to be written. - * @param Level The indentation level. - */ - void WriteElement( - const XmlExpressionElement& rElement, - const IndexType Level = 0); - - ///@} - -protected: - ///@name Protected member variables - ///@{ - - std::ostream& mrOStream; /// The output stream - - ///@} - ///@name Protected operations - ///@{ - - /** - * @brief Writes generic lazy type expressions - * - * @param rExpressions Expressions list to write. - * @param rTabbing Tabbing used for expression writing. - */ - virtual void WriteExpressions( - const std::vector& rExpressions, - const std::string& rTabbing) = 0; - - ///@} -}; - -} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_utils.cpp b/kratos/utilities/xml_utilities/xml_utils.cpp similarity index 97% rename from kratos/future/utilities/xml_utilities/xml_utils.cpp rename to kratos/utilities/xml_utilities/xml_utils.cpp index 263e1be172de..80d594159e84 100644 --- a/kratos/future/utilities/xml_utilities/xml_utils.cpp +++ b/kratos/utilities/xml_utilities/xml_utils.cpp @@ -18,7 +18,7 @@ // Include base h #include "xml_utils.h" -namespace Kratos::Future { +namespace Kratos { template void XmlUtilities::AddDataArrayAttributes( @@ -56,4 +56,4 @@ template void XmlUtilities::AddDataArrayAttributes(XmlElement&, const NDData&); template void XmlUtilities::AddDataArrayAttributes(XmlElement&, const NDData&); -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file diff --git a/kratos/future/utilities/xml_utilities/xml_utils.h b/kratos/utilities/xml_utilities/xml_utils.h similarity index 97% rename from kratos/future/utilities/xml_utilities/xml_utils.h rename to kratos/utilities/xml_utilities/xml_utils.h index eb34fbee0c9a..9daa7baed5ed 100644 --- a/kratos/future/utilities/xml_utilities/xml_utils.h +++ b/kratos/utilities/xml_utilities/xml_utils.h @@ -20,7 +20,7 @@ #include "includes/define.h" #include "xml_element.h" -namespace Kratos::Future { +namespace Kratos { ///@name Kratos Classes ///@{ @@ -67,4 +67,4 @@ class KRATOS_API(KRATOS_CORE) XmlUtilities ///@} -} // namespace Kratos::Future \ No newline at end of file +} // namespace Kratos \ No newline at end of file