# Help to generate code

**URL:** <https://discourse.julialang.org/t/help-to-generate-code/27935>\
**Category:** General Usage\
**Created:** [August 24, 2019, 1:29pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935 "2019-08-24T13:29:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 24, 2019, 1:29pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/1 "2019-08-24T13:29:08Z")

</div>

Dear community,  
I think I have a good use case for the learning of metaprogramming. I want to generate this code:

```julia
        for problem in get_problems(analysis)
            for element in get_elements(problem)
                for ip in get_integration_points(element)
                    material = ip("material", time)
                    material_preprocess_increment!(material, element, ip, time)
                end
            end
        end

```

for example using lines:

```julia
@integrate_material material_preprocess_analysis! 
@integrate_material material_preprocess_increment!
@integrate_material material_preprocess_iteration!

```

The original block of code is repeated multiple times, [here it is in use](https://github.com/JuliaFEM/FEMMaterials.jl/blob/70593ea4535a54fb6080cf1ecaad943e50694aee/src/mecamatso.jl#L295-L302).

I read here: [Metaprogramming · The Julia Language](https://docs.julialang.org/en/v1/manual/metaprogramming/index.html) and here: [http://mikeinnes.github.io/MacroTools.jl/stable/](http://mikeinnes.github.io/MacroTools.jl/stable/), but I couldn’t figure out how to start also if someone can propose the right way of working document or idea.

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 24, 2019, 2:06pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/2 "2019-08-24T14:06:44Z")

</div>

If you’re repeating code multiple times with just a different function `f` being called in the innermost loop, why not extract it out into a function that takes `f` as an argument?

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 24, 2019, 6:25pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/3 "2019-08-24T18:25:57Z")

</div>

Thanks. I was fixed to the macro idea and didn’t see an obvious solutions. Here is my closure:

```julia
    function operate_integration_points!(func!, time)
        for problem in get_problems(analysis)
            for element in get_elements(problem)
                for ip in get_integration_points(element)
                    if string(func!) == "FEMMaterials.material_preprocess_analysis!"
                        material_type = getfield(Materials, problem.properties.material_model)
                        material = Material(material_type, tuple())
                        ip.fields["material"] = field(material)
                        func!(material, element, ip, time)
                    else
                        material = ip("material", time)
                        func!(material, element, ip, time)
                    end
                end
            end
        end
    end

```

All comments welcome, I’m just learning. I have opened a pull request here: [https://github.com/JuliaFEM/FEMMaterials.jl/pull/7](https://github.com/JuliaFEM/FEMMaterials.jl/pull/7)

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 24, 2019, 6:44pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/4 "2019-08-24T18:44:21Z")

</div>

> [@Tero\_Frondelius](#):
>
> `string(func!) == "FEMMaterials.material_preprocess_analysis!"`

Actually, this comparison fails in julia 1.2. What would be the right way to do it?

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 24, 2019, 8:12pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/5 "2019-08-24T20:12:49Z")

</div>

I found a solution:

```julia
func_name = last(split(string(func!),"."))
if func_name == "material_preprocess_analysis!"

```

It seems that julia 1.0 and 1.1 returns full name with module and julia 1.2 just the method name.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 24, 2019, 9:41pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/6 "2019-08-24T21:41:47Z")

</div>

I think everything would be cleaner if your higher-order function was responsible only for factorizing the code that can be factorized everywhere (and not more). This would avoid the need for a test within the nested loops.

For example:

```julia
function operate_integration_points!(f, time)
    for problem in get_problems(analysis)
        for element in get_elements(problem)
            for ip in get_integration_points(element)
                f(problem, element, ip, time)
            end
        end
    end
end

```

If you do this, the function `f` passed as argument should now be responsible for determining the `material` from other arguments. In the specific case of `material_preprocess_analysis!`, this would look like

```julia
function material_preprocess_analysis_aux!(problem, element, ip, time)
    material_type = getfield(Materials, problem.properties.material_model)
    material = Material(material_type, tuple())
    ip.fields["material"] = field(material)
    material_preprocess_analysis!(material, element, ip, time)
end

operate_integration_points!(material_preprocess_analysis_aux!, time)

```

while in the general case, you would have:

```julia
function material_preprocess_increment_aux!(problem, element, ip, time)
    material = ip("material", time)
    material_preprocess_increment!(material, element, ip, time)
end

operate_integration_points!(material_preprocess_increment_aux!, time)

```

Now, instead of defining auxilliary functions, you might want to use Julia’s special `do` syntax. The last block of code above could be written instead like this:

```julia
operate_integration_points!(time) do problem, element, ip, time
    material = ip("material", time)
    material_preprocess_increment!(material, element, ip, time)
end

```

Finally, if you have many preprocessing functions which fall in the general case, and you want to factor out the logic of getting the material first, before calling the preprocessing step on it, you can use something like this:

```julia
aux(preprocess!) = (problem, element, ip, time) -> begin
    material = ip("material", time)
    preprocess!(material, element, ip, time)
end

operate_integration_points!(aux(material_preprocess_increment!), time)
operate_integration_points!(aux(material_preprocess_iteration!), time)

```

Does this make sense?

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 25, 2019, 11:28am UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/7 "2019-08-25T11:28:04Z")

</div>

> [@ffevotte](#):
>
> Does this make sense?

Yes, thanks for the good ideas. This is performance critical code and we yet don’t have performance tests. Is there any differences in performance (which you can say without testing)?

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 25, 2019, 10:07pm UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/8 "2019-08-25T22:07:23Z")

</div>

There should not be any performance difference.

However, thanks to `BenchmarkTools.jl`, such things are really easy to check by yourself. So I would advise you to

1. hand-write write one nested loop like this _(you already have it IIUC)_
2. create a realistically large test case for it _(this is where you perhaps have work to do, but you’ll have to do it at some point anyway: better do it early)_
3. benchmark it _(almost no work involved)_
4. transform it using higher-order functions like explained above _(this is what you’re working on anyway)_
5. if benchmark performance does not degrade generalize the approach to all `preprocess_*`functions

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [August 26, 2019, 5:09am UTC](https://discourse.julialang.org/t/help-to-generate-code/27935/9 "2019-08-26T05:09:19Z")

</div>

Thanks a lot. I am just learning the structure, but my current understanding is that all of the preprocessing functions are empty. They are generalized developer API, which gives hooks to all phases of material integration. This way material model development is disconnected from FEM solver development.

Thus I am expecting compiler to throw away most of the code most of the cases. Only challenge is that remaining code is always in the hot loop.

I hope my explanation make sense, but I got the answer I was waiting for: no differences in performance just in readability/code elegance.
