diff --git a/include/tensor_computes/ParsedCompute.h b/include/tensor_computes/ParsedCompute.h index 8ab7c36..2cf9d6f 100644 --- a/include/tensor_computes/ParsedCompute.h +++ b/include/tensor_computes/ParsedCompute.h @@ -32,5 +32,7 @@ class ParsedCompute : public TensorOperator ParsedJITTensor _jit; ParsedTensor _no_jit; + torch::Tensor _time_tensor; std::vector _params; + const bool _real_space; }; diff --git a/include/tensor_computes/TensorOperatorBase.h b/include/tensor_computes/TensorOperatorBase.h index 70d8fbd..324ef83 100644 --- a/include/tensor_computes/TensorOperatorBase.h +++ b/include/tensor_computes/TensorOperatorBase.h @@ -61,4 +61,7 @@ class TensorOperatorBase : public MooseObject, public DependencyResolverInterfac /// reciprocal axes const torch::Tensor &_i, &_j, &_k; + + /// substep time + const Real & _time; }; diff --git a/scripts/TestHarness/tests/test_HDF5Diff.py b/scripts/TestHarness/tests/test_HDF5Diff.py index bc6b71c..cfeb5c4 100644 --- a/scripts/TestHarness/tests/test_HDF5Diff.py +++ b/scripts/TestHarness/tests/test_HDF5Diff.py @@ -41,5 +41,5 @@ def testDataSetMismatch(self): self.runTests('-i', 'hdf5diffs', '--re', 'dataset_mismatch') e = cm.exception - self.assertRegex(e.output, "tester\.dataset_mismatch:.*\['c\.0', 'c\.1', 'c\.2', 'mu\.0', 'mu\.1', 'mu\.2'\]") + self.assertRegex(e.output, r"tester\.dataset_mismatch:.*\['c\.0', 'c\.1', 'c\.2', 'mu\.0', 'mu\.1', 'mu\.2'\]") self.checkStatus(e.output, failed=1) diff --git a/src/actions/DomainAction.C b/src/actions/DomainAction.C index ac9dbae..cc9894d 100644 --- a/src/actions/DomainAction.C +++ b/src/actions/DomainAction.C @@ -477,11 +477,11 @@ DomainAction::ifft(const torch::Tensor & t) const switch (_dim) { case 1: - return torch::fft::irfft(t); + return torch::fft::irfft(t, getShape()[0]); case 2: - return torch::fft::irfft2(t); + return torch::fft::irfft2(t, getShape()); case 3: - return torch::fft::irfftn(t, c10::nullopt, {0, 1, 2}); + return torch::fft::irfftn(t, getShape(), {0, 1, 2}); default: mooseError("Unsupported mesh dimension"); } diff --git a/src/tensor_computes/ComputeGroup.C b/src/tensor_computes/ComputeGroup.C index 6c54a11..be78a9d 100644 --- a/src/tensor_computes/ComputeGroup.C +++ b/src/tensor_computes/ComputeGroup.C @@ -42,7 +42,14 @@ void ComputeGroup::computeBuffer() { for (const auto & cmp : _computes) - cmp->computeBuffer(); + try + { + cmp->computeBuffer(); + } + catch (const std::exception & e) + { + cmp->mooseError("Exception: ", e.what()); + } } void diff --git a/src/tensor_computes/FFTGradient.C b/src/tensor_computes/FFTGradient.C index f03da65..1b458e8 100644 --- a/src/tensor_computes/FFTGradient.C +++ b/src/tensor_computes/FFTGradient.C @@ -36,7 +36,6 @@ FFTGradient::FFTGradient(const InputParameters & parameters) void FFTGradient::computeBuffer() { - std::cout << std::endl; _u = _domain.ifft((_input_is_reciprocal ? _input : _domain.fft(_input)) * _domain.getReciprocalAxis(_direction) * _i); } diff --git a/src/tensor_computes/ParsedCompute.C b/src/tensor_computes/ParsedCompute.C index 439999b..422cf1a 100644 --- a/src/tensor_computes/ParsedCompute.C +++ b/src/tensor_computes/ParsedCompute.C @@ -32,7 +32,7 @@ ParsedCompute::validParams() false, "Provide i (imaginary unit), kx,ky,kz (reciprocal space frequency), k2 " "(square of the k-vector), x,y,z " - "(real space coordinates), and pi,e."); + "(real space coordinates), time t, pi, and e."); // Constants and their values params.addParam>( "constant_names", @@ -42,14 +42,15 @@ ParsedCompute::validParams() "constant_expressions", std::vector(), "Vector of values for the constants in constant_names (can be an FParser expression)"); - + params.addParam("real_space", true, "Is the tensor being computed a real space tensor?"); return params; } ParsedCompute::ParsedCompute(const InputParameters & parameters) : TensorOperator(parameters), _use_jit(getParam("enable_jit")), - _extra_symbols(getParam("extra_symbols")) + _extra_symbols(getParam("extra_symbols")), + _real_space(getParam("real_space")) { const auto & expression = getParam("expression"); const auto & names = getParam>("inputs"); @@ -69,7 +70,7 @@ ParsedCompute::ParsedCompute(const InputParameters & parameters) _params.push_back(&getInputBufferByName(name)); static const std::vector reserved_symbols = { - "i", "x", "kx", "y", "ky", "z", "kz", "k2"}; + "i", "x", "kx", "y", "ky", "z", "kz", "k2", "t"}; // helper function to check if the name given is one of the reserved_names auto isReservedName = [this](const auto & name) @@ -108,7 +109,8 @@ ParsedCompute::ParsedCompute(const InputParameters & parameters) // append extra symbols variables_vec.insert(variables_vec.end(), reserved_symbols.begin(), reserved_symbols.end()); - _constant_tensors.push_back(torch::tensor(c10::complex(0.0, 1.0))); + _constant_tensors.push_back( + torch::tensor(c10::complex(0.0, 1.0), MooseTensor::complexFloatTensorOptions())); _params.push_back(&_constant_tensors[0]); for (const auto dim : make_range(3u)) @@ -118,6 +120,7 @@ ParsedCompute::ParsedCompute(const InputParameters & parameters) } _params.push_back(&_domain.getKSquare()); + _params.push_back(&_time_tensor); fp.AddConstant("pi", libMesh::pi); fp.AddConstant("e", std::exp(Real(1.0))); @@ -185,8 +188,13 @@ ParsedCompute::ParsedCompute(const InputParameters & parameters) void ParsedCompute::computeBuffer() { + if (_extra_symbols) + _time_tensor = torch::tensor(_time, MooseTensor::floatTensorOptions()); + + // use local shape if we add parallel support, and add option for reciprocal shape if (_use_jit) - _u = _jit.Eval(_params); + _u = _jit.Eval(_params).expand(_real_space ? _domain.getShape() : _domain.getReciprocalShape()); else - _u = _no_jit.Eval(_params); + _u = _no_jit.Eval(_params).expand(_real_space ? _domain.getShape() + : _domain.getReciprocalShape()); } diff --git a/src/tensor_computes/TensorOperatorBase.C b/src/tensor_computes/TensorOperatorBase.C index dcd0f0f..0a9226c 100644 --- a/src/tensor_computes/TensorOperatorBase.C +++ b/src/tensor_computes/TensorOperatorBase.C @@ -33,7 +33,8 @@ TensorOperatorBase::TensorOperatorBase(const InputParameters & parameters) _z(_domain.getAxis(2)), _i(_domain.getReciprocalAxis(0)), _j(_domain.getReciprocalAxis(1)), - _k(_domain.getReciprocalAxis(2)) + _k(_domain.getReciprocalAxis(2)), + _time(_tensor_problem.subTime()) { } diff --git a/src/tensor_solver/SecantSolver.C b/src/tensor_solver/SecantSolver.C index 8e0196a..cfccc21 100644 --- a/src/tensor_solver/SecantSolver.C +++ b/src/tensor_solver/SecantSolver.C @@ -140,7 +140,7 @@ SecantSolver::secantSolve() if (_verbose) { const auto unorm = torch::norm(du).item(); - std::cout << _iterations << " |du| = " << unorm << " |R|=" << Rnorm << std::endl; + _console << _iterations << " |du| = " << unorm << " |R|=" << Rnorm << std::endl; } // nan check diff --git a/test/tests/cahnhilliard/cahnhilliard.i b/test/tests/cahnhilliard/cahnhilliard.i index 1b3b537..ceac3b7 100644 --- a/test/tests/cahnhilliard/cahnhilliard.i +++ b/test/tests/cahnhilliard/cahnhilliard.i @@ -14,7 +14,6 @@ device_names = cpu [] - [TensorBuffers] [c] [] @@ -81,6 +80,7 @@ enable_jit = true expression = 'Mbar*mubar' inputs = 'Mbar mubar' + real_space = false [] [cbar] type = ForwardFFT diff --git a/test/tests/postprocessors/gold/interface_velocity_out.csv b/test/tests/postprocessors/gold/interface_velocity_out.csv new file mode 100644 index 0000000..0026614 --- /dev/null +++ b/test/tests/postprocessors/gold/interface_velocity_out.csv @@ -0,0 +1,12 @@ +time,v +0,0 +0.01,0 +0.02,0.2006196179713 +0.03,0.2006238853419 +0.04,0.20062820630563 +0.05,0.20063258191329 +0.06,0.20063701324401 +0.07,0.200641501405 +0.08,0.20064604753323 +0.09,0.20065065279606 +0.1,0.20065531839251 diff --git a/test/tests/postprocessors/interface_velocity.i b/test/tests/postprocessors/interface_velocity.i new file mode 100644 index 0000000..e09d586 --- /dev/null +++ b/test/tests/postprocessors/interface_velocity.i @@ -0,0 +1,45 @@ +[Domain] + dim = 2 + nx = 10 + ny = 2 + xmax = ${fparse pi*4} + mesh_mode = DUMMY + device_names = cpu +[] + +[TensorBuffers] + [c] + [] +[] + +[TensorComputes] + [Solve] + [c] + type = ParsedCompute + buffer = c + extra_symbols = true + expression = sin(x+0.2*t) + [] + [] +[] + +[Postprocessors] + [v] + type = TensorInterfaceVelocityPostprocessor + buffer = c + [] +[] + +[Problem] + type = TensorProblem +[] + +[Executioner] + type = Transient + num_steps = 10 + dt = 0.01 +[] + +[Outputs] + csv = true +[] diff --git a/test/tests/postprocessors/tests b/test/tests/postprocessors/tests index 296cae7..74ccef5 100644 --- a/test/tests/postprocessors/tests +++ b/test/tests/postprocessors/tests @@ -37,4 +37,13 @@ issues = '#6' design = 'ReciprocalIntegral.md' [] + + [interface_velocity] + type = CSVDiff + input = interface_velocity.i + csvdiff = interface_velocity_out.csv + requirement = 'The system shall be able to measure the maximum interfacial velocity for a given tensor.' + issues = '#6' + design = 'TensorInterfaceVelocityPostprocessor.md' + [] [] diff --git a/test/tests/tensor_compute/backandforth.i b/test/tests/tensor_compute/backandforth.i index b76a409..41ae5db 100644 --- a/test/tests/tensor_compute/backandforth.i +++ b/test/tests/tensor_compute/backandforth.i @@ -1,7 +1,4 @@ [Domain] - dim = 2 - nx = 20 - ny = 20 xmax = ${fparse pi*4} ymax = ${fparse pi*4} device_names = 'cpu' @@ -9,6 +6,8 @@ [] [TensorBuffers] + [eta_gold] + [] [eta] [] [eta_bar] @@ -17,16 +16,24 @@ [] [zero] [] + [diff] + [] [] [TensorComputes] [Initialize] - [eta] + [eta_gold] type = ParsedCompute - buffer = eta + buffer = eta_gold expression = 'sin(x)+sin(y)+sin(z)' extra_symbols = true [] + [eta] + type = ParsedCompute + buffer = eta + expression = eta_gold + inputs = eta_gold + [] [eta2] type = ConstantTensor buffer = eta2 @@ -52,6 +59,22 @@ input = eta_bar [] [] + + [Postprocess] + [diff] + type = ParsedCompute + buffer = diff + expression = 'abs(eta - eta2) + abs(eta - eta_gold)' + inputs = 'eta eta2 eta_gold' + [] + [] +[] + +[Postprocessors] + [norm] + type = TensorIntegralPostprocessor + buffer = diff + [] [] [TensorSolver] @@ -68,13 +91,9 @@ [Executioner] type = Transient - num_steps = 2 + num_steps = 4 [] -[TensorOutputs] - [xdmf] - type = XDMFTensorOutput - buffer = 'eta eta2' - enable_hdf5 = true - [] +[Outputs] + csv = true [] diff --git a/test/tests/tensor_compute/gold/backandforth.h5 b/test/tests/tensor_compute/gold/backandforth.h5 deleted file mode 100644 index 6251f46..0000000 Binary files a/test/tests/tensor_compute/gold/backandforth.h5 and /dev/null differ diff --git a/test/tests/tensor_compute/gold/backandforth_out.csv b/test/tests/tensor_compute/gold/backandforth_out.csv new file mode 100644 index 0000000..1d89e52 --- /dev/null +++ b/test/tests/tensor_compute/gold/backandforth_out.csv @@ -0,0 +1,6 @@ +time,norm +0,0 +1,0 +2,0 +3,0 +4,0 diff --git a/test/tests/tensor_compute/tests b/test/tests/tensor_compute/tests index ffa853f..d8881f1 100644 --- a/test/tests/tensor_compute/tests +++ b/test/tests/tensor_compute/tests @@ -1,12 +1,50 @@ [Tests] [backandforth] - type = HDF5Diff - input = backandforth.i - hdf5diff = backandforth.h5 - abs_tol = 1e-13 issues = '#6' requirement = 'The system shall be able to transform a buffer from real space to reciprocal space and back and recover the original tensor' design = PerformFFT.md + [even_1d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=1 Domain/nx=10' + detail = 'in one dimension with an even number of grid cells' + [] + [odd_1d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=1 Domain/nx=11' + detail = 'in one dimension with an odd number of grid cells' + [] + [even_2d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=2 Domain/nx=10 Domain/ny=8' + detail = 'in two dimensions with an even number of grid cells' + [] + [odd_2d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=1 Domain/nx=9 Domain/ny=11' + detail = 'in two dimensions with an odd number of grid cells' + [] + [even_3d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=2 Domain/nx=10 Domain/ny=8 Domain/nz=12' + detail = 'in three dimensions with an even number of grid cells' + [] + [odd_3d] + type = CSVDiff + input = backandforth.i + csvdiff = backandforth_out.csv + cli_args = 'Domain/dim=1 Domain/nx=9 Domain/ny=13 Domain/nz=11' + detail = 'in three dimensions with an odd number of grid cells' + [] [] [rotating_grain_secant] type = HDF5Diff