diff --git a/CMakeLists.txt b/CMakeLists.txt
index f797f03aff8442f9b954aa514121e9aeecd7c4ea..b4f889d67b5402ae3a10504d93713064acb252fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,7 +47,7 @@ ELSE()
 ENDIF()
 
 
-find_package(netCDF REQUIRED)
+find_package(netCDF 4.0 REQUIRED)
 set(netcdf_flag HAVE_LIBNETCDF)
 if (${netCDF_FOUND})
   add_compile_definitions(${netcdf_flag}=${netCDF_FOUND})
diff --git a/include/cdo.h b/include/cdo.h
index cc19cc3e679bf53cf6c817243e6f643913f40c61..1539884fe36d48921a2a2f5b3d4f3b5973fa376c 100644
--- a/include/cdo.h
+++ b/include/cdo.h
@@ -5,6 +5,7 @@
 #include <node.h>
 #include <parser.h>
 #include <factory.h>
+#include <cdo_def_options.h>
 #include <cdo_node_attach_exception.h>
 #include <cdo_exception.h>
 #include <cdo_module.h>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 84b73839bba22274b63bbd16321e25f00a6be83f..3c7f3e3cca56c56fe1f8a4043f9c49d43bfcffd5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,4 @@
 list( APPEND cdolib_src_files
-	         	after_dvtrans.cc
 				after_fctrans.cc
 				after_namelist.cc
 				after_sptrans.cc
@@ -9,6 +8,119 @@ list( APPEND cdolib_src_files
 				bitinformation.cc
 				bitinformation.h
 				cdi_lockedIO.cc
+				cellsearch_reg2d.cc
+				cellsearch_reg2d.h
+				cellsearch_spherepart.h
+				cellsearch_unstruct.h
+				cellsearch_utils.h
+				grid_cellsearch.cc
+				grid_cellsearch.h
+				mpim_grid/gridreference.cc
+				mpim_grid/gridreference.h
+				mpim_grid/mpim_grid.cc
+				mpim_grid/mpim_grid.h
+				mpmo.cc
+				mpmo.h
+				mpmo_color.cc
+				mpmo_color.h
+				namelist.cc
+				namelist.h
+				nanoflann.hpp
+				node.cc
+				node.h
+				oper_args.cc
+				oper_args.h
+				operator_help.cc
+				operator_help.h
+				par_io.cc
+				par_io.h
+				param_conversion.cc
+				param_conversion.h
+				parse_literals.cc
+				parse_literals.h
+				parser.cc
+				parser.h
+				percentiles.cc
+				percentiles.h
+				percentiles_hist.cc
+				percentiles_hist.h
+				pipe.cc
+				pipe.h
+				pipeStream.cc
+				pipeStream.h
+				pmlist.cc
+				pmlist.h
+				point.h
+				pointsearch_full.h
+				pointsearch_healpix.h
+				pointsearch_kdtree.h
+				pointsearch_nanoflann.h
+				pointsearch_reg2d.cc
+				pointsearch_reg2d.h
+				pointsearch_spherepart.h
+				pointsearch_unstruct.h
+				pointsearch_utils.h
+				printinfo.cc
+				printinfo.h
+				process.cc
+				process.h
+				processManager.cc
+				processManager.h
+				process_int.cc
+				process_int.h
+				progress.cc
+				progress.h
+				pthread_debug.cc
+				pthread_debug.h
+				region.cc
+				region.h
+				remap.h
+				remap_bicubic.cc
+				remap_bilinear.cc
+				remap_cell_search.cc
+				remap_conserv.cc
+				remap_knn.cc
+				remap_point_search.cc
+				remap_scrip_io.cc
+				remap_search_reg2d.cc
+				remap_store_link.cc
+				remap_store_link.h
+				remap_utils.cc
+				remap_utils.h
+				remap_vars.cc
+				remap_vars.h
+				remaplib.cc
+				selboxinfo.h
+				sellist.cc
+				sellist.h
+				specspace.cc
+				specspace.h
+				statistic.cc
+				statistic.h
+				stdnametable.cc
+				stdnametable.h
+				table.cc
+				table.h
+				transform.h
+				util_date.h
+				util_fileextensions.cc
+				util_fileextensions.h
+				util_files.cc
+				util_files.h
+				util_string.cc
+				util_string.h
+				util_wildcards.cc
+				util_wildcards.h
+				varray.cc
+				varray.h
+				vector3d.h
+				verifygrid.h
+				vertical_interp.cc
+				vertical_interp.h
+				vertint_util.cc
+				vertint_util.h
+				zaxis_print.cc
+	         	after_dvtrans.cc
                 cdi_lockedIO.h
                 cdi_uuid.h
                 cdoStream.cc
@@ -18,23 +130,27 @@ list( APPEND cdolib_src_files
                 cdo_cmor.h
                 cdo_data.cc
                 cdo_data.h
+                cdo_def_options.cc
+                cdo_def_options.h
                 cdo_default_values.cc
                 cdo_default_values.h
-                cdo_features.cc
-                cdo_features.h
+                cdo_exception.h
                 cdo_fctrans.cc
                 cdo_fctrans.h
+                cdo_features.cc
+                cdo_features.h
                 cdo_fft.cc
                 cdo_fft.h
                 cdo_fftw3.cc
                 cdo_fftw3.h
                 cdo_fill.cc
-                cdo_exception.h
                 cdo_fill.h
                 cdo_getopt.cc
                 cdo_getopt.h
                 cdo_history.cc
                 cdo_history.h
+                cdo_magics_mapper.cc
+                cdo_magics_mapper.h
                 cdo_math.cc
                 cdo_math.h
                 cdo_module.cc
@@ -57,6 +173,7 @@ list( APPEND cdolib_src_files
                 cdo_season.h
                 cdo_settings.cc
                 cdo_settings.h
+                cdo_stepstat.h
                 cdo_syntax_error.cc
                 cdo_syntax_error.h
                 cdo_task.cc
@@ -68,11 +185,7 @@ list( APPEND cdolib_src_files
                 cdo_vlist.h
                 cdo_zaxis.cc
                 cdo_zaxis.h
-				cellsearch_reg2d.cc
-				cellsearch_reg2d.h
-				cellsearch_spherepart.h
-				cellsearch_unstruct.h
-				cellsearch_utils.h
+                cdotest.cc
                 cf_interface.h
                 cfortran.h
                 cfortran.h
@@ -82,6 +195,7 @@ list( APPEND cdolib_src_files
                 commandline.cc
                 commandline.h
                 compare.h
+                config.h
                 const.h
                 constants.cc
                 constants.h
@@ -121,17 +235,15 @@ list( APPEND cdolib_src_files
                 field_functions.h
                 field_memory.cc
                 field_meridional.cc
+                field_trend.cc
+                field_trend.h
                 field_vinterp.cc
                 field_vinterp.h
                 field_zonal.cc
-                field_trend.cc
-                field_trend.h
                 fieldc.cc
                 fieldc_complex.cc
                 fileStream.cc
                 fileStream.h
-                memoryStream.cc
-                memoryStream.h
                 fill_1d.cc
                 fill_1d.h
                 gaussian_latitudes.c
@@ -144,8 +256,6 @@ list( APPEND cdolib_src_files
                 grid_from_name.cc
                 grid_gme.cc
                 grid_icosphere.cc
-				grid_cellsearch.cc
-				grid_cellsearch.h
                 grid_pointsearch.cc
                 grid_pointsearch.h
                 grid_print.cc
@@ -166,7 +276,11 @@ list( APPEND cdolib_src_files
                 knndata.h
                 libncl.h
                 listbuffer.h
+                magics_template_parser.cc
+                magics_template_parser.h
                 matrix_view.h
+                memoryStream.cc
+                memoryStream.h
                 merge_axis.cc
                 merge_axis.h
                 module_info.cc
@@ -176,115 +290,19 @@ list( APPEND cdolib_src_files
                 mpim_grid/grid_convert.h
                 mpim_grid/grid_healpix.cc
                 mpim_grid/grid_healpix.h
+                mpim_grid/grid_options.cc
+                mpim_grid/grid_options.h
                 mpim_grid/grid_proj.cc
                 mpim_grid/grid_proj.h
                 mpim_grid/grid_rot.cc
                 mpim_grid/grid_rot.h
-				mpim_grid/gridreference.cc
-				mpim_grid/gridreference.h
-				mpim_grid/mpim_grid.cc
-				mpim_grid/mpim_grid.h
-				mpmo.cc
-				mpmo.h
-				mpmo_color.cc
-				mpmo_color.h
-				namelist.cc
-				namelist.h
-				nanoflann.hpp
-				operator_help.cc
-				operator_help.h
-				oper_args.cc
-				oper_args.h
-				par_io.cc
-				par_io.h
-				param_conversion.cc
-				param_conversion.h
-				parse_literals.cc
-				parse_literals.h
-				percentiles.cc
-				percentiles.h
-				percentiles_hist.cc
-				percentiles_hist.h
-				pipe.cc
-				pipe.h
-				pipeStream.cc
-				pipeStream.h
-				pmlist.cc
-				pmlist.h
-				printinfo.cc
-				printinfo.h
-				point.h
-				pointsearch_reg2d.cc
-				pointsearch_reg2d.h
-				pointsearch_healpix.h
-				pointsearch_unstruct.h
-				pointsearch_kdtree.h
-				pointsearch_nanoflann.h
-				pointsearch_spherepart.h
-				pointsearch_full.h
-				pointsearch_utils.h
-				process.cc
-				process.h
-				processManager.cc
-				processManager.h
-				parser.h
-				parser.cc
-				node.cc
-				node.h
-				process_int.cc
-				process_int.h
-				progress.cc
-				progress.h
-				pthread_debug.cc
-				pthread_debug.h
-				region.h
-				region.cc
-				remap.h
-				remap_bicubic.cc
-				remap_bilinear.cc
-				remap_cell_search.cc
-				remap_conserv.cc
-				remap_knn.cc
-				remap_point_search.cc
-				remap_scrip_io.cc
-				remap_search_reg2d.cc
-				remap_store_link.cc
-				remap_store_link.h
-				remap_utils.cc
-				remap_utils.h
-				remap_vars.cc
-				remap_vars.h
-				remaplib.cc
-				selboxinfo.h
-				sellist.cc
-				sellist.h
-				specspace.cc
-				specspace.h
-				statistic.cc
-				statistic.h
-				stdnametable.cc
-				stdnametable.h
-				table.cc
-				table.h
-				transform.h
-				util_fileextensions.cc
-				util_fileextensions.h
-				util_files.cc
-				util_files.h
-				util_string.cc
-				util_string.h
-				util_wildcards.cc
-				util_wildcards.h
-				util_date.h
-				varray.cc
-				varray.h
-				vector3d.h
-				verifygrid.h
-				vertical_interp.cc
-				vertical_interp.h
-				vertint_util.h
-				vertint_util.cc
-				zaxis_print.cc
+                remap_gradients.cc
+                remap_grid.h
+                remap_method_conserv.cc
+                remap_method_conserv.h
+                remap_stat.cc
+                results_template_parser.cc
+                results_template_parser.h
 )
 
 list( APPEND cdolib_src_files
@@ -339,23 +357,22 @@ list( APPEND cdo_src_files
 )
 
 list( APPEND cdo_operators_src_files
-                                Adisit.cc
 				Afterburner.cc
 				Arith.cc
 				Arithc.cc
 				Arithdays.cc
 				Arithlat.cc
 				Bitrounding.cc
-				Cat.cc
 				CDIread.cc
 				CDItest.cc
 				CDIwrite.cc
-				Change.cc
-				Change_e5slm.cc
-				Cloudlayer.cc
 				CMOR.cc
 				CMOR_lite.cc
 				CMOR_table.cc
+				Cat.cc
+				Change.cc
+				Change_e5slm.cc
+				Cloudlayer.cc
 				Collgrid.cc
 				Command.cc
 				Comp.cc
@@ -377,15 +394,14 @@ list( APPEND cdo_operators_src_files
 				Distgrid.cc
 				Duplicate.cc
 				EOFs.cc
-				Eof3d.cc
-				EcaIndices.cc
 				EcaEtccdi.cc
-			        Echam5ini.cc
+				EcaIndices.cc
 				Enlarge.cc
 				Enlargegrid.cc
 				Ensstat.cc
 				Ensstat3.cc
 				Ensval.cc
+				Eof3d.cc
 				Eofcoeff.cc
 				Eofcoeff3d.cc
 				EstFreq.cc
@@ -411,8 +427,8 @@ list( APPEND cdo_operators_src_files
 				Importamsr.cc
 				Importbinary.cc
 				Importcmsaf.cc
-				Importobs.cc
 				Importfv3grid.cc
+				Importobs.cc
 				Info.cc
 				Input.cc
 				Intgrid.cc
@@ -451,8 +467,8 @@ list( APPEND cdo_operators_src_files
 				Regres.cc
 				Remapeta.cc
 				Remapgrid.cc
-				Remapweights.cc
 				Remapstat.cc
+				Remapweights.cc
 				Replace.cc
 				Replacevalues.cc
 				Rhopot.cc
@@ -462,12 +478,12 @@ list( APPEND cdo_operators_src_files
 				Samplegrid.cc
 				Samplegridicon.cc
 				Seascount.cc
+				Seasmonstat.cc
 				Seaspctl.cc
 				Seasstat.cc
-				Seasmonstat.cc
 				Selbox.cc
-				Selgridcell.cc
 				Select.cc
+				Selgridcell.cc
 				Selmulti.cc
 				Seloperator.cc
 				Selrec.cc
@@ -488,8 +504,8 @@ list( APPEND cdo_operators_src_files
 				Settime.cc
 				Setzaxis.cc
 				Shiftxy.cc
-				Showinfo.cc
 				Showattribute.cc
+				Showinfo.cc
 				Sinfo.cc
 				Smooth.cc
 				Sort.cc
@@ -505,6 +521,7 @@ list( APPEND cdo_operators_src_files
 				Tee.cc
 				Test.cc
 				Tests.cc
+                Templates.cc
 				Timcount.cc
 				Timcumsum.cc
 				Timfillmiss.cc
@@ -525,28 +542,28 @@ list( APPEND cdo_operators_src_files
 				Vargen.cc
 				Varrms.cc
 				Varsstat.cc
+				Verifygrid.cc
+				Verifyweights.cc
+				Vertcum.cc
 				Vertfillmiss.cc
 				Vertintap.cc
 				Vertintgh.cc
 				Vertintml.cc
 				Vertintzs.cc
 				Vertstat.cc
-				Vertcum.cc
 				Vertwind.cc
-				Verifygrid.cc
-				Verifyweights.cc
 				Wct.cc
 				Wind.cc
 				WindTrans.cc
 				Writegrid.cc
 				Writerandom.cc
-				Yeararith.cc
-				Yearmonstat.cc
 				Ydayarith.cc
 				Ydaypctl.cc
 				Ydaystat.cc
 				Ydrunpctl.cc
 				Ydrunstat.cc
+				Yeararith.cc
+				Yearmonstat.cc
 				Yhourarith.cc
 				Yhourstat.cc
 				Ymonarith.cc
@@ -556,6 +573,13 @@ list( APPEND cdo_operators_src_files
 				Yseaspctl.cc
 				Yseasstat.cc
 				Zonstat.cc
+                Adisit.cc
+                Echam5ini.cc
+                Maggraph.cc
+                Magplot.cc
+                Magvector.cc
+                Setfilter.cc
+                Splitsel.cc
 )
 
 add_library(operators ${cdo_operators_src_files})
diff --git a/src/Ensstat.cc b/src/Ensstat.cc
index 1507c31229279d1ba4afa5369355a4fd7d2209aa..4272e1ff2a4bb38eba7d2fd70a110d147cc4a546 100644
--- a/src/Ensstat.cc
+++ b/src/Ensstat.cc
@@ -237,7 +237,7 @@ public:
     auto task = Options::CDO_task ? std::make_unique<cdo::Task>() : nullptr;
     const int numTasks = Options::CDO_task ? 2 : 1;
 
-    FieldVector workFields(Threading::ompNumThreads);
+    FieldVector workFields(Threading::ompNumMaxThreads);
     for (auto &work : workFields) work.resize(numFiles);
 
     FieldVector fieldVector[2];
diff --git a/src/Ensstat3.cc b/src/Ensstat3.cc
index 1b29f821bdd3a47b59fec2547004353e992b392d..f2cccf6958fcf2f3272685ec6631d58599704e87 100644
--- a/src/Ensstat3.cc
+++ b/src/Ensstat3.cc
@@ -158,8 +158,8 @@ public:
     /* ("first touch strategy")                            */
     /* --> #pragma omp parallel for ...                    */
     /* *************************************************** */
-    field = FieldVector(Threading::ompNumThreads);
-    for (int i = 0; i < Threading::ompNumThreads; ++i)
+    field = FieldVector(Threading::ompNumMaxThreads);
+    for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
       {
         field[i].resize(numFiles);
         field[i].weightv.resize(numFiles);
diff --git a/src/Fillmiss.cc b/src/Fillmiss.cc
index a9c935f7c58aa24f4f6dabec6e7377fa7b1abf91..1a500ce5b7e4fbbca90be96d2297a7dc74f2ceee 100644
--- a/src/Fillmiss.cc
+++ b/src/Fillmiss.cc
@@ -312,7 +312,7 @@ setmisstodis(Varray<T1> &vIn, Varray<T2> &vOut, int gridID, size_t numMissVals,
   if (nv != nvals) cdo_abort("Internal problem, number of valid values differ!");
 
   std::vector<KnnData> knnDataMem;
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataMem.push_back(KnnData(numNeighbors));
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataMem.push_back(KnnData(numNeighbors));
 
   cdo::timer timer;
 
diff --git a/src/Filter.cc b/src/Filter.cc
index f2dbc52d02155a0b14d159fe4925e0126aac0f56..79688d23aab0d2ae9f0e6604c1d30cabdc0473e8 100644
--- a/src/Filter.cc
+++ b/src/Filter.cc
@@ -272,7 +272,7 @@ public:
     if (Options::cdoVerbose)
       cdo_print("Allocate %zu array%s over %zu steps: size=%zu Bytes", numArrays, numArrays > 1 ? "s" : "", nts, allocatedMem);
 
-    std::vector<FilterMemory> fourierMemory(Threading::ompNumThreads);
+    std::vector<FilterMemory> fourierMemory(Threading::ompNumMaxThreads);
 
     if (useFFTW)
       {
diff --git a/src/Fourier.cc b/src/Fourier.cc
index 4812d9d0daf705c5dfb59770d97548b5b1994fab..ae68101afa6d563eb0fb1dfda76186a5e5d3b24e 100644
--- a/src/Fourier.cc
+++ b/src/Fourier.cc
@@ -237,7 +237,7 @@ public:
 
     int nts = tsID;
 
-    std::vector<FourierMemory> fourierMemory(Threading::ompNumThreads);
+    std::vector<FourierMemory> fourierMemory(Threading::ompNumMaxThreads);
 
     if (use_fftw)
       {
diff --git a/src/Gridboxstat.cc b/src/Gridboxstat.cc
index 6aad078d61bccf77f6041af0bbba3a82957cfd5e..5a0c8ee8422fc970a630e0c5dfd439c9f4931235 100644
--- a/src/Gridboxstat.cc
+++ b/src/Gridboxstat.cc
@@ -231,8 +231,8 @@ gridbox_stat(const Field &field1, Field &field2, size_t xinc, size_t yinc, int s
   auto useWeight = !field1.weightv.empty();
 
   auto boxsize = xinc * yinc;
-  FieldVector fields(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  FieldVector fields(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       fields[i].resize(boxsize);
       if (useWeight) fields[i].weightv.resize(boxsize);
diff --git a/src/Intlevel.cc b/src/Intlevel.cc
index bb8c823359aef9a95fddf840fdf75b5123e08fe6..58bbb7ba31d04e73a20e79433c12b22e22032f23 100644
--- a/src/Intlevel.cc
+++ b/src/Intlevel.cc
@@ -211,7 +211,7 @@ static void
 vert_gen_weights3d1d(bool extrapolate, size_t gridsize, int nlev1, const Varray<T> &xlev1, int nlev2,
                      const std::vector<double> &lev2, Varray<int> &xlev_idx, Varray<float> &xlev_wgt)
 {
-  auto nthreads = Threading::ompNumThreads;
+  auto nthreads = Threading::ompNumMaxThreads;
   Varray2D<double> lev1p2(nthreads, Varray<double>(nlev1 + 2));
   Varray2D<float> lev_wgt(nthreads, Varray<float>(nlev2));
   Varray2D<int> lev_idx(nthreads, Varray<int>(nlev2));
diff --git a/src/Intlevel3d.cc b/src/Intlevel3d.cc
index aab6a491f8bf03a4269aada3748545b731b90e32..2dadae8dd233c7916d707b8f41851c766feec89b 100644
--- a/src/Intlevel3d.cc
+++ b/src/Intlevel3d.cc
@@ -39,7 +39,7 @@ static void
 vert_gen_weights3d(bool expol, size_t gridsize, int nlev1, const Varray<float> &xlev1, int nlev2, const Varray<float> &xlev2,
                    Varray<int> &xlev_idx, Varray<float> &xlev_wgt)
 {
-  auto nthreads = Threading::ompNumThreads;
+  auto nthreads = Threading::ompNumMaxThreads;
   Varray2D<double> lev1p2(nthreads, Varray<double>(nlev1 + 2));
   Varray2D<double> lev2(nthreads, Varray<double>(nlev2));
   Varray2D<float> lev_wgt(nthreads, Varray<float>(nlev2));
diff --git a/src/Makefile.am b/src/Makefile.am
index c01e042ea5276f2f12ddcc9844044b5ac1b5a069..1f4cb55327573c4299a82c0abe1ad4a7020c839d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,8 @@ libcdo_la_SOURCES = after_dvtrans.cc      \
 				cdo_cmor.h                \
 				cdo_data.cc               \
 				cdo_data.h                \
+				cdo_def_options.cc 		  \
+				cdo_def_options.h         \
 				cdo_default_values.cc     \
 				cdo_default_values.h      \
 				cdo_features.cc           \
diff --git a/src/Remapstat.cc b/src/Remapstat.cc
index fdc785498ff41d9089e026173986f14276e87768..888817f4e11dda7bed22de926b463a0478af7cc2 100644
--- a/src/Remapstat.cc
+++ b/src/Remapstat.cc
@@ -519,8 +519,8 @@ gen_mapdata(int gridID1, int gridID2)
       auto maxIndex = gridsize1;
       if (gridsize1 > 1000000) maxIndex /= 4;
       Vmask vmask(gridsize1, 0);
-      Varray2D<size_t> indices_2D(Threading::ompNumThreads, Varray<size_t>(maxIndex));
-      Varray2D<double> dist_2D(Threading::ompNumThreads, Varray<double>(maxIndex));
+      Varray2D<size_t> indices_2D(Threading::ompNumMaxThreads, Varray<size_t>(maxIndex));
+      Varray2D<double> dist_2D(Threading::ompNumMaxThreads, Varray<double>(maxIndex));
 
       StatInfo statInfo;
 
@@ -560,10 +560,10 @@ gen_mapdata(int gridID1, int gridID2)
             }
 
           // if (Options::cdoVerbose) printf("%zu numIndices %zu nvalues %zu  maxdist %g\n", i+1, numIndices, nvalues, maxdist);
-          if (Options::cdoVerbose && Threading::ompNumThreads == 1) statInfo.add(numIndices, nvalues, searchRadius);
+          if (Options::cdoVerbose && Threading::ompNumMaxThreads == 1) statInfo.add(numIndices, nvalues, searchRadius);
         }
 
-      if (Options::cdoVerbose && Threading::ompNumThreads == 1) statInfo.print();
+      if (Options::cdoVerbose && Threading::ompNumMaxThreads == 1) statInfo.print();
       if (Options::cdoVerbose) check_vmask(vmask);
       if (Options::cdoVerbose) cdo_print("Point search qnearest: %.2f seconds", timer.elapsed());
 
@@ -608,7 +608,7 @@ remap_kernel(int operfunc, const Varray<size_t> &indices, size_t &numMissVals2,
 static void
 remap_field(const Varray2D<size_t> &mapdata, const Field &field1, Field &field2, int operfunc)
 {
-  std::vector<Field> fields(Threading::ompNumThreads);
+  std::vector<Field> fields(Threading::ompNumMaxThreads);
 
   auto gridsize2 = gridInqSize(field2.grid);
   cdo::timer timer;
diff --git a/src/Runpctl.cc b/src/Runpctl.cc
index 0756b5193ba93697643d7c4ed472341dacc4185b..4c5b8f40d6bb29cc996a70e1bad6a8552c6cdebb 100644
--- a/src/Runpctl.cc
+++ b/src/Runpctl.cc
@@ -28,7 +28,7 @@ runpctl(double pn, int ndates, size_t gridsize, Varray<T> &v2, double mv, const
 {
   T missval = mv;
   size_t numMissVals = 0;
-  Varray2D<T> array_2D(Threading::ompNumThreads, Varray<T>(ndates));
+  Varray2D<T> array_2D(Threading::ompNumMaxThreads, Varray<T>(ndates));
 
 #ifdef _OPENMP
 #pragma omp parallel for default(shared) schedule(dynamic)
diff --git a/src/Samplegridicon.cc b/src/Samplegridicon.cc
index ae8645f386b6e731b7bee9ec51a58ea9e56a6fee..5c2189bac6230029cbe10ae66f29f2e3f896ada2 100644
--- a/src/Samplegridicon.cc
+++ b/src/Samplegridicon.cc
@@ -311,7 +311,7 @@ compute_child_from_bounds(CellIndex &cellindex2, Varray<double> &grid_center_lon
 
   constexpr int MaxSearch = 128;
   std::vector<KnnData> knnDataMem;
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataMem.push_back(KnnData(MaxSearch));
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataMem.push_back(KnnData(MaxSearch));
 
   cellindex2.child.resize(MAX_CHILDS * ncells2);
   auto &child2 = cellindex2.child;
diff --git a/src/Smooth.cc b/src/Smooth.cc
index f4483f0343f977f8f30f64325ca2a1e02fed3d59..9da7e42aaddc67ebf33b911014fd28d37dcb6896 100644
--- a/src/Smooth.cc
+++ b/src/Smooth.cc
@@ -72,7 +72,7 @@ smooth(int gridID, double mv, const Varray<T1> &array1, Varray<T2> &array2, cons
   knnParams.weightR = spoint.weightR;
 
   std::vector<KnnData> knnDataList;
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataList.push_back(KnnData(knnParams));
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataList.push_back(KnnData(knnParams));
 
   cdo::timer timer;
 
diff --git a/src/Templates.cc b/src/Templates.cc
index e05f52ab1c0ddc56152a768886c8f9dac1d86337..6bbc77dc600159c20589d2de4e8fb17f4bea5afc 100644
--- a/src/Templates.cc
+++ b/src/Templates.cc
@@ -9,6 +9,8 @@
 
 #include "process_int.h"
 
+// THIS IS A TEMPLATE FOR LATER USE
+class Template
 {
   CdoStreamID streamID1;
   int taxisID1;
@@ -84,6 +86,7 @@ public:
   }
 };
 
+class Template2
 {
   size_t numMissVals;
 
diff --git a/src/Timfillmiss.cc b/src/Timfillmiss.cc
index 0a0cd0a5f8ee1c1faff0ec65a85d0c7ddeaf1678..25a4cda343fae6d16f7b634053059c7dff894108 100644
--- a/src/Timfillmiss.cc
+++ b/src/Timfillmiss.cc
@@ -195,7 +195,7 @@ public:
         timeValues[tsID] = julianDate_to_double(calendar, dtlist.get_vDateTime(tsID), dtlist.get_vDateTime(0));
       }
 
-    dataValues2D = Varray2D<double>(Threading::ompNumThreads);
+    dataValues2D = Varray2D<double>(Threading::ompNumMaxThreads);
     for (auto &dataValues : dataValues2D) dataValues.resize(numSteps);
 
     for (int varID = 0; varID < numVars; ++varID) { step(varID); }
diff --git a/src/Timsort.cc b/src/Timsort.cc
index a2e56c862299e50844b5ae5014ff0e066fcb3d93..119bb8e1564f237d5f98e0c25f878a689cec20ad 100644
--- a/src/Timsort.cc
+++ b/src/Timsort.cc
@@ -104,7 +104,7 @@ public:
 
     int nts = tsID;
 
-    std::vector<Field> fields(Threading::ompNumThreads);
+    std::vector<Field> fields(Threading::ompNumMaxThreads);
 
     for (int varID = 0; varID < numVars; ++varID)
       {
diff --git a/src/Tstepcount.cc b/src/Tstepcount.cc
index c7796796cc697688dbf795bfe1aed9d435efbf10..35c76835ef139ffa8b957920d79530a5cce372b7 100644
--- a/src/Tstepcount.cc
+++ b/src/Tstepcount.cc
@@ -120,7 +120,7 @@ public:
 
     int nts = tsID;
 
-    std::vector<Field> fields(Threading::ompNumThreads);
+    std::vector<Field> fields(Threading::ompNumMaxThreads);
 
     for (int varID = 0; varID < numVars; ++varID)
       {
diff --git a/src/Vertfillmiss.cc b/src/Vertfillmiss.cc
index 72d3a0616c36b381983507b6e594be58730af1d2..d15f56784659196f73e251afd384885e04cf52b3 100644
--- a/src/Vertfillmiss.cc
+++ b/src/Vertfillmiss.cc
@@ -113,7 +113,7 @@ public:
     auto numLevels = var.nlevels;
     auto missval = var.missval;
 
-    Varray2D<double> dataValues2D(Threading::ompNumThreads);
+    Varray2D<double> dataValues2D(Threading::ompNumMaxThreads);
     for (auto &dataValues : dataValues2D) dataValues.resize(numLevels);
 
     Varray<double> levelValues(numLevels);
diff --git a/src/after_fctrans.cc b/src/after_fctrans.cc
index 2b7830c26bdd49e8ece8249ea1a9bbdfcf567690..18b978b3a5d091b04e28ed6b7ee37ae0cffb1937 100644
--- a/src/after_fctrans.cc
+++ b/src/after_fctrans.cc
@@ -2013,7 +2013,7 @@ fc2gp(const double *restrict trig, const long *restrict ifax, const double *rest
   long nvexx = lot - (nblox - 1) * NFFT;
   const long nvex0 = nvexx;
 
-  const long nthmax = (nblox < Threading::ompNumThreads) ? nblox : Threading::ompNumThreads;
+  const long nthmax = (nblox < Threading::ompNumMaxThreads) ? nblox : Threading::ompNumMaxThreads;
   const long nvals = lot * jump;
 
   Varray<double> wfc(nvals);
diff --git a/src/after_sptrans.cc b/src/after_sptrans.cc
index 07a30cfbfc3725728633521e7b6821dd4824309e..63a1e27651b7aac71b61a5135640c9202f76e7e4 100644
--- a/src/after_sptrans.cc
+++ b/src/after_sptrans.cc
@@ -126,15 +126,15 @@ after_legini_full(long ntr, long nlat, double *restrict poli, double *restrict p
   auto needHnm = (pdev != nullptr) || (pol2 != nullptr);
 
 #ifdef _OPENMP
-  Varray2D<double> pnm_2(Threading::ompNumThreads);
-  Varray2D<double> hnm_2(Threading::ompNumThreads);
-  Varray2D<double> ztemp1_2(Threading::ompNumThreads);
-  Varray2D<double> ztemp2_2(Threading::ompNumThreads);
-  for (long i = 0; i < Threading::ompNumThreads; ++i) pnm_2[i].resize(dimsp);
+  Varray2D<double> pnm_2(Threading::ompNumMaxThreads);
+  Varray2D<double> hnm_2(Threading::ompNumMaxThreads);
+  Varray2D<double> ztemp1_2(Threading::ompNumMaxThreads);
+  Varray2D<double> ztemp2_2(Threading::ompNumMaxThreads);
+  for (long i = 0; i < Threading::ompNumMaxThreads; ++i) pnm_2[i].resize(dimsp);
   if (needHnm)
-    for (long i = 0; i < Threading::ompNumThreads; ++i) hnm_2[i].resize(dimsp);
-  for (long i = 0; i < Threading::ompNumThreads; ++i) ztemp1_2[i].resize(twowaves);
-  for (long i = 0; i < Threading::ompNumThreads; ++i) ztemp2_2[i].resize(twowaves);
+    for (long i = 0; i < Threading::ompNumMaxThreads; ++i) hnm_2[i].resize(dimsp);
+  for (long i = 0; i < Threading::ompNumMaxThreads; ++i) ztemp1_2[i].resize(twowaves);
+  for (long i = 0; i < Threading::ompNumMaxThreads; ++i) ztemp2_2[i].resize(twowaves);
 #else
   Varray<double> pnm(dimsp), hnm, ztemp1(twowaves), ztemp2(twowaves);
   if (needHnm) hnm.resize(dimsp);
@@ -197,7 +197,7 @@ sp2fc(const double *sa, double *fa, const double *poli, long nlev, long nlat, lo
   cumindex[0] = 0;
   for (long jmm = 1; jmm < ntp1; jmm++) cumindex[jmm] = cumindex[jmm - 1] + (ntp1 - jmm + 1);
 
-  if (nlev >= Threading::ompNumThreads)
+  if (nlev >= Threading::ompNumMaxThreads)
     {
 #ifdef _OPENMP
 #pragma omp parallel for default(shared)
@@ -268,7 +268,7 @@ fc2sp(const double *fa, double *sa, const double *poli, long nlev, long nlat, lo
   cumindex[0] = 0;
   for (long jmm = 1; jmm < ntp1; jmm++) cumindex[jmm] = cumindex[jmm - 1] + (ntp1 - jmm + 1);
 
-  if (nlev >= Threading::ompNumThreads)
+  if (nlev >= Threading::ompNumMaxThreads)
     {
 #ifdef _OPENMP
 #pragma omp parallel for default(shared)
diff --git a/src/bitinformation.cc b/src/bitinformation.cc
index e12c4212c604d5ca9d762660823a5a92106400f5..53158a4c59a586231af42e413935ccab174a0241 100644
--- a/src/bitinformation.cc
+++ b/src/bitinformation.cc
@@ -134,7 +134,7 @@ bitpair_count(float *A, float *B, size_t n)
   uint32_t *Buint = (uint32_t *) B;
 
 #ifdef CDO
-  std::vector<BitpairCounters> BC(Threading::ompNumThreads);
+  std::vector<BitpairCounters> BC(Threading::ompNumMaxThreads);
 #else
   std::vector<BitpairCounters> BC(1);
 #endif
@@ -158,7 +158,7 @@ bitpair_count(float *A, float *B, size_t n)
 
 #ifdef CDO
 #ifdef _OPENMP
-  for (int m = 1; m < Threading::ompNumThreads; ++m)
+  for (int m = 1; m < Threading::ompNumMaxThreads; ++m)
     {
       for (int k = 0; k < NBITS; ++k)
         for (int j = 0; j < 2; ++j)
diff --git a/src/cdo.cc b/src/cdo.cc
index 62addce2d4267afe2814703ba70f21ea95e5eecf..dc712f3ab0b11d398a49de7527d3d8ea4f0a90f9 100644
--- a/src/cdo.cc
+++ b/src/cdo.cc
@@ -22,35 +22,26 @@
 
 #include <cdi.h>
 
-#include "cpp_lib.h"
+//#include "cpp_lib.h"
 #include "cdo_timer.h"
 #include "cdo_getopt.h"
 #include "cdo_settings.h"
 #include "cdo_rlimit.h"
-#include "mpim_grid.h"
-#include "griddes.h"
 #include "cdo_default_values.h"
 #include "param_conversion.h"
 #include "progress.h"
 #include "module_info.h"
-#include "percentiles.h"
 #include "util_wildcards.h"
-#include "util_string.h"
 #include "process_int.h"
 #include "processManager.h"
-#include "cdo_options.h"
 #include "commandline.h"
 #include "mpmo_color.h"
 #include "cdo_output.h"
 #include "cdo_features.h"
-#include "cdo_zaxis.h"
-#include "table.h"
-#include "datetime.h"
-#include "grid_cellsearch.h"
 #include "cdo_pthread.h"
-#include "institution.h"
 #include "parser.h"
 #include "factory.h"
+#include "cdo_def_options.h"
 
 static ProcessManager g_processManager;
 
@@ -62,16 +53,12 @@ cdo_exit(std::string msg = "")
   exit(EXIT_FAILURE);
 }
 
-static int CDO_numThreads = 0;
-static int CDO_Rusage = 0;
 static bool applyDryRun = false;
 
 #ifdef HIRLAM_EXTENSIONS
 extern "C" void streamGrbDefDataScanningMode(int scanmode);
 #endif
 
-void set_pointsearch_method(const std::string &methodStr);
-
 static void
 cdo_display_syntax_help(const std::string &help, FILE *p_target)
 {
@@ -262,22 +249,6 @@ cdo_print_debug_info()
   print_pthread_info();
 }
 
-static std::string
-predefined_tables(int p_padding)
-{
-  const char *name;
-  constexpr int id_padding = 4;
-  int padding = p_padding + id_padding;
-  int numTables = tableInqNumber();
-  std::string tables{ "Predefined tables: " };
-  for (int id = 0; id < numTables; id++)
-    {
-      if (id % 7 == 6) tables += std::string("\n") + std::string(padding, ' ');
-      if ((name = tableInqNamePtr(id))) tables += std::string(name);
-      if (id < numTables - 1) tables += ",";
-    }
-  return tables;
-}
 
 static void
 create_options_from_envvars()
@@ -293,184 +264,7 @@ create_options_from_envvars()
   CLIOptions::option_from_envvar("CDO_TEST");
 }
 
-static void
-setup_cli_options()
-{
-  CLIOptions::option("envvars")
-      ->add_effect([&]() { CLIOptions::print_envvars = true; })
-      ->aborts_program(true)
-      ->set_category("Info")
-      ->add_help("Prints the environment variables of CDO.");
-
-  CLIOptions::option("settings")
-      ->add_effect([&]() { CLIOptions::print_settings = true; })
-      ->aborts_program(true)
-      ->set_category("Info")
-      ->add_help("Prints the settings of CDO.");
-
-  CLIOptions::option("debug", "d")
-      ->add_effect([&]() {
-        unsigned cdoDebugLevel = 0;
-        unsigned cdiDebugLevel = 0;
-        cdo::parse_debug_arguments({ "1" }, cdoDebugLevel, cdiDebugLevel);
-
-        cdiDebug(cdiDebugLevel);
-        cdo::set_debug(cdoDebugLevel);
-        cdo::features::version();
-      })
-      ->set_category("Output")
-      ->add_help("Pring all available debug messages");
-
-  CLIOptions::option("scoped_debug", "D")
-      ->describe_argument("comma seperated scopes")
-      ->set_category("Output")
-      ->on_empty_argument([]() {
-        std::cerr << "No debug level given please choose: " << std::endl;
-        print_debug_options();
-        exit(EXIT_SUCCESS);
-      })
-      ->add_effect([&](const std::string &argument) {
-        auto [success, tokens] = tokenize_comma_seperated_int_list(argument);
-        if (tokens.empty())
-          {
-            print_debug_options();
-            exit(EXIT_SUCCESS);
-          }
-
-        unsigned cdoDebugLevel = 0;
-        unsigned cdiDebugLevel = 0;
-        cdo::parse_debug_arguments(tokens, cdoDebugLevel, cdiDebugLevel);
-
-        cdiDebug(cdiDebugLevel);
-        cdo::set_debug(cdoDebugLevel);
-
-        cdo::features::version();
-      })
-      ->add_help("Multiple scopes simultaneously possible. Use this option without arguments to get a list of possible scopes");
-
-  CLIOptions::option("worker")
-      ->describe_argument("num")
-      ->add_effect([&](const std::string &argument) { Options::numStreamWorker = parameter_to_int(argument); })
-      ->set_category("Multi Threading")
-      ->add_help("Number of worker to decode/decompress GRIB records.");
-
-  CLIOptions::option("precision")
-      ->describe_argument("float_digits[,double_digits]")
-      ->add_effect([&](const std::string &argument) { cdo::set_digits(argument); })
-      ->set_category("Numeric")
-      ->add_help("Precision to use in displaying floating-point data (default: 7,15).");
-
-  CLIOptions::option("percentile")
-      ->describe_argument("method")
-      ->set_category("Numeric")
-      ->add_effect([&](const std::string &argument) { percentile_set_method(argument); })
-      ->add_help("Methods: nrank, nist, rtype8, <NumPy method (linear|lower|higher|nearest|...)>");
-
-  CLIOptions::option("netcdf_hdr_pad")
-      ->describe_argument("nbr")
-      ->add_effect([&](const std::string &argument) {
-        int netcdf_hdr_pad = parameter_to_bytes(argument);
-        if (netcdf_hdr_pad >= 0) cdo::netcdf_hdr_pad = netcdf_hdr_pad;
-      })
-      ->add_help("Pad NetCDF output header with nbr bytes.");
-
-  CLIOptions::option("use_fftw")
-      ->describe_argument("true|false")
-      ->add_effect([&](const std::string &argument) { Options::Use_FFTW = (int) parameter_to_bool(argument); })
-      ->add_help("Sets fftw usage.");
-
-  CLIOptions::option("config")
-      ->describe_argument("all|all-json|<specific_feature_name>")
-      ->add_effect([&](const std::string &argument) { cdo::features::print_config(argument); })
-      ->on_empty_argument([&]() { cdo::features::print_argument_options(); })
-      ->aborts_program(true)
-      ->set_category("Info")
-      ->add_help("Prints all features and the enabled status.", "Use option <all> to see explicit feature names.");
-
-  CLIOptions::option("pointsearchmethod")
-      ->set_internal(true)
-      ->describe_argument("<kdtree|nanoflann|spherepart|full>")
-      ->set_category("Search Methods")
-      ->add_effect([&](const std::string &argument) { set_pointsearch_method(argument); })
-      ->add_help("Sets the point search method.");
-
-  CLIOptions::option("gridsearchradius")
-      ->describe_argument("degrees[0..180]")
-      ->set_category("Search Methods")
-      ->add_effect([&](const std::string &argument) {
-        auto fval = radius_str_to_deg(argument);
-        if (fval < 0 || fval > 180) cdo_abort("%s=%g out of bounds (0-180 deg)!", "gridsearchradius", fval);
-        cdo_set_search_radius(fval);
-      })
-      ->add_help("Sets the grid search radius (0-180 deg).");
-
-  CLIOptions::option("remap_weights")
-      ->describe_argument("0|1")
-      ->add_effect([&](const std::string &argument) {
-        auto intarg = parameter_to_int(argument);
-        if (intarg != 0 && intarg != 1) cdo_abort("Unsupported value for option --remap_weights %d [0/1]", intarg);
-        Options::REMAP_genweights = intarg;
-      })
-      ->add_help("Generate remap weights (default: 1).");
-
-  CLIOptions::option("no_remap_weights")
-      ->add_effect([&]() { Options::REMAP_genweights = 0; })
-      ->add_help("Switch off generation of remap weights.");
-
-  CLIOptions::option("enableexcept")
-      ->describe_argument("except")
-      ->set_category("Numeric")
-      ->add_effect([&](const std::string &argument) {
-        auto except = cdo::evaluate_except_options(argument);
-        if (except < 0) cdo_abort("option --%s: unsupported argument: %s", "enableexcept", argument);
-        cdo::set_feenableexcept(except);
-        if (signal(SIGFPE, cdo::signal_handler) == SIG_ERR) cdo_warning("can't catch SIGFPE!");
-      })
-      ->add_help("Set individual floating-point traps ", "(DIVBYZERO, INEXACT, INVALID, OVERFLOW, UNDERFLOW, ALL_EXCEPT)");
-
-  CLIOptions::option("timestat_date")
-      ->describe_argument("srcdate")
-      ->add_effect([&](const std::string &argument) { set_timestat_date(argument); })
-      ->add_help("Target timestamp (temporal statistics): ", "first, middle, midhigh or last source timestep.");
-
-  CLIOptions::option("ignore_time_bounds")
-      ->add_effect([&]() {
-        extern bool CDO_Ignore_Time_Bounds;
-        CDO_Ignore_Time_Bounds = true;
-      })
-      ->add_help("Ignores time bounds for time range statistics.");
-
-  CLIOptions::option("use_time_bounds")
-      ->add_effect([&]() {
-        extern bool CDO_Use_Time_Bounds;
-        CDO_Use_Time_Bounds = true;
-      })
-      ->add_help("Enables use of timebounds.");
-
-  CLIOptions::option("cmor")->add_effect([&]() { Options::CMOR_Mode = 1; })->add_help("CMOR conform NetCDF output.");
-
-  CLIOptions::option("reduce_dim")->add_effect([&]() { Options::CDO_Reduce_Dim = 1; })->add_help("Reduce NetCDF dimensions.");
-
-  CLIOptions::option("float")
-      ->add_effect([&]() { Options::CDO_Memtype = MemType::Float; })
-      ->set_category("Numeric")
-      ->add_help("Using single precision floats for data in memory.");
-
-  CLIOptions::option("single")
-      ->add_effect([&]() { Options::CDO_Memtype = MemType::Float; })
-      ->set_category("Numeric")
-      ->add_help("Using single precision floats for data in memory.");
-
-  CLIOptions::option("double")
-      ->add_effect([&]() { Options::CDO_Memtype = MemType::Double; })
-      ->set_category("Numeric")
-      ->add_help("Using double precision floats for data in memory.");
-
-  CLIOptions::option("rusage")
-      ->add_effect([&]() { CDO_Rusage = 1; })
-      ->add_help("Print information about resource utilization.")
-      ->set_category("Info");
-
+static void setup_cli_options(){
   CLIOptions::option("attribs")
       ->describe_argument("arbitrary|filesOnly|onlyFirst|noOutput|obase")
       ->aborts_program(true)
@@ -504,32 +298,17 @@ setup_cli_options()
           }
       })
       ->add_help("Prints list of operators.");
-
   CLIOptions::option("operators_no_output")
       ->aborts_program(true)
       ->add_effect([&]() { print_operator_attributes("noOutput"); })
       ->set_category("Info")
       ->add_help("Prints all operators which produce no output.");
-
-  CLIOptions::option("pedantic")->add_effect([&]() { MpMO::enable_pedantic(true); })->add_help("Warnings count as errors.");
-
   CLIOptions::option("color", "C")
       ->describe_argument("auto|no|all")
       ->add_effect([&](const std::string &argument) { cdo::evaluate_color_options(argument); })
       ->set_category("Output")
       ->add_help("Set behaviour of colorized output messages.");
-
-  CLIOptions::option("eccodes")
-      ->add_effect([&]() { cdiDefGlobal("ECCODES_GRIB1", true); })
-      ->set_category("Format Specific")
-      ->add_help("Use ecCodes to decode/encode GRIB1 messages.");
-
-  CLIOptions::option("format", "f")
-      ->describe_argument("grb1|grb2|nc1|nc2|nc4|nc4c|nc5|nczarr|srv|ext|ieg")
-      ->add_effect([&](const std::string &argument) { cdo::set_default_filetype(argument); })
-      ->add_help("Format of the output file.");
-
-  CLIOptions::option("help", "h")
+ CLIOptions::option("help", "h")
       ->describe_argument("operator")
       ->add_effect([&](const std::string &operator_name) { cdo_print_help(operator_name); })
       ->on_empty_argument([]() { cdo_usage(stdout); })
@@ -537,245 +316,14 @@ setup_cli_options()
       ->set_category("Help")
       ->add_help("Shows either help information for the given operator or the usage of CDO.");
 
-  CLIOptions::option("history")
-      ->add_effect([&]() { Options::CDO_Append_History = true; })
-      ->set_category("History")
-      ->add_help("Do append to NetCDF \"history\" global attribute.");
-
-  CLIOptions::option("no_history")
-      ->add_effect([&]() { Options::CDO_Append_History = false; })
-      ->set_category("History")
-      ->add_help("Do not append to NetCDF \"history\" global attribute.");
-
-  CLIOptions::option("version", "V")
-      ->add_effect([&]() { cdo::features::version(); })
-      ->aborts_program(true)
-      ->set_category("Info")
-      ->add_help("Print the version number.");
-
-  CLIOptions::option("dryrun", "A")->add_effect([&]() { applyDryRun = true; })->add_help("Dry run that shows processed CDO call.");
-
-  CLIOptions::option("absolute_taxis", "a")
-      ->add_effect([&]() {
-        if (CdoDefault::TaxisType == TAXIS_RELATIVE)
-          cdo_abort("option --%s: can't be combined with option --%s", "absolute_taxis (-a)", "relative_taxis (-r)");
-        CdoDefault::TaxisType = TAXIS_ABSOLUTE;
-      })
-      ->add_help("Generate an absolute time axis.");
-
-  CLIOptions::option("force")->add_effect([&]() { Options::force = true; })->add_help("Forcing a CDO process.");
-
-  CLIOptions::option("fast")
-      ->set_internal(true)
-      ->add_effect([&]() {
-        Options::fast = true;
-        cdiDefGlobal("NETCDF_LAZY_GRID_LOAD", true);
-      })
-      ->add_help("If available, use a faster method even if it requires more memory.");
-
-  // clang-format off
-  CLIOptions::option("default_datatype", "b")
-      ->describe_argument("nbits")
-      ->set_category("Numeric")
-      ->add_effect([&](const std::string &argument) { cdo::set_default_datatype(argument); })
-      ->add_help("Set the number of bits for the output precision",
-                 "    I8|I16|I32|F32|F64     for nc1,nc2,nc4,nc4c,nc5,nczarr;",
-                 "    U8|U16|U32             for nc4,nc4c,nc5;",
-                 "    F32|F64                for grb2,srv,ext,ieg;",
-                 "    P1 - P24               for grb1,grb2");
-  // clang-format on
-
-  CLIOptions::option("check_data_range", "c")
-      ->add_effect([&]() { Options::CheckDatarange = true; })
-      ->add_help("Enables checks for data overflow.");
-
-  CLIOptions::option("grid", "g")
-      ->describe_argument("grid")
-      ->add_effect([&](const std::string &argument) { cdo_set_grids(argument); })
-      ->add_help("Set default grid name or file. Available grids: ",
-                 "F<XXX>, t<RES>, tl<RES>, r<NX>x<NY>, global_<DXY>, zonal_<DY>, gme<NI>, lon=<LON>/lat=<LAT>, hpz<ZOOM>");
-
-  CLIOptions::option("institution", "i")
-      ->describe_argument("institute_name")
-      ->add_effect([&](const std::string &argument) { define_institution(argument); })
-      ->add_help("Sets institution name.");
-
-  CLIOptions::option("chunktype", "k")
-      ->describe_argument("auto|grid|lines")
-
-      ->set_category("Format Specific")
-      ->add_effect([&](const std::string &argument) { cdo::set_chunktype(argument); })
-      ->add_help("NetCDF4 chunk type: auto, grid or lines.");
-
-  CLIOptions::option("chunksize")
-      ->describe_argument("size")
-      ->set_category("Format Specific")
-      ->add_effect([&](const std::string &argument) {
-        int chunkSize = parameter_to_bytes(argument);
-        if (chunkSize >= 0) Options::cdoChunkSize = chunkSize;
-      })
-      ->add_help("NetCDF4 chunk size.");
-
-  CLIOptions::option("lock_io", "L")->add_effect([&]() { Threading::cdoLockIO = true; })->add_help("Lock IO (sequential access).");
-
-  CLIOptions::option("zaxis", "l")
-      ->describe_argument("zaxis")
-      ->add_effect([&](const std::string &argument) { cdo_set_zaxes(argument); })
-      ->add_help("Set default zaxis name or file.");
-
-  CLIOptions::option("set_missval", "m")
-      ->describe_argument("missval")
-      ->add_effect([&](const std::string &argument) { cdiDefMissval(std::stof(argument)); })
-      ->add_help("Set the missing value of non NetCDF files (default: " + get_scientific(cdiInqMissval()) + ").");
-
-  CLIOptions::option("has_missval", "M")
-      ->add_effect([&]() { cdiDefGlobal("HAVE_MISSVAL", true); })
-      ->add_help("Set HAS_MISSVAL to true.");
-
-  CLIOptions::option("varnames", "n")
-      ->set_internal(true)
-      ->describe_argument("<varname| file>")
-      ->add_effect([&](const std::string &argument) { Options::cdoVarnames = split_string(argument, ","); })
-      ->add_help("Set default varnames or file.");
-
   CLIOptions::option("overwrite", "O")
       ->add_effect([&]() { Options::cdoOverwriteMode = true; })
       ->add_help("Overwrite existing output file, if checked.");
 
-  CLIOptions::option("num_threads", "P")
-      ->describe_argument("nthreads")
-      ->add_effect([&](const std::string &argument) { CDO_numThreads = parameter_to_int(argument); })
-      ->set_category("Multi Threading")
-      ->add_help("Set number of OpenMP threads.");
-
-  CLIOptions::option("parrallel_read", "p")
-      ->set_internal(true)
-      ->add_effect([&]() {
-        Options::CDO_Parallel_Read = true;
-        Options::CDO_task = true;
-      })
-      ->set_category("Multi Threading")
-      ->add_help("Enables parallel read.");
-
-  CLIOptions::option("sortname", "Q")
-      ->add_effect([&]() { cdiDefGlobal("SORTNAME", true); })
-      ->set_category("Format Specific")
-      ->add_help("Alphanumeric sorting of NetCDF parameter names.");
-
-  CLIOptions::option("seed")
-      ->describe_argument("seed")
-      ->set_category("Numeric")
-      ->add_effect([&](const std::string &argument) {
-        int intarg = parameter_to_int(argument);
-        if (intarg < 0) cdo_abort("Unsupported value for option --seed %d [>=0]", intarg);
-        Options::Random_Seed = intarg;
-      })
-      ->add_help("Seed for a new sequence of pseudo-random numbers. <seed> must be >= 0");
-
-  CLIOptions::option("regular", "R")
-      ->add_effect([&]() {
-        Options::cdoRegulargrid = true;
-        cdiDefGlobal("REGULARGRID", true);
-      })
-      ->set_category("CGRIBEX")
-      ->add_help("Convert GRIB1 data from global reduced to regular Gaussian grid (cgribex only).");
-
-  CLIOptions::option("relative_taxis", "r")
-      ->add_effect([&]() {
-        if (CdoDefault::TaxisType == TAXIS_ABSOLUTE)
-          cdo_abort("option --%s: can't be combined with option --%s", "relative_taxis (-r)", "absolute_taxis (-a)");
-        CdoDefault::TaxisType = TAXIS_RELATIVE;
-      })
-      ->add_help("Generate a relative time axis.");
-
-  CLIOptions::option("cdo_diagnostic", "S")
-      ->add_effect([&]() { Options::cdoDiag = true; })
-      ->add_help("Create an extra output stream for the module TIMSTAT. This stream",
-                 "contains the number of non missing values for each output period.");
-
-  CLIOptions::option("silent", "s")
-      ->add_effect([&]() {
-        Options::silentMode = true;
-        MpMO::enable_silent_mode(Options::silentMode);
-      })
-      ->set_category("Output")
-      ->add_help("Silent mode.");
-
-  CLIOptions::option("timer", "T")->add_effect([&]() { Options::Timer = true; })->add_help("Enable timer.");
-
-  CLIOptions::option("table", "t")
-      ->describe_argument("codetab")
-      ->set_category("CGRIBEX")
-      ->add_effect([&](const std::string &argument) { CdoDefault::TableID = cdo::define_table(argument); })
-      ->add_help("Set GRIB1 default parameter code table name or file (cgribex only).", predefined_tables(CLIOptions::padding));
-
   CLIOptions::option("interactive", "u")
       ->add_effect([&]() { Options::cdoInteractive = true; })
       ->add_help("Enable CDO interactive mode.");
 
-  CLIOptions::option("verbose", "v")
-      ->add_effect([&]() {
-        Options::cdoVerbose = true;
-        MpMO::enable_verbose(true);
-        CLIOptions::print_envvars = true;
-        gridEnableVerbose(Options::cdoVerbose);
-      })
-      ->add_help("Print extra details for some operators.");
-
-  CLIOptions::option("disable_warnings", "w")
-      ->add_effect([&]() {  // disable warning messages
-        MpMO::enable_warnings(false);
-        extern int _Verbose;  // CDI Warnings
-        _Verbose = 0;
-      })
-      ->set_category("Output")
-      ->add_help("Disable warning messages.");
-
-  CLIOptions::option("par_io", "X")
-      ->set_internal(true)
-      ->add_effect([&]() {
-        Options::cdoParIO = true;  // multi threaded I/O
-      })
-      ->add_help("Enables multithreaded I/O.")
-      ->set_category("Multi Threading");
-
-  CLIOptions::option("shuffle")
-      ->add_effect([&]() { Options::cdoShuffle = true; })
-      ->set_category("Compression")
-      ->add_help("Specify shuffling of variable data bytes before compression (NetCDF)");
-
-  CLIOptions::option("compress", "Z")
-      ->add_effect([&]() { Options::cdoCompress = true; })
-      ->set_category("Compression")
-      ->add_help("Enables compression. Default = SZIP");
-
-  CLIOptions::option("filter", "F")
-      ->describe_argument("filterspec")
-      ->add_effect([&](const std::string &argument) { cdo::set_filterspec(argument); })
-      ->set_category("Compression")
-      ->add_help("NetCDF4 filter specification");
-
-  CLIOptions::option("compression_type", "z")
-      ->describe_argument("aec|jpeg|zip[_1-9]|zstd[1-19]")
-      ->set_category("Compression")
-      ->add_effect([&](const std::string &argument) { cdo::set_compression_type(argument); })
-      ->add_help("aec         AEC compression of GRIB2 records", "jpeg        JPEG compression of GRIB2 records",
-                 "zip[_1-9]   Deflate compression of NetCDF4 variables", "zstd[_1-19] Zstandard compression of NetCDF4 variables");
-
-  CLIOptions::option("nsb")
-      ->set_internal(true)
-      ->describe_argument("1-23")
-      ->add_effect([&](const std::string &argument) { Options::nsb = parameter_to_int(argument); })
-      ->set_category("Numeric")
-      ->add_help("Number of significant bits used for bit-rounding.");
-
-  CLIOptions::option("show_available_options")
-      ->set_internal(true)
-      ->aborts_program(true)
-      ->set_category("Info")
-      ->add_effect([&]() { CLIOptions::print_available_options(); })
-      ->add_help("Shows all available optins and prints all shortforms, only internal use for testing.");
-
   CLIOptions::option("argument_groups")
       ->aborts_program(true)
       ->add_help("Explanation and Examples for subgrouping operators with [ ] syntax")
@@ -788,43 +336,8 @@ setup_cli_options()
       ->add_effect([&]() { cdo_display_syntax_help(Parser::apply_help, stderr); })
       ->set_category("Help");
 
-  CLIOptions::option("sortparam")->add_effect([]() { cdiDefGlobal("SORTPARAM", true); });
-
-#ifdef HIRLAM_EXTENSIONS
-  CLIOptions::option("Dkext")
-      ->describe_argument("debLev")
-      ->set_category("Hirlam Extension")
-      ->add_effect([&](const std::string &argument) {
-        auto extDebugVal = parameter_to_int(argument);
-        if (extDebugVal > 0)
-          {
-            extern int cdiDebugExt;
-            cdoDebugExt = extDebugVal;
-            cdiDebugExt = extDebugVal;
-          }
-      })
-      ->add_help("Setting debugLevel for extensions.");
-
-  CLIOptions::option("outputGribDataScanningMode")
-      ->describe_argument("mode")
-      ->set_category("Hirlam Extension")
-      ->add_effect([&](const std::string &argument) {
-        auto scanningModeValue = parameter_to_int(argument);
-        if (cdoDebugExt) printf("scanningModeValue=%d\n", scanningModeValue);
+  CLIOptions::option("dryrun", "A")->add_effect([&]() { applyDryRun = true; })->add_help("Dry run that shows processed CDO call.");
 
-        if ((scanningModeValue == 0) || (scanningModeValue == 64) || (scanningModeValue == 96))
-          {
-            streamGrbDefDataScanningMode(scanningModeValue);  // -1: not used; allowed modes: <0,
-                                                              // 64, 96>; Default is 64
-          }
-        else
-          {
-            cdo_warning("Warning: %d not in allowed modes: <0, 64, 96>; Using default: 64\n", scanningModeValue);
-            streamGrbDefDataScanningMode(64);
-          }
-      })
-      ->add_help("Setting grib scanning mode for data in output file <0, 64, 96>.", "Default is 64");
-#endif  // HIRLAM_EXTENSIONS
 }
 
 static void
@@ -868,6 +381,7 @@ main(int argc, char *argv[])
   create_options_from_envvars();
   CLIOptions::get_env_vars();
 
+  setup_options();
   setup_cli_options();
 
   auto CDO_optind = CLIOptions::parse(std::vector<std::string>(argv, argv + argc));
@@ -887,7 +401,7 @@ main(int argc, char *argv[])
       cdo::set_external_proj_func();
       cdo::set_stacksize(67108864);  // 64MB
       cdo::set_coresize(Options::coresize);
-      cdo::setup_openMP(CDO_numThreads);
+      cdo::setup_openMP(Threading::ompNumUserRequestedThreads);
 
       if (cdo::dbg()) cdo_print_debug_info();
 
@@ -930,7 +444,7 @@ main(int argc, char *argv[])
       if (Options::Timer) timer_report(allTimers);
     }
 
-  if (CDO_Rusage) cdo::features::print_rusage();
+  if (Options::CDO_Rusage) cdo::features::print_rusage();
 
   return Options::cdoExitStatus;
 }
diff --git a/src/cdo_benchmark.h b/src/cdo_benchmark.h
deleted file mode 100644
index bcfa64d9c73ab209159842b77eca86d72786198e..0000000000000000000000000000000000000000
--- a/src/cdo_benchmark.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef CDO_BENCHMARK_H
-#define CDO_BENCHMARK_H
-#define DBE2
-#ifdef DBE2
-
-#include <iostream>
-#include <chrono>
-
-template <typename func>
-void
-cdo_benchmark(func lambda)
-{
-  auto start = std::chrono::steady_clock::now();
-  lambda();
-  auto end = std::chrono::steady_clock::now();
-  auto elapsedm = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
-  // time end
-  std::cout << "time: " << elapsedm << " ns" << std::endl;
-}
-
-#define CDO_BENCH(x) cdo_benchmark(x)
-
-#else
-#define CDO_BENCH(x)                                                                            \
-  std::cout << "benchmark found, please remove. " << __FILE__ << ": " << __LINE__ << std::endl; \
-  x()
-#endif
-#endif
diff --git a/src/cdo_def_options.cc b/src/cdo_def_options.cc
new file mode 100644
index 0000000000000000000000000000000000000000..425e22b830f3a6249722acdf737f2d56d6a14f45
--- /dev/null
+++ b/src/cdo_def_options.cc
@@ -0,0 +1,482 @@
+#include <csignal>
+#include "cdo_def_options.h"
+#include "cdo_getopt.h"
+#include "percentiles.h"
+#include "cdo_options.h"
+#include "cdo_default_values.h"
+#include "util_string.h"
+#include "cdo_features.h"
+#include "griddes.h"
+#include "cdo_output.h"
+#include "param_conversion.h"
+#include "cdo_settings.h"
+#include "cdi.h"
+#include "datetime.h"
+#include "table.h"
+#include "mpim_grid/mpim_grid.h"
+#include "grid_pointsearch.h"
+#include "institution.h"
+#include "cdo_zaxis.h"
+
+void
+setup_options()
+{
+  CLIOptions::option("envvars")
+      ->add_effect([&]() { CLIOptions::print_envvars = true; })
+      ->aborts_program(true)
+      ->set_category("Info")
+      ->add_help("Prints the environment variables of CDO.");
+
+  CLIOptions::option("settings")
+      ->add_effect([&]() { CLIOptions::print_settings = true; })
+      ->aborts_program(true)
+      ->set_category("Info")
+      ->add_help("Prints the settings of CDO.");
+
+  CLIOptions::option("debug", "d")
+      ->add_effect([&]() {
+        unsigned cdoDebugLevel = 0;
+        unsigned cdiDebugLevel = 0;
+        cdo::parse_debug_arguments({ "1" }, cdoDebugLevel, cdiDebugLevel);
+
+        cdiDebug(cdiDebugLevel);
+        cdo::set_debug(cdoDebugLevel);
+        cdo::features::version();
+      })
+      ->set_category("Output")
+      ->add_help("Pring all available debug messages");
+
+  CLIOptions::option("scoped_debug", "D")
+      ->describe_argument("comma seperated scopes")
+      ->set_category("Output")
+      ->on_empty_argument([]() {
+        std::cerr << "No debug level given please choose: " << std::endl;
+        print_debug_options();
+        exit(EXIT_SUCCESS);
+      })
+      ->add_effect([&](const std::string &argument) {
+        auto [success, tokens] = tokenize_comma_seperated_int_list(argument);
+        if (tokens.empty())
+          {
+            print_debug_options();
+            exit(EXIT_SUCCESS);
+          }
+
+        unsigned cdoDebugLevel = 0;
+        unsigned cdiDebugLevel = 0;
+        cdo::parse_debug_arguments(tokens, cdoDebugLevel, cdiDebugLevel);
+
+        cdiDebug(cdiDebugLevel);
+        cdo::set_debug(cdoDebugLevel);
+
+        cdo::features::version();
+      })
+      ->add_help("Multiple scopes simultaneously possible. Use this option without arguments to get a list of possible scopes");
+
+  CLIOptions::option("worker")
+      ->describe_argument("num")
+      ->add_effect([&](const std::string &argument) { Options::numStreamWorker = parameter_to_int(argument); })
+      ->set_category("Multi Threading")
+      ->add_help("Number of worker to decode/decompress GRIB records.");
+
+  CLIOptions::option("precision")
+      ->describe_argument("float_digits[,double_digits]")
+      ->add_effect([&](const std::string &argument) { cdo::set_digits(argument); })
+      ->set_category("Numeric")
+      ->add_help("Precision to use in displaying floating-point data (default: 7,15).");
+
+  CLIOptions::option("percentile")
+      ->describe_argument("method")
+      ->set_category("Numeric")
+      ->add_effect([&](const std::string &argument) { percentile_set_method(argument); })
+      ->add_help("Methods: nrank, nist, rtype8, <NumPy method (linear|lower|higher|nearest|...)>");
+
+  CLIOptions::option("netcdf_hdr_pad")
+      ->describe_argument("nbr")
+      ->add_effect([&](const std::string &argument) {
+        int netcdf_hdr_pad = parameter_to_bytes(argument);
+        if (netcdf_hdr_pad >= 0) cdo::netcdf_hdr_pad = netcdf_hdr_pad;
+      })
+      ->add_help("Pad NetCDF output header with nbr bytes.");
+
+  CLIOptions::option("use_fftw")
+      ->describe_argument("true|false")
+      ->add_effect([&](const std::string &argument) { Options::Use_FFTW = (int) parameter_to_bool(argument); })
+      ->add_help("Sets fftw usage.");
+
+  CLIOptions::option("config")
+      ->describe_argument("all|all-json|<specific_feature_name>")
+      ->add_effect([&](const std::string &argument) { cdo::features::print_config(argument); })
+      ->on_empty_argument([&]() { cdo::features::print_argument_options(); })
+      ->aborts_program(true)
+      ->set_category("Info")
+      ->add_help("Prints all features and the enabled status.", "Use option <all> to see explicit feature names.");
+
+  CLIOptions::option("pointsearchmethod")
+      ->set_internal(true)
+      ->describe_argument("<kdtree|nanoflann|spherepart|full>")
+      ->set_category("Search Methods")
+      ->add_effect([&](const std::string &argument) { set_pointsearch_method(argument); })
+      ->add_help("Sets the point search method.");
+
+  CLIOptions::option("gridsearchradius")
+      ->describe_argument("degrees[0..180]")
+      ->set_category("Search Methods")
+      ->add_effect([&](const std::string &argument) {
+        auto fval = radius_str_to_deg(argument);
+        if (fval < 0 || fval > 180) cdo_abort("%s=%g out of bounds (0-180 deg)!", "gridsearchradius", fval);
+        cdo_set_search_radius(fval);
+      })
+      ->add_help("Sets the grid search radius (0-180 deg).");
+
+  CLIOptions::option("remap_weights")
+      ->describe_argument("0|1")
+      ->add_effect([&](const std::string &argument) {
+        auto intarg = parameter_to_int(argument);
+        if (intarg != 0 && intarg != 1) cdo_abort("Unsupported value for option --remap_weights %d [0/1]", intarg);
+        Options::REMAP_genweights = intarg;
+      })
+      ->add_help("Generate remap weights (default: 1).");
+
+  CLIOptions::option("no_remap_weights")
+      ->add_effect([&]() { Options::REMAP_genweights = 0; })
+      ->add_help("Switch off generation of remap weights.");
+
+  CLIOptions::option("enableexcept")
+      ->describe_argument("except")
+      ->set_category("Numeric")
+      ->add_effect([&](const std::string &argument) {
+        auto except = cdo::evaluate_except_options(argument);
+        if (except < 0) cdo_abort("option --%s: unsupported argument: %s", "enableexcept", argument);
+        cdo::set_feenableexcept(except);
+        if (signal(SIGFPE, cdo::signal_handler) == SIG_ERR) cdo_warning("can't catch SIGFPE!");
+      })
+      ->add_help("Set individual floating-point traps ", "(DIVBYZERO, INEXACT, INVALID, OVERFLOW, UNDERFLOW, ALL_EXCEPT)");
+
+  CLIOptions::option("timestat_date")
+      ->describe_argument("srcdate")
+      ->add_effect([&](const std::string &argument) { set_timestat_date(argument); })
+      ->add_help("Target timestamp (temporal statistics): ", "first, middle, midhigh or last source timestep.");
+
+  CLIOptions::option("ignore_time_bounds")
+      ->add_effect([&]() {
+        extern bool CDO_Ignore_Time_Bounds;
+        CDO_Ignore_Time_Bounds = true;
+      })
+      ->add_help("Ignores time bounds for time range statistics.");
+
+  CLIOptions::option("use_time_bounds")
+      ->add_effect([&]() {
+        extern bool CDO_Use_Time_Bounds;
+        CDO_Use_Time_Bounds = true;
+      })
+      ->add_help("Enables use of timebounds.");
+
+  CLIOptions::option("cmor")->add_effect([&]() { Options::CMOR_Mode = 1; })->add_help("CMOR conform NetCDF output.");
+
+  CLIOptions::option("reduce_dim")->add_effect([&]() { Options::CDO_Reduce_Dim = 1; })->add_help("Reduce NetCDF dimensions.");
+
+  CLIOptions::option("float")
+      ->add_effect([&]() { Options::CDO_Memtype = MemType::Float; })
+      ->set_category("Numeric")
+      ->add_help("Using single precision floats for data in memory.");
+
+  CLIOptions::option("single")
+      ->add_effect([&]() { Options::CDO_Memtype = MemType::Float; })
+      ->set_category("Numeric")
+      ->add_help("Using single precision floats for data in memory.");
+
+  CLIOptions::option("double")
+      ->add_effect([&]() { Options::CDO_Memtype = MemType::Double; })
+      ->set_category("Numeric")
+      ->add_help("Using double precision floats for data in memory.");
+
+  CLIOptions::option("rusage")
+      ->add_effect([&]() { Options::CDO_Rusage = 1; })
+      ->add_help("Print information about resource utilization.")
+      ->set_category("Info");
+
+  CLIOptions::option("pedantic")->add_effect([&]() { MpMO::enable_pedantic(true); })->add_help("Warnings count as errors.");
+
+  CLIOptions::option("eccodes")
+      ->add_effect([&]() { cdiDefGlobal("ECCODES_GRIB1", true); })
+      ->set_category("Format Specific")
+      ->add_help("Use ecCodes to decode/encode GRIB1 messages.");
+
+  CLIOptions::option("format", "f")
+      ->describe_argument("grb1|grb2|nc1|nc2|nc4|nc4c|nc5|nczarr|srv|ext|ieg")
+      ->add_effect([&](const std::string &argument) { cdo::set_default_filetype(argument); })
+      ->add_help("Format of the output file.");
+
+
+  CLIOptions::option("history")
+      ->add_effect([&]() { Options::CDO_Append_History = true; })
+      ->set_category("History")
+      ->add_help("Do append to NetCDF \"history\" global attribute.");
+
+  CLIOptions::option("no_history")
+      ->add_effect([&]() { Options::CDO_Append_History = false; })
+      ->set_category("History")
+      ->add_help("Do not append to NetCDF \"history\" global attribute.");
+
+  CLIOptions::option("version", "V")
+      ->add_effect([&]() { cdo::features::version(); })
+      ->aborts_program(true)
+      ->set_category("Info")
+      ->add_help("Print the version number.");
+
+  CLIOptions::option("absolute_taxis", "a")
+      ->add_effect([&]() {
+        if (CdoDefault::TaxisType == TAXIS_RELATIVE)
+          cdo_abort("option --%s: can't be combined with option --%s", "absolute_taxis (-a)", "relative_taxis (-r)");
+        CdoDefault::TaxisType = TAXIS_ABSOLUTE;
+      })
+      ->add_help("Generate an absolute time axis.");
+
+  CLIOptions::option("force")->add_effect([&]() { Options::force = true; })->add_help("Forcing a CDO process.");
+
+  CLIOptions::option("fast")
+      ->set_internal(true)
+      ->add_effect([&]() {
+        Options::fast = true;
+        cdiDefGlobal("NETCDF_LAZY_GRID_LOAD", true);
+      })
+      ->add_help("If available, use a faster method even if it requires more memory.");
+
+  // clang-format off
+  CLIOptions::option("default_datatype", "b")
+      ->describe_argument("nbits")
+      ->set_category("Numeric")
+      ->add_effect([&](const std::string &argument) { cdo::set_default_datatype(argument); })
+      ->add_help("Set the number of bits for the output precision",
+                 "    I8|I16|I32|F32|F64     for nc1,nc2,nc4,nc4c,nc5,nczarr;",
+                 "    U8|U16|U32             for nc4,nc4c,nc5;",
+                 "    F32|F64                for grb2,srv,ext,ieg;",
+                 "    P1 - P24               for grb1,grb2");
+  // clang-format on
+
+  CLIOptions::option("check_data_range", "c")
+      ->add_effect([&]() { Options::CheckDatarange = true; })
+      ->add_help("Enables checks for data overflow.");
+
+  CLIOptions::option("grid", "g")
+      ->describe_argument("grid")
+      ->add_effect([&](const std::string &argument) { cdo_set_grids(argument); })
+      ->add_help("Set default grid name or file. Available grids: ",
+                 "F<XXX>, t<RES>, tl<RES>, r<NX>x<NY>, global_<DXY>, zonal_<DY>, gme<NI>, lon=<LON>/lat=<LAT>, hpz<ZOOM>");
+
+  CLIOptions::option("institution", "i")
+      ->describe_argument("institute_name")
+      ->add_effect([&](const std::string &argument) { define_institution(argument); })
+      ->add_help("Sets institution name.");
+
+  CLIOptions::option("chunktype", "k")
+      ->describe_argument("auto|grid|lines")
+
+      ->set_category("Format Specific")
+      ->add_effect([&](const std::string &argument) { cdo::set_chunktype(argument); })
+      ->add_help("NetCDF4 chunk type: auto, grid or lines.");
+
+  CLIOptions::option("chunksize")
+      ->describe_argument("size")
+      ->set_category("Format Specific")
+      ->add_effect([&](const std::string &argument) {
+        int chunkSize = parameter_to_bytes(argument);
+        if (chunkSize >= 0) Options::cdoChunkSize = chunkSize;
+      })
+      ->add_help("NetCDF4 chunk size.");
+
+  CLIOptions::option("lock_io", "L")->add_effect([&]() { Threading::cdoLockIO = true; })->add_help("Lock IO (sequential access).");
+
+  CLIOptions::option("zaxis", "l")
+      ->describe_argument("zaxis")
+      ->add_effect([&](const std::string &argument) { cdo_set_zaxes(argument); })
+      ->add_help("Set default zaxis name or file.");
+
+  CLIOptions::option("set_missval", "m")
+      ->describe_argument("missval")
+      ->add_effect([&](const std::string &argument) { cdiDefMissval(std::stof(argument)); })
+      ->add_help("Set the missing value of non NetCDF files (default: " + get_scientific(cdiInqMissval()) + ").");
+
+  CLIOptions::option("has_missval", "M")
+      ->add_effect([&]() { cdiDefGlobal("HAVE_MISSVAL", true); })
+      ->add_help("Set HAS_MISSVAL to true.");
+
+  CLIOptions::option("varnames", "n")
+      ->set_internal(true)
+      ->describe_argument("<varname| file>")
+      ->add_effect([&](const std::string &argument) { Options::cdoVarnames = split_string(argument, ","); })
+      ->add_help("Set default varnames or file.");
+
+
+  CLIOptions::option("num_threads", "P")
+      ->describe_argument("nthreads")
+      ->add_effect([&](const std::string &argument) { Threading::ompNumUserRequestedThreads = parameter_to_int(argument); })
+      ->set_category("Multi Threading")
+      ->add_help("Set number of OpenMP threads.");
+
+  CLIOptions::option("parrallel_read", "p")
+      ->set_internal(true)
+      ->add_effect([&]() {
+        Options::CDO_Parallel_Read = true;
+        Options::CDO_task = true;
+      })
+      ->set_category("Multi Threading")
+      ->add_help("Enables parallel read.");
+
+  CLIOptions::option("sortname", "Q")
+      ->add_effect([&]() { cdiDefGlobal("SORTNAME", true); })
+      ->set_category("Format Specific")
+      ->add_help("Alphanumeric sorting of NetCDF parameter names.");
+
+  CLIOptions::option("seed")
+      ->describe_argument("seed")
+      ->set_category("Numeric")
+      ->add_effect([&](const std::string &argument) {
+        int intarg = parameter_to_int(argument);
+        if (intarg < 0) cdo_abort("Unsupported value for option --seed %d [>=0]", intarg);
+        Options::Random_Seed = intarg;
+      })
+      ->add_help("Seed for a new sequence of pseudo-random numbers. <seed> must be >= 0");
+
+  CLIOptions::option("regular", "R")
+      ->add_effect([&]() {
+        Options::cdoRegulargrid = true;
+        cdiDefGlobal("REGULARGRID", true);
+      })
+      ->set_category("CGRIBEX")
+      ->add_help("Convert GRIB1 data from global reduced to regular Gaussian grid (cgribex only).");
+
+  CLIOptions::option("relative_taxis", "r")
+      ->add_effect([&]() {
+        if (CdoDefault::TaxisType == TAXIS_ABSOLUTE)
+          cdo_abort("option --%s: can't be combined with option --%s", "relative_taxis (-r)", "absolute_taxis (-a)");
+        CdoDefault::TaxisType = TAXIS_RELATIVE;
+      })
+      ->add_help("Generate a relative time axis.");
+
+  CLIOptions::option("cdo_diagnostic", "S")
+      ->add_effect([&]() { Options::cdoDiag = true; })
+      ->add_help("Create an extra output stream for the module TIMSTAT. This stream",
+                 "contains the number of non missing values for each output period.");
+
+  CLIOptions::option("silent", "s")
+      ->add_effect([&]() {
+        Options::silentMode = true;
+        MpMO::enable_silent_mode(Options::silentMode);
+      })
+      ->set_category("Output")
+      ->add_help("Silent mode.");
+
+  CLIOptions::option("timer", "T")->add_effect([&]() { Options::Timer = true; })->add_help("Enable timer.");
+
+  CLIOptions::option("table", "t")
+      ->describe_argument("codetab")
+      ->set_category("CGRIBEX")
+      ->add_effect([&](const std::string &argument) { CdoDefault::TableID = cdo::define_table(argument); })
+      ->add_help("Set GRIB1 default parameter code table name or file (cgribex only).", cdo::predefined_tables(CLIOptions::padding));
+
+
+  CLIOptions::option("sortparam")->add_effect([]() { cdiDefGlobal("SORTPARAM", true); });
+
+  CLIOptions::option("verbose", "v")
+      ->add_effect([&]() {
+        Options::cdoVerbose = true;
+        MpMO::enable_verbose(true);
+        CLIOptions::print_envvars = true;
+        gridEnableVerbose(Options::cdoVerbose);
+      })
+      ->add_help("Print extra details for some operators.");
+
+  CLIOptions::option("disable_warnings", "w")
+      ->add_effect([&]() {  // disable warning messages
+        MpMO::enable_warnings(false);
+        extern int _Verbose;  // CDI Warnings
+        _Verbose = 0;
+      })
+      ->set_category("Output")
+      ->add_help("Disable warning messages.");
+
+  CLIOptions::option("par_io", "X")
+      ->set_internal(true)
+      ->add_effect([&]() {
+        Options::cdoParIO = true;  // multi threaded I/O
+      })
+      ->add_help("Enables multithreaded I/O.")
+      ->set_category("Multi Threading");
+
+  CLIOptions::option("shuffle")
+      ->add_effect([&]() { Options::cdoShuffle = true; })
+      ->set_category("Compression")
+      ->add_help("Specify shuffling of variable data bytes before compression (NetCDF)");
+
+  CLIOptions::option("compress", "Z")
+      ->add_effect([&]() { Options::cdoCompress = true; })
+      ->set_category("Compression")
+      ->add_help("Enables compression. Default = SZIP");
+
+  CLIOptions::option("filter", "F")
+      ->describe_argument("filterspec")
+      ->add_effect([&](const std::string &argument) { cdo::set_filterspec(argument); })
+      ->set_category("Compression")
+      ->add_help("NetCDF4 filter specification");
+
+  CLIOptions::option("compression_type", "z")
+      ->describe_argument("aec|jpeg|zip[_1-9]|zstd[1-19]")
+      ->set_category("Compression")
+      ->add_effect([&](const std::string &argument) { cdo::set_compression_type(argument); })
+      ->add_help("aec         AEC compression of GRIB2 records", "jpeg        JPEG compression of GRIB2 records",
+                 "zip[_1-9]   Deflate compression of NetCDF4 variables", "zstd[_1-19] Zstandard compression of NetCDF4 variables");
+
+  CLIOptions::option("nsb")
+      ->set_internal(true)
+      ->describe_argument("1-23")
+      ->add_effect([&](const std::string &argument) { Options::nsb = parameter_to_int(argument); })
+      ->set_category("Numeric")
+      ->add_help("Number of significant bits used for bit-rounding.");
+
+  CLIOptions::option("show_available_options")
+      ->set_internal(true)
+      ->aborts_program(true)
+      ->set_category("Info")
+      ->add_effect([&]() { CLIOptions::print_available_options(); })
+      ->add_help("Shows all available optins and prints all shortforms, only internal use for testing.");
+
+
+
+#ifdef HIRLAM_EXTENSIONS
+  CLIOptions::option("Dkext")
+      ->describe_argument("debLev")
+      ->set_category("Hirlam Extension")
+      ->add_effect([&](const std::string &argument) {
+        auto extDebugVal = parameter_to_int(argument);
+        if (extDebugVal > 0)
+          {
+            extern int cdiDebugExt;
+            cdoDebugExt = extDebugVal;
+            cdiDebugExt = extDebugVal;
+          }
+      })
+      ->add_help("Setting debugLevel for extensions.");
+
+  CLIOptions::option("outputGribDataScanningMode")
+      ->describe_argument("mode")
+      ->set_category("Hirlam Extension")
+      ->add_effect([&](const std::string &argument) {
+        auto scanningModeValue = parameter_to_int(argument);
+        if (cdoDebugExt) printf("scanningModeValue=%d\n", scanningModeValue);
+
+        if ((scanningModeValue == 0) || (scanningModeValue == 64) || (scanningModeValue == 96))
+          {
+            streamGrbDefDataScanningMode(scanningModeValue);  // -1: not used; allowed modes: <0,
+                                                              // 64, 96>; Default is 64
+          }
+        else
+          {
+            cdo_warning("Warning: %d not in allowed modes: <0, 64, 96>; Using default: 64\n", scanningModeValue);
+            streamGrbDefDataScanningMode(64);
+          }
+      })
+      ->add_help("Setting grib scanning mode for data in output file <0, 64, 96>.", "Default is 64");
+#endif  // HIRLAM_EXTENSIONS
+}
diff --git a/src/cdo_def_options.h b/src/cdo_def_options.h
new file mode 100644
index 0000000000000000000000000000000000000000..27d3b2b7dfb2d2f3f67bab95d01a0fd88e65ce32
--- /dev/null
+++ b/src/cdo_def_options.h
@@ -0,0 +1,6 @@
+#ifndef CDO_DEF_OPTIONS_H
+#define CDO_DEF_OPTIONS_H
+
+void setup_options();
+
+#endif
diff --git a/src/cdo_fctrans.cc b/src/cdo_fctrans.cc
index 2b552c34d4f5d434fd1e3c228f20bd7fb0fe952c..b6cb55a84b95b5106e761cad7dee7a9819a51d58 100644
--- a/src/cdo_fctrans.cc
+++ b/src/cdo_fctrans.cc
@@ -29,9 +29,9 @@ fc2gp(const double *fc, double *gp, long nlat, long nlon, long nlev, long nfc)
     fftw_plan plan;
   };
 
-  std::vector<FourierMemory> ompmem(Threading::ompNumThreads);
+  std::vector<FourierMemory> ompmem(Threading::ompNumMaxThreads);
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       ompmem[i].in_fft = fftw_alloc_complex(nlon / 2 + 1);
       ompmem[i].out_fft = (double *) fftw_malloc(nlon * sizeof(double));
@@ -72,7 +72,7 @@ fc2gp(const double *fc, double *gp, long nlat, long nlon, long nlev, long nfc)
         }
     }
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       fftw_free(ompmem[i].in_fft);
       fftw_free(ompmem[i].out_fft);
@@ -96,9 +96,9 @@ gp2fc(const double *gp, double *fc, long nlat, long nlon, long nlev, long nfc)
     fftw_plan plan;
   };
 
-  std::vector<FourierMemory> ompmem(Threading::ompNumThreads);
+  std::vector<FourierMemory> ompmem(Threading::ompNumMaxThreads);
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       ompmem[i].in_fft = (double *) fftw_malloc(nlon * sizeof(double));
       ompmem[i].out_fft = fftw_alloc_complex(nlon / 2 + 1);
@@ -134,7 +134,7 @@ gp2fc(const double *gp, double *fc, long nlat, long nlon, long nlev, long nfc)
         }
     }
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       fftw_free(ompmem[i].in_fft);
       fftw_free(ompmem[i].out_fft);
diff --git a/src/cdo_fftw3.cc b/src/cdo_fftw3.cc
index bd7af926dc1ee7d9bf3f944f7ba0fd24a694fa30..9bdec59a85f4b42535c161f712e4963f68d684fd 100644
--- a/src/cdo_fftw3.cc
+++ b/src/cdo_fftw3.cc
@@ -23,9 +23,9 @@ fourier2grid(int gridID1, const Varray<double> &array1, Varray<double> &array2)
     fftw_plan plan;
   };
 
-  std::vector<FourierMemory> ompmem(Threading::ompNumThreads);
+  std::vector<FourierMemory> ompmem(Threading::ompNumMaxThreads);
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       ompmem[i].in_fft = fftw_alloc_complex(nlon);
       ompmem[i].out_fft = (double *) fftw_malloc(nlon * sizeof(double));
@@ -55,7 +55,7 @@ fourier2grid(int gridID1, const Varray<double> &array1, Varray<double> &array2)
       for (size_t ilon = 0; ilon < nlon; ++ilon) array2[ilat * nlon + ilon] = out_fft[ilon];
     }
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       fftw_free(ompmem[i].in_fft);
       fftw_free(ompmem[i].out_fft);
@@ -79,9 +79,9 @@ grid2fourier(int gridID1, const Varray<double> &array1, int gridID2, Varray<doub
     fftw_plan plan;
   };
 
-  std::vector<FourierMemory> ompmem(Threading::ompNumThreads);
+  std::vector<FourierMemory> ompmem(Threading::ompNumMaxThreads);
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       ompmem[i].in_fft = (double *) fftw_malloc(nlon * sizeof(double));
       ompmem[i].out_fft = fftw_alloc_complex(nlon);
@@ -111,7 +111,7 @@ grid2fourier(int gridID1, const Varray<double> &array1, int gridID2, Varray<doub
         }
     }
 
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       fftw_free(ompmem[i].in_fft);
       fftw_free(ompmem[i].out_fft);
diff --git a/src/cdo_options.cc b/src/cdo_options.cc
index 3f93a6053d8d9e2a5aa5f1bc27d2802ddde4fd07..94fecf5da98d94fa0a569a564852982fb2da01ae 100644
--- a/src/cdo_options.cc
+++ b/src/cdo_options.cc
@@ -52,6 +52,7 @@ int cdoCompType = CDI_COMPRESS_NONE;
 int cdoCompLevel = 0;
 bool cdoInteractive = false;
 bool cdoVerbose = false;
+int CDO_Rusage = 0;
 int cdoExitStatus = 0;
 bool Timer = false;
 
@@ -96,7 +97,8 @@ const char *cdoExpName = nullptr;
 
 namespace Threading
 {
-int ompNumThreads = 1;
+int ompNumMaxThreads = 1;
+int ompNumUserRequestedThreads = 0;
 bool cdoLockIO = false;
 }  // namespace Threading
 
diff --git a/src/cdo_options.h b/src/cdo_options.h
index 06588a43ea31854ed35835a0f57fde247469e89f..008d65e8aeafbfe155ab5a787c65f393f50f07f1 100644
--- a/src/cdo_options.h
+++ b/src/cdo_options.h
@@ -48,6 +48,7 @@ extern int cdoCompType;
 extern int cdoCompLevel;
 extern bool cdoInteractive;
 extern bool cdoVerbose;
+extern int CDO_Rusage;
 extern bool cdoProcessInfo;
 extern int cdoExitStatus;
 extern bool Timer;
@@ -88,7 +89,8 @@ extern bool REMAP_genweights;
 
 namespace Threading
 {
-extern int ompNumThreads;
+extern int ompNumMaxThreads;
+extern int ompNumUserRequestedThreads;
 extern bool cdoLockIO;
 }  // namespace Threading
 
diff --git a/src/cdo_settings.cc b/src/cdo_settings.cc
index 98c00d1b9671f5fdacbb2ec37b0115b2876b38ec..4989ab7b7174e3341bfc5a0d3711f9562502de77 100644
--- a/src/cdo_settings.cc
+++ b/src/cdo_settings.cc
@@ -384,13 +384,13 @@ setup_openMP(int numThreads)
   if (numThreads <= 0) numThreads = 1;
   omp_set_num_threads(numThreads);
 
-  Threading::ompNumThreads = omp_get_max_threads();
+  Threading::ompNumMaxThreads = omp_get_max_threads();
   if (omp_get_max_threads() > omp_get_num_procs())
     fprintf(stderr, "Warning: Number of OMP threads=%d is greater than number of Cores=%d!\n", omp_get_max_threads(),
             omp_get_num_procs());
 
-  if (Threading::ompNumThreads < numThreads)
-    fprintf(stderr, "Warning: omp_get_max_threads() returns %d!\n", Threading::ompNumThreads);
+  if (Threading::ompNumMaxThreads < numThreads)
+    fprintf(stderr, "Warning: omp_get_max_threads() returns %d!\n", Threading::ompNumMaxThreads);
 
   if (cdo::dbg()) cdo::features::print_openmp_info();
 
diff --git a/src/cdo_settings.h b/src/cdo_settings.h
index 0d28b82b470d6efe024b0156de6425c5cffb94e4..f89e8d147fc89fa52234c205e3399d0a79086180 100644
--- a/src/cdo_settings.h
+++ b/src/cdo_settings.h
@@ -25,7 +25,7 @@ void set_chunktype(const std::string &arg);
 
 void evaluate_color_options(const std::string &arg);
 
-void setup_openMP(int CDO_numThreads);
+void setup_openMP(int ompNumUserRequestedThreads);
 
 };  // namespace cdo
 
diff --git a/src/cdo_task.cc b/src/cdo_task.cc
index 9a8d640ea1f2ef3e4b4b2f2d6af7801a0f4d7656..d41a59200c5a6cdbd53a1e84ea6d2300e4049541 100644
--- a/src/cdo_task.cc
+++ b/src/cdo_task.cc
@@ -19,7 +19,7 @@ void
 Task::task(cdo::Task *taskInfo)
 {
 #if defined(_OPENMP)
-  omp_set_num_threads(Threading::ompNumThreads);  // Has to be called for every thread!
+  omp_set_num_threads(Threading::ompNumMaxThreads);  // Has to be called for every thread!
 #endif
 
   // cond.wait mutex must be locked before we can wait
diff --git a/src/cellsearch_spherepart.h b/src/cellsearch_spherepart.h
index b7855c6f221d0f4530cb575bdb26696a5c0e111e..b5669b995339aafba9d6a868c74373d25ccfd743 100644
--- a/src/cellsearch_spherepart.h
+++ b/src/cellsearch_spherepart.h
@@ -77,8 +77,8 @@ private:
   create(size_t numCells, size_t numCorners, const Varray<double> &cornerLons, const Varray<double> &cornerLats)
   {
     Varray<enum yac_edge_type> edgeTypes(numCorners, YAC_GREAT_CIRCLE_EDGE);
-    Varray<yac_grid_cell> cells(Threading::ompNumThreads);
-    for (int i = 0; i < Threading::ompNumThreads; ++i)
+    Varray<yac_grid_cell> cells(Threading::ompNumMaxThreads);
+    for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
       {
         cells[i].coordinates_xyz = new double[numCorners][3];
         cells[i].edge_type = edgeTypes.data();
@@ -114,7 +114,7 @@ private:
 
     m_yacCellSearch = yac_bnd_sphere_part_search_new(m_bndCircles, numCells);
 
-    for (int i = 0; i < Threading::ompNumThreads; ++i) delete[] cells[i].coordinates_xyz;
+    for (int i = 0; i < Threading::ompNumMaxThreads; ++i) delete[] cells[i].coordinates_xyz;
   }
 };
 
diff --git a/src/datetime.cc b/src/datetime.cc
index e82cf5caef97af88a533485fe8f72d0d97dfed61..e260cc71976b21df6a4ebaf365c56281c2edac28 100644
--- a/src/datetime.cc
+++ b/src/datetime.cc
@@ -37,18 +37,18 @@ time_units_cstr(TimeUnits timeUnit)
 }
 
 void
-set_timestat_date(const std::string &optarg)
+set_timestat_date(const std::string &p_optarg)
 {
   TimeStat timestatdate = TimeStat::UNDEF;
 
   // clang-format off
-  if      (optarg == "first")   timestatdate = TimeStat::FIRST;
-  else if (optarg == "last")    timestatdate = TimeStat::LAST;
-  else if (optarg == "middle")  timestatdate = TimeStat::MEAN;
-  else if (optarg == "midhigh") timestatdate = TimeStat::MIDHIGH;
+  if      (p_optarg == "first")   timestatdate = TimeStat::FIRST;
+  else if (p_optarg == "last")    timestatdate = TimeStat::LAST;
+  else if (p_optarg == "middle")  timestatdate = TimeStat::MEAN;
+  else if (p_optarg == "midhigh") timestatdate = TimeStat::MIDHIGH;
   // clang-format on
 
-  if (timestatdate == TimeStat::UNDEF) cdo_abort("option --%s: unsupported argument: %s", "timestat_date", optarg);
+  if (timestatdate == TimeStat::UNDEF) cdo_abort("option --%s: unsupported argument: %s", "timestat_date", p_optarg);
 
   CDO_Timestat_Date = timestatdate;
 }
diff --git a/src/datetime.h b/src/datetime.h
index ec510c7de685c88b182fe909582224e23221292b..61cda014e2849c710e4c6c54a3b7e86417fa2387 100644
--- a/src/datetime.h
+++ b/src/datetime.h
@@ -111,7 +111,7 @@ private:
 };
 
 CdiDateTime datetime_avg(int calendar, int ndates, const std::vector<CdiDateTime> &cdiDateTimes);
-void set_timestat_date(const std::string &optarg);
+void set_timestat_date(const std::string &p_optarg);
 
 void adjust_month_and_year(int &month, int &year);
 
diff --git a/src/fileStream.cc b/src/fileStream.cc
index f1e1a491abd355e290ca0633292e4ed3a7dc4a4a..a55664a3e2f0a8d0bf8797626897c01e5e326aba 100644
--- a/src/fileStream.cc
+++ b/src/fileStream.cc
@@ -209,8 +209,8 @@ FileStream::def_vlist(int p_vlistID)
   if (Options::VersionInfo) cdiDefAttTxt(p_vlistID, CDI_GLOBAL, "CDO", (int) strlen(cdo_comment()), cdo_comment());
 
 #ifdef _OPENMP
-  if (Threading::ompNumThreads > 1)
-    cdiDefAttInt(p_vlistID, CDI_GLOBAL, "cdo_openmp_thread_number", CDI_DATATYPE_INT32, 1, &Threading::ompNumThreads);
+  if (Threading::ompNumMaxThreads > 1)
+    cdiDefAttInt(p_vlistID, CDI_GLOBAL, "cdo_openmp_thread_number", CDI_DATATYPE_INT32, 1, &Threading::ompNumMaxThreads);
 #endif
   defDatarangeList(p_vlistID);
 
diff --git a/src/grid_pointsearch.h b/src/grid_pointsearch.h
index 43c511943c8de900ffa9c7183c35911745981515..f56b15b14c9240facc8417b89ece63ec076af490 100644
--- a/src/grid_pointsearch.h
+++ b/src/grid_pointsearch.h
@@ -55,6 +55,9 @@ public:
   PointsearchUnstruct unstruct;
 };
 
+
+void set_pointsearch_method(const std::string &methodStr);
+
 void grid_search_point_unstruct(GridPointsearch &gps, const PointLonLat &pointLL, KnnData &knnData);
 void grid_search_point_smooth(GridPointsearch &gps, const PointLonLat &pointLL, KnnData &knnData);
 
diff --git a/src/hetaeta.cc b/src/hetaeta.cc
index 08f955821771a3837b4f8e7a9a3945be240ad0af..8386998079f93f63178dfd737cb70024190644b4 100644
--- a/src/hetaeta.cc
+++ b/src/hetaeta.cc
@@ -423,7 +423,7 @@ hetaeta(bool ltq, int ngp, const Vmask &imiss, int nlev1, const double *ah1, con
   long nlev1p1 = nlev1 + 1;
   long nlev2p1 = nlev2 + 1;
 
-  auto nthreads = Threading::ompNumThreads;
+  auto nthreads = Threading::ompNumMaxThreads;
   Varray2D<double> ph1(nthreads, Varray<double>(nlev1p1));
   Varray2D<double> lnph1(nthreads, Varray<double>(nlev1p1));
   Varray2D<double> fi1(nthreads, Varray<double>(nlev1p1));
@@ -576,7 +576,7 @@ template void hetaeta(bool ltq, int ngp, const Vmask &imiss, int nlev1, const do
 #ifdef TEST_HETAETA
 
 // g++ -DTEST_HETAETA -I../libcdi/src -std=c++20 -g -Wall -fopenmp hetaeta.cc
-int Threading::ompNumThreads = 2;
+int Threading::ompNumMaxThreads = 2;
 
 int
 cdo_omp_get_thread_num()
@@ -594,7 +594,7 @@ main(int argc, char *argv[])
   constexpr int NGP = 512;
 
 #ifdef _OPENMP
-  omp_set_num_threads(Threading::ompNumThreads);
+  omp_set_num_threads(Threading::ompNumMaxThreads);
 #endif
 
   printf("NGP = %d\n", NGP);
diff --git a/src/memoryStream.cc b/src/memoryStream.cc
index 4d19acf48b420ec10504c8a5458bdbc0e9d89602..a37725ffce52da0592a69feb692dd89560b5fb35 100644
--- a/src/memoryStream.cc
+++ b/src/memoryStream.cc
@@ -68,7 +68,7 @@ MemoryStream::open_write(int p_filetype)
   set_compression(m_fileID, CDI_FILETYPE_NC4);
 
   m_filetype = CDI_FILETYPE_NC4;
-  Debug(FILE_STREAM, "finished open_write");
+  Debug(FILE_STREAM, "finished open_write with filetype set to: %d", inqFileType());
 
   return m_fileID;
 }
diff --git a/src/namelistdump.cc b/src/namelistdump.cc
deleted file mode 100644
index 1ca4f6474030479f2156126785850da14bbdaa17..0000000000000000000000000000000000000000
--- a/src/namelistdump.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-  This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
-
-  Author: Uwe Schulzweida
-
-*/
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <sys/stat.h>
-
-#include "namelist.h"
-
-int
-main(int argc, char *argv[])
-{
-  if (argc != 2)
-    {
-      fprintf(stderr, "Usage: %s namelist\n", argv[0]);
-      return -1;
-    }
-
-  const char *filename = argv[1];
-  printf("Parse namelist %s:\n", filename);
-
-  struct stat sbuf;
-  size_t filesize = (stat(filename, &sbuf) == 0) ? sbuf.st_size : 0;
-
-  if (filesize == 0)
-    {
-      fprintf(stderr, "Empty table file: %s\n", filename);
-      return -1;
-    }
-
-  FILE *fp = std::fopen(filename, "r");
-  if (fp == nullptr)
-    {
-      fprintf(stderr, "Open failed on %s: %s\n", filename, strerror(errno));
-      return -1;
-    }
-
-  char *buffer = (char *) std::malloc(filesize);
-  size_t nitems = fread(buffer, 1, filesize, fp);
-
-  std::fclose(fp);
-
-  if (nitems != filesize)
-    {
-      fprintf(stderr, "Read failed on %s!\n", filename);
-      std::free(buffer);
-      return -1;
-    }
-
-  NamelistParser p;
-
-  NamelistError status = p.parse(buffer, filesize);
-  printf("Processed number of lines: %lu\n", p.lineno - 1);
-  if (status != NamelistError::UNDEFINED)
-    {
-      switch (status)
-        {
-        case NamelistError::INVAL:
-          fprintf(stderr, "Namelist error: Invalid character in %s (line=%lu character='%c')!\n", filename, p.lineno,
-                  buffer[p.pos]);
-          break;
-        case NamelistError::PART:
-          fprintf(stderr, "Namelist error: End of string not found in %s (line=%lu)!\n", filename, p.lineno);
-          break;
-        case NamelistError::INKEY:
-          fprintf(stderr, "Namelist error: Invalid keyword in %s (line=%lu)!\n", filename, p.lineno);
-          break;
-        case NamelistError::INTYP:
-          fprintf(stderr, "Namelist error: Invalid keyword type in %s (line=%lu)!\n", filename, p.lineno);
-          break;
-        case NamelistError::INOBJ: fprintf(stderr, "Namelist error: Invalid object in %s (line=%lu)!\n", filename, p.lineno); break;
-        case NamelistError::EMKEY: fprintf(stderr, "Namelsit error: Emtry key name in %s (line=%lu)!\n", filename, p.lineno); break;
-        default: fprintf(stderr, "Namelsit error in %s (line=%lu)!\n", filename, p.lineno); break;
-        }
-    }
-
-  p.dump(buffer);
-
-  std::free(buffer);
-
-  return 0;
-}
diff --git a/src/pointsearch_kdtree.h b/src/pointsearch_kdtree.h
index 8c89086543dd887261bbcfdacb46ccc013b87d32..498abbc69a2cd213012bdab19e6fda7c84672b67 100644
--- a/src/pointsearch_kdtree.h
+++ b/src/pointsearch_kdtree.h
@@ -132,7 +132,7 @@ private:
 
     // if (Options::cdoVerbose) cdo_print("BBOX: min=%g/%g/%g  max=%g/%g/%g", min[0], min[1], min[2], max[0], max[1], max[2]);
 
-    m_kdtree = kd_buildTree(pointlist.data(), n, min, max, 3, Threading::ompNumThreads);
+    m_kdtree = kd_buildTree(pointlist.data(), n, min, max, 3, Threading::ompNumMaxThreads);
     // if (m_kdtree == nullptr) cdo_abort("kd_buildTree failed!");
   }
 };
diff --git a/src/process.cc b/src/process.cc
index 383c2745669a78c4202e8c53edb463f8e7a0a0ab..d3555a61f3b910ba95d364ee9292028bc5c9a681 100644
--- a/src/process.cc
+++ b/src/process.cc
@@ -370,7 +370,7 @@ void
 Process::cdo_initialize()
 {
 #ifdef _OPENMP
-  omp_set_num_threads(Threading::ompNumThreads);  // Has to be called for every module (pthread)!
+  omp_set_num_threads(Threading::ompNumMaxThreads);  // Has to be called for every module (pthread)!
 #endif
 #ifdef HAVE_LIBPTHREAD
   threadID = pthread_self();
diff --git a/src/processManager.cc b/src/processManager.cc
index 2d0aa173fd2b965617bbeafe567498ebacc13bec..900e7a50ee3d4668320c7ee98ebac8beeae7394b 100644
--- a/src/processManager.cc
+++ b/src/processManager.cc
@@ -141,8 +141,6 @@ ProcessManager::buildProcessTree(std::vector<std::shared_ptr<Node>> roots)
           Debug(PROCESS, "adding out files to %s", node->oper);
           Debug(PROCESS, "node type = %d", n->type);
           if (n->type == Node::NodeType::OUTFILE) { first_process->add_file_out_stream(n->oper); }
-          else if (n->type == Node::NodeType::OUT_MEM_BUFFER) { first_process->add_mem_out_stream(n->ncid); }
-          else { cdo_abort("Unkown stream type"); }
         }
     }
 
diff --git a/src/remap_conserv.cc b/src/remap_conserv.cc
index 37a6b72bfd66f230809dcad6aa7b074cdf4ee620..fe7fcd1056aceb73a428134756505536fa7ee7f8 100644
--- a/src/remap_conserv.cc
+++ b/src/remap_conserv.cc
@@ -452,11 +452,11 @@ remap_conserv_weights(RemapSearch &remapSearch, RemapVars &rv)
         }
     }
 
-  Varray<GridCell> tgtGridCell2(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i) gridcell_init_yac(tgtGridCell2[i], tgtNumCorners, tgtEdgeType);
+  Varray<GridCell> tgtGridCell2(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) gridcell_init_yac(tgtGridCell2[i], tgtNumCorners, tgtEdgeType);
 
-  Varray<CellSearch> cellSearch2(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  Varray<CellSearch> cellSearch2(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       cellSearch2[i].numCorners = srcNumCorners;
       cellSearch2[i].edgeType = srcEdgeType;
@@ -474,7 +474,7 @@ remap_conserv_weights(RemapSearch &remapSearch, RemapVars &rv)
 
   size_t numSearchCellsStat[3] = { 0, 100000, 0 };
 
-  Varray<Varray<size_t>> indices2(Threading::ompNumThreads);
+  Varray<Varray<size_t>> indices2(Threading::ompNumMaxThreads);
 
   // Loop over target grid cells
 
@@ -560,7 +560,7 @@ remap_conserv_weights(RemapSearch &remapSearch, RemapVars &rv)
     }
 
   // Finished with all cells: deallocate search arrays
-  for (auto ompthID = 0; ompthID < Threading::ompNumThreads; ++ompthID)
+  for (auto ompthID = 0; ompthID < Threading::ompNumMaxThreads; ++ompthID)
     {
       cellSearch2[ompthID].free();
       gridcell_free_yac(tgtGridCell2[ompthID]);
@@ -652,11 +652,11 @@ remap_conserv(const Varray<T1> &srcArray, Varray<T2> &tgtArray, double srcMissva
         }
     }
 
-  Varray<GridCell> tgtGridCell2(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i) gridcell_init_yac(tgtGridCell2[i], tgtNumCorners, tgtEdgeType);
+  Varray<GridCell> tgtGridCell2(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) gridcell_init_yac(tgtGridCell2[i], tgtNumCorners, tgtEdgeType);
 
-  Varray<CellSearch> cellSearch2(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i)
+  Varray<CellSearch> cellSearch2(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i)
     {
       cellSearch2[i].numCorners = srcNumCorners;
       cellSearch2[i].edgeType = srcEdgeType;
@@ -671,7 +671,7 @@ remap_conserv(const Varray<T1> &srcArray, Varray<T2> &tgtArray, double srcMissva
 
   size_t numSearchCellsStat[3] = { 0, 100000, 0 };
 
-  Varray<Varray<size_t>> indices2(Threading::ompNumThreads);
+  Varray<Varray<size_t>> indices2(Threading::ompNumMaxThreads);
 
   // Loop over target grid cells
 
@@ -749,7 +749,7 @@ remap_conserv(const Varray<T1> &srcArray, Varray<T2> &tgtArray, double srcMissva
 
   // Finished with all cells: deallocate search arrays
 
-  for (auto ompthID = 0; ompthID < Threading::ompNumThreads; ++ompthID)
+  for (auto ompthID = 0; ompthID < Threading::ompNumMaxThreads; ++ompthID)
     {
       cellSearch2[ompthID].free();
       gridcell_free_yac(tgtGridCell2[ompthID]);
diff --git a/src/remap_knn.cc b/src/remap_knn.cc
index f2fd4326af69d2eabc77fca3667e1768877d4e4c..00d68d0c1b3d94c043b3a4abee6c44bafd636955 100644
--- a/src/remap_knn.cc
+++ b/src/remap_knn.cc
@@ -36,8 +36,8 @@ remap_knn_weights(const KnnParams &knnParams, RemapSearch &rsearch, RemapVars &r
   weight_links_alloc(knnParams.k, tgtGridSize, weightLinks);
 
   std::vector<KnnData> knnDataList;
-  knnDataList.reserve(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataList.push_back(KnnData(knnParams));
+  knnDataList.reserve(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataList.push_back(KnnData(knnParams));
 
   cdo::timer timer;
 
@@ -116,8 +116,8 @@ remap_knn(const Varray<T1> &srcArray, Varray<T2> &tgtArray, double srcMissval, s
   if (numMissVals) remap_set_mask(srcArray, srcGridSize, numMissVals, srcMissval, srcGridMask);
 
   std::vector<KnnData> knnDataList;
-  knnDataList.reserve(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataList.push_back(KnnData(knnParams));
+  knnDataList.reserve(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataList.push_back(KnnData(knnParams));
 
   cdo::timer timer;
 
@@ -190,8 +190,8 @@ intgrid_knn(KnnParams knnParams, const Field &field1, Field &field2)
   if (field1.numMissVals) remap_set_mask(srcArray, srcGridSize, field1.numMissVals, srcMissval, srcGridMask);
 
   std::vector<KnnData> knnDataList;
-  knnDataList.reserve(Threading::ompNumThreads);
-  for (int i = 0; i < Threading::ompNumThreads; ++i) knnDataList.push_back(KnnData(knnParams));
+  knnDataList.reserve(Threading::ompNumMaxThreads);
+  for (int i = 0; i < Threading::ompNumMaxThreads; ++i) knnDataList.push_back(KnnData(knnParams));
 
   remap_search_init(mapType, remap.search, remap.srcGrid, remap.tgtGrid);
 
diff --git a/src/remap_store_link.cc b/src/remap_store_link.cc
index d69de6f3f55d5140bcec26442118e27a1c8b3c6e..3d02d7a9a6a31f0ff2cb0d1a87ea692c463b1879 100644
--- a/src/remap_store_link.cc
+++ b/src/remap_store_link.cc
@@ -119,7 +119,7 @@ weight_links_to_remap_links(int doAlloc, size_t tgtGridSize, std::vector<WeightL
       auto &tgtCellIndices = rv.tgtCellIndices;
       auto &weights = rv.weights;
 
-      auto useLinksArrays = (Threading::ompNumThreads > 1 && rv.numLinksPerValue == -1 && tgtGridSize > cdoMinLoopSize);
+      auto useLinksArrays = (Threading::ompNumMaxThreads > 1 && rv.numLinksPerValue == -1 && tgtGridSize > cdoMinLoopSize);
       if (useLinksArrays) rv.linksOffset.resize(tgtGridSize);
       if (useLinksArrays) rv.linksPerValue.resize(tgtGridSize);
 
diff --git a/src/remap_vars.cc b/src/remap_vars.cc
index 4acb4b421344d5821582b5f456a9abb33698167f..c155eb06e6c787b1aa503bb0eb73dd1a35b5d49c 100644
--- a/src/remap_vars.cc
+++ b/src/remap_vars.cc
@@ -305,8 +305,8 @@ remap_laf(const Varray<T1> &srcArray, Varray<T2> &tgtArray, double tgtMissval, s
   auto max_cls = get_max_index(numLinks, tgtSize, tgtIndices);
 
 #ifdef _OPENMP
-  Varray2D<T1> src_cls2(Threading::ompNumThreads, Varray<T1>(max_cls));
-  Varray2D<double> src_weights2(Threading::ompNumThreads, Varray<double>(max_cls));
+  Varray2D<T1> src_cls2(Threading::ompNumMaxThreads, Varray<T1>(max_cls));
+  Varray2D<double> src_weights2(Threading::ompNumMaxThreads, Varray<double>(max_cls));
 #else
   Varray<T1> src_cls(max_cls);
   Varray<double> src_weights(max_cls);
diff --git a/src/table.cc b/src/table.cc
index b5fd1fbf2c8362461f8300304fa882de6530b987..7c48d2be38b38640862b1f8ee751958fff7acdd9 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -40,4 +40,21 @@ define_table(const std::string &tablearg)
   return tableID;
 }
 
+std::string
+predefined_tables(int p_padding)
+{
+  const char *name;
+  constexpr int id_padding = 4;
+  int padding = p_padding + id_padding;
+  int numTables = tableInqNumber();
+  std::string tables{ "Predefined tables: " };
+  for (int id = 0; id < numTables; id++)
+    {
+      if (id % 7 == 6) tables += std::string("\n") + std::string(padding, ' ');
+      if ((name = tableInqNamePtr(id))) tables += std::string(name);
+      if (id < numTables - 1) tables += ",";
+    }
+  return tables;
+}
+
 }  // namespace cdo
diff --git a/src/table.h b/src/table.h
index 6630436b47a022e4575b218c56c1bba555f86850..07d53b8da897e193138caee49dfb2d343ae404fe 100644
--- a/src/table.h
+++ b/src/table.h
@@ -7,7 +7,8 @@ namespace cdo
 {
 
 int define_table(const std::string &tablearg);
+std::string predefined_tables(int p_padding);
 
-}
+}  // namespace cdo
 
 #endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0e0a5545cf17e6416c9dc331e002a75169a683bc..d2de7728c8ee760232a777d86b4e2c692107d5e0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,2 +1,2 @@
-add_subdirectory(bandit_tests)
 add_subdirectory(pytest)
+add_subdirectory(bandit_tests)
diff --git a/test/bandit_tests/CMakeLists.txt b/test/bandit_tests/CMakeLists.txt
index 72845b4b82bb9cb3b093903d05bdf16413177df5..65e74144c5420e93d2f69a50fc4d9a530d679121 100644
--- a/test/bandit_tests/CMakeLists.txt
+++ b/test/bandit_tests/CMakeLists.txt
@@ -14,7 +14,7 @@ add_executable(test_param_conversion_test param_conversion_test.cc)
 add_executable(test_pmlist                pmlist.cc)
 add_executable(test_util_string           util_string.cc)
 add_executable(test_wildcards             wildcards.cc)
-add_executable(test_operator_args         operator_args.cc)
+#add_executable(test_operator_args         operator_args.cc)
 
 set(labels_test_wildcards ENABLE_ON_HAVE_WORDEXP)